Commit adfdb516 authored by Roberto Raggi's avatar Roberto Raggi

Recursive definition of CPlusPlus::QualifiedNameId.

Done-with: Erik Verbruggen
parent 94264617
......@@ -256,27 +256,48 @@ private:
_type = control()->namedType(templId);
}
virtual void visit(const QualifiedNameId *name)
const Name *instantiate(const Name *name)
{
QVarLengthArray<const Name *, 8> names(name->nameCount());
for (unsigned i = 0; i < name->nameCount(); ++i) {
const Name *n = name->nameAt(i);
if (const TemplateNameId *templId = n->asTemplateNameId()) {
QVarLengthArray<FullySpecifiedType, 8> arguments(templId->templateArgumentCount());
for (unsigned templateArgIndex = 0; templateArgIndex < templId->templateArgumentCount(); ++templateArgIndex) {
FullySpecifiedType argTy = templId->templateArgumentAt(templateArgIndex);
arguments[templateArgIndex] = q->apply(argTy);
}
n = control()->templateNameId(templId->identifier(), arguments.data(), arguments.size());
if (! name)
return name;
else if (const Name *nameId = name->asNameId()) {
const Identifier *id = control()->findOrInsertIdentifier(nameId->identifier()->chars(),
nameId->identifier()->size());
return control()->nameId(id);
} else if (const TemplateNameId *templId = name->asTemplateNameId()) {
QVarLengthArray<FullySpecifiedType, 8> arguments(templId->templateArgumentCount());
for (unsigned templateArgIndex = 0; templateArgIndex < templId->templateArgumentCount(); ++templateArgIndex) {
FullySpecifiedType argTy = templId->templateArgumentAt(templateArgIndex);
arguments[templateArgIndex] = q->apply(argTy);
}
const Identifier *id = control()->findOrInsertIdentifier(templId->identifier()->chars(),
templId->identifier()->size());
return control()->templateNameId(id, arguments.data(), arguments.size());
} else if (const QualifiedNameId *qq = name->asQualifiedNameId()) {
const Name *base = instantiate(qq->base());
const Name *name = instantiate(qq->name());
return control()->qualifiedNameId(base, name);
} else if (const OperatorNameId *op = name->asOperatorNameId()) {
return control()->operatorNameId(op->kind());
} else if (const ConversionNameId *c = name->asConversionNameId()) {
FullySpecifiedType ty = q->apply(c->type());
return control()->conversionNameId(ty);
names[i] = n;
}
const QualifiedNameId *q = control()->qualifiedNameId(names.data(), names.size(), name->isGlobal());
_type = control()->namedType(q);
return 0;
}
virtual void visit(const QualifiedNameId *name)
{
if (const Name *n = instantiate(name))
_type = control()->namedType(n);
}
virtual void visit(const DestructorNameId *name)
......
......@@ -47,6 +47,18 @@ namespace {
using namespace CPlusPlus;
static void addNames(const Name *name, QList<const Name *> *names)
{
if (! name)
return;
else if (name->isNameId() || name->isTemplateNameId())
names->append(name);
else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
addNames(q->base(), names);
addNames(q->name(), names);
}
}
static void fullyQualifiedName_helper(Symbol *symbol, QList<const Name *> *names)
{
if (! symbol)
......@@ -56,23 +68,16 @@ static void fullyQualifiedName_helper(Symbol *symbol, QList<const Name *> *names
if (symbol->name()) {
if (symbol->isClass() || symbol->isNamespace()) {
if (const QualifiedNameId *q = symbol->name()->asQualifiedNameId()) {
for (unsigned i = 0; i < q->nameCount(); ++i)
names->append(q->nameAt(i));
addNames(symbol->name(), names);
} else if (symbol->name()->isNameId() || symbol->name()->isTemplateNameId()) {
names->append(symbol->name());
}
} else if (symbol->isObjCClass() || symbol->isObjCBaseClass() || symbol->isObjCProtocol()
|| symbol->isObjCForwardClassDeclaration() || symbol->isObjCForwardProtocolDeclaration()
|| symbol->isForwardClassDeclaration()) {
if (symbol->name())
names->append(symbol->name());
addNames(symbol->name(), names);
} else if (symbol->isFunction()) {
if (const QualifiedNameId *q = symbol->name()->asQualifiedNameId()) {
for (unsigned i = 0; i < q->nameCount() - 1; ++i)
names->append(q->nameAt(i));
}
if (const QualifiedNameId *q = symbol->name()->asQualifiedNameId())
addNames(q->base(), names);
}
}
}
......@@ -142,6 +147,9 @@ const Name *LookupContext::minimalName(const Name *name,
Scope *source,
ClassOrNamespace *target) const
{
qWarning() << "TODO:" << Q_FUNC_INFO;
#if 0
Q_ASSERT(name);
Q_ASSERT(source);
Q_ASSERT(target);
......@@ -153,7 +161,7 @@ const Name *LookupContext::minimalName(const Name *name,
Symbol *canonicalSymbol = symbols.first();
std::vector<const Name *> fqNames = fullyQualifiedName(canonicalSymbol).toVector().toStdVector();
if (const QualifiedNameId *qId = name->asQualifiedNameId())
fqNames.push_back(qId->nameAt(qId->nameCount() - 1));
fqNames.push_back(qId->name());
else
fqNames.push_back(name);
......@@ -172,6 +180,8 @@ const Name *LookupContext::minimalName(const Name *name,
return lastWorking->nameAt(0);
else
return lastWorking;
#endif
return 0;
}
......@@ -396,21 +406,11 @@ QList<Symbol *> ClassOrNamespace::lookup_helper(const Name *name, bool searchInE
if (name) {
if (const QualifiedNameId *q = name->asQualifiedNameId()) {
ClassOrNamespace *binding = this;
if (q->isGlobal())
binding = globalNamespace();
if (q->nameCount() == 1)
return binding->find(q->unqualifiedNameId());
binding = binding->lookupType(q->nameAt(0));
for (unsigned index = 1; binding && index < q->nameCount() - 1; ++index)
binding = binding->findType(q->nameAt(index));
if (! q->base())
result = globalNamespace()->find(q->name());
if (binding)
result = binding->find(q->unqualifiedNameId());
else if (ClassOrNamespace *binding = lookupType(q->base()))
result = binding->find(q->name());
return result;
}
......@@ -533,17 +533,14 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
bool searchInEnclosingScope)
{
if (const QualifiedNameId *q = name->asQualifiedNameId()) {
ClassOrNamespace *e = this;
if (q->isGlobal())
e = globalNamespace();
if (! q->base())
return globalNamespace()->findType(q->name());
e = e->lookupType(q->nameAt(0));
else if (ClassOrNamespace *binding = lookupType(q->base()))
return binding->findType(q->name());
for (unsigned index = 1; e && index < q->nameCount(); ++index)
e = e->findType(q->nameAt(index));
return e;
return 0;
} else if (! processed->contains(this)) {
processed->insert(this);
......@@ -653,12 +650,10 @@ ClassOrNamespace *ClassOrNamespace::findOrCreateType(const Name *name)
return this;
if (const QualifiedNameId *q = name->asQualifiedNameId()) {
ClassOrNamespace *e = this;
if (! q->base())
return globalNamespace()->findOrCreateType(q->name());
for (unsigned i = 0; e && i < q->nameCount(); ++i)
e = e->findOrCreateType(q->nameAt(i));
return e;
return findOrCreateType(q->base())->findOrCreateType(q->name());
} else if (name->isNameId() || name->isTemplateNameId()) {
ClassOrNamespace *e = nestedType(name);
......@@ -871,7 +866,7 @@ bool CreateBindings::visit(UsingDeclaration *u)
{
if (u->name()) {
if (const QualifiedNameId *q = u->name()->asQualifiedNameId()) {
if (const NameId *unqualifiedId = q->unqualifiedNameId()->asNameId()) {
if (const NameId *unqualifiedId = q->name()->asNameId()) {
if (ClassOrNamespace *delegate = _currentClassOrNamespace->lookupType(q)) {
ClassOrNamespace *b = _currentClassOrNamespace->findOrCreateType(unqualifiedId);
b->addUsing(delegate);
......
......@@ -246,14 +246,10 @@ void NamePrettyPrinter::visit(const ConversionNameId *name)
void NamePrettyPrinter::visit(const QualifiedNameId *name)
{
if (name->isGlobal())
_name += QLatin1String("::");
for (unsigned index = 0; index < name->nameCount(); ++index) {
if (index != 0)
_name += QLatin1String("::");
_name += operator()(name->nameAt(index));
}
if (name->base())
_name += operator()(name->base());
_name += QLatin1String("::");
_name += operator()(name->name());
}
void NamePrettyPrinter::visit(const SelectorNameId *name)
......
......@@ -221,11 +221,10 @@ bool ResolveExpression::visit(NewExpressionAST *ast)
bool ResolveExpression::visit(TypeidExpressionAST *)
{
const Name *std_type_info[2];
std_type_info[0] = control()->nameId(control()->findOrInsertIdentifier("std"));
std_type_info[1] = control()->nameId(control()->findOrInsertIdentifier("type_info"));
const Name *stdName = control()->nameId(control()->findOrInsertIdentifier("std"));
const Name *tiName = control()->nameId(control()->findOrInsertIdentifier("type_info"));
const Name *q = control()->qualifiedNameId(control()->qualifiedNameId(/* :: */ 0, stdName), tiName);
const Name *q = control()->qualifiedNameId(std_type_info, 2, /*global=*/ true);
FullySpecifiedType ty(control()->namedType(q));
addResult(ty, _scope);
......@@ -314,14 +313,11 @@ void ResolveExpression::thisObject()
addResult(ptrTy, fun->scope());
break;
} else if (const QualifiedNameId *q = fun->name()->asQualifiedNameId()) {
const Name *nestedNameSpecifier = 0;
if (q->nameCount() == 1 && q->isGlobal())
nestedNameSpecifier = q->nameAt(0);
else
nestedNameSpecifier = control()->qualifiedNameId(q->names(), q->nameCount() - 1);
FullySpecifiedType classTy(control()->namedType(nestedNameSpecifier));
FullySpecifiedType ptrTy(control()->pointerType(classTy));
addResult(ptrTy, fun->scope());
if (q->base()) {
FullySpecifiedType classTy(control()->namedType(q->base()));
FullySpecifiedType ptrTy(control()->pointerType(classTy));
addResult(ptrTy, fun->scope());
}
break;
}
}
......
......@@ -117,8 +117,8 @@ protected:
return;
} else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
for (unsigned i = 0; i < q->nameCount(); ++i)
addType(q->nameAt(i));
addType(q->base());
addType(q->name());
} else if (name->isNameId() || name->isTemplateNameId()) {
addType(name->identifier());
......
......@@ -535,7 +535,7 @@ protected:
{
const Name *name = function->name();
if (const QualifiedNameId *q = name->asQualifiedNameId())
name = q->unqualifiedNameId();
name = q->name();
if (_declarationName->isEqualTo(name))
_functions->append(function);
......
......@@ -200,7 +200,7 @@ protected:
{ _item = newCompletionItem(name); }
virtual void visit(const QualifiedNameId *name)
{ _item = newCompletionItem(name->unqualifiedNameId()); }
{ _item = newCompletionItem(name->name()); }
};
struct CompleteFunctionDeclaration
......
......@@ -96,10 +96,9 @@ bool SearchSymbols::visit(Function *symbol)
QString extraScope;
if (const Name *name = symbol->name()) {
if (const QualifiedNameId *nameId = name->asQualifiedNameId()) {
if (nameId->nameCount() > 1) {
extraScope = overview.prettyName(nameId->nameAt(nameId->nameCount() - 2));
}
if (const QualifiedNameId *q = name->asQualifiedNameId()) {
if (q->base())
extraScope = overview.prettyName(q->base());
}
}
QString fullScope = _scope;
......
......@@ -870,35 +870,31 @@ bool CheckDeclaration::visit(QtPropertyDeclarationAST *ast)
return false;
}
void CheckDeclaration::checkQEnumsQFlagsNames(NameListAST *nameListAst,
const char *declName)
static bool checkEnumName(const Name *name)
{
for (NameListAST *iter = nameListAst; iter; iter = iter->next) {
if (! name)
return false;
const Name *name = semantic()->check(iter->value, _scope);
if (!name)
continue;
else if (name->asNameId() != 0)
return true;
if (name->isNameId())
continue;
else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
if (! q->base())
return false; // global qualified name
const QualifiedNameId *qName = name->asQualifiedNameId();
if (!qName)
translationUnit()->error(iter->firstToken(), "invalid name in %s",
declName);
else if (qName->isGlobal())
translationUnit()->error(iter->firstToken(),
"invalid name '%s' in %s",
qName->identifier()->chars(), declName);
else {
for (unsigned i = 0; i < qName->nameCount(); ++i) {
const Name *namePart = qName->nameAt(i);
if (!namePart || !namePart->isNameId()) {
translationUnit()->error(iter->firstToken(),
"invalid name '%s' in %s",
qName->identifier()->chars(), declName);
}
}
if (checkEnumName(q->base()) && checkEnumName(q->name()))
return true;
}
return false;
}
void CheckDeclaration::checkQEnumsQFlagsNames(NameListAST *nameListAst, const char *declName)
{
for (NameListAST *iter = nameListAst; iter; iter = iter->next) {
if (const Name *name = semantic()->check(iter->value, _scope)) {
if (! checkEnumName(name))
translationUnit()->error(iter->firstToken(), "invalid name in %s", declName);
}
}
}
......@@ -87,15 +87,15 @@ const Name *CheckName::check(NestedNameSpecifierListAST *nested_name_specifier_l
const Name *previousName = switchName(0);
Scope *previousScope = switchScope(scope);
std::vector<const Name *> names;
for (NestedNameSpecifierListAST *it = nested_name_specifier_list; it; it = it->next) {
NestedNameSpecifierAST *nested_name_specifier = it->value;
names.push_back(semantic()->check(nested_name_specifier->class_or_namespace_name, _scope));
const Name *n = semantic()->check(nested_name_specifier->class_or_namespace_name, _scope);
if (! _name)
_name = n;
else
_name = control()->qualifiedNameId(_name, n);
}
if (! names.empty())
_name = control()->qualifiedNameId(&names[0], names.size());
(void) switchScope(previousScope);
return switchName(previousName);
}
......@@ -127,13 +127,20 @@ Scope *CheckName::switchScope(Scope *scope)
bool CheckName::visit(QualifiedNameAST *ast)
{
std::vector<const Name *> names;
for (NestedNameSpecifierListAST *it = ast->nested_name_specifier_list; it; it = it->next) {
NestedNameSpecifierAST *nested_name_specifier = it->value;
names.push_back(semantic()->check(nested_name_specifier->class_or_namespace_name, _scope));
const Name *n = semantic()->check(nested_name_specifier->class_or_namespace_name, _scope);
if (_name || ast->global_scope_token)
_name = control()->qualifiedNameId(_name, n);
else
_name = n;
}
names.push_back(semantic()->check(ast->unqualified_name, _scope));
_name = control()->qualifiedNameId(&names[0], names.size(), ast->global_scope_token != 0);
const Name *n = semantic()->check(ast->unqualified_name, _scope);
if (_name || ast->global_scope_token)
_name = control()->qualifiedNameId(_name, n);
else
_name = n;
ast->name = _name;
return false;
......
......@@ -177,11 +177,10 @@ template <> struct Compare<QualifiedNameId>
{
bool operator()(const QualifiedNameId &name, const QualifiedNameId &otherName) const
{
if (name.isGlobal() == otherName.isGlobal())
return std::lexicographical_compare(name.firstName(), name.lastName(),
otherName.firstName(), otherName.lastName());
if (name.base() == otherName.base())
return name.name() < otherName.name();
return name.isGlobal() < otherName.isGlobal();
return name.base() < otherName.base();
}
};
......@@ -285,10 +284,9 @@ public:
return conversionNameIds.intern(ConversionNameId(type));
}
template <typename _Iterator>
const QualifiedNameId *findOrInsertQualifiedNameId(_Iterator first, _Iterator last, bool isGlobal)
const QualifiedNameId *findOrInsertQualifiedNameId(const Name *base, const Name *name)
{
return qualifiedNameIds.intern(QualifiedNameId(first, last, isGlobal));
return qualifiedNameIds.intern(QualifiedNameId(base, name));
}
template <typename _Iterator>
......@@ -641,11 +639,9 @@ const OperatorNameId *Control::operatorNameId(int kind)
const ConversionNameId *Control::conversionNameId(const FullySpecifiedType &type)
{ return d->findOrInsertConversionNameId(type); }
const QualifiedNameId *Control::qualifiedNameId(const Name *const *names,
unsigned nameCount,
bool isGlobal)
const QualifiedNameId *Control::qualifiedNameId(const Name *base, const Name *name)
{
return d->findOrInsertQualifiedNameId(names, names + nameCount, isGlobal);
return d->findOrInsertQualifiedNameId(base, name);
}
const SelectorNameId *Control::selectorNameId(const Name *const *names,
......
......@@ -83,9 +83,7 @@ public:
const ConversionNameId *conversionNameId(const FullySpecifiedType &type);
/// Returns the canonical qualified name id.
const QualifiedNameId *qualifiedNameId(const Name *const *names,
unsigned nameCount,
bool isGlobal = false);
const QualifiedNameId *qualifiedNameId(const Name *base, const Name *name);
const SelectorNameId *selectorNameId(const Name *const *names,
unsigned nameCount,
......
......@@ -298,11 +298,11 @@ bool NamedType::isEqualTo(const Type *other) const
const Name *name = _name;
if (const QualifiedNameId *q = name->asQualifiedNameId())
name = q->unqualifiedNameId();
name = q->name();
const Name *otherName = o->name();
if (const QualifiedNameId *q = otherName->asQualifiedNameId())
otherName = q->unqualifiedNameId();
otherName = q->name();
return name->isEqualTo(otherName);
}
......
......@@ -63,48 +63,29 @@ void QualifiedNameId::accept0(NameVisitor *visitor) const
const Identifier *QualifiedNameId::identifier() const
{
if (const Name *u = unqualifiedNameId())
if (const Name *u = name())
return u->identifier();
return 0;
}
unsigned QualifiedNameId::nameCount() const
{ return _names.size(); }
const Name *QualifiedNameId::nameAt(unsigned index) const
{ return _names[index]; }
bool QualifiedNameId::isGlobal() const
{ return _isGlobal; }
const Name *QualifiedNameId::unqualifiedNameId() const
{
if (_names.empty())
return 0;
const Name *QualifiedNameId::base() const
{ return _base; }
return _names.back();
}
const Name *QualifiedNameId::name() const
{ return _name; }
bool QualifiedNameId::isEqualTo(const Name *other) const
{
const QualifiedNameId *q = other->asQualifiedNameId();
if (! q)
return false;
else if (isGlobal() != q->isGlobal())
return false;
else {
const unsigned count = nameCount();
if (count != q->nameCount())
return false;
for (unsigned i = 0; i < count; ++i) {
const Name *l = nameAt(i);
const Name *r = q->nameAt(i);
if (! l->isEqualTo(r))
return false;
if (const QualifiedNameId *q = other->asQualifiedNameId()) {
if (_base == q->_base || (_base && _base->isEqualTo(q->_base))) {
if (_name == q->_name || (_name && _name->isEqualTo(q->_name))) {
return true;
}
}
}
return true;
return false;
}
NameId::NameId(const Identifier *identifier)
......
......@@ -59,36 +59,27 @@ namespace CPlusPlus {
class CPLUSPLUS_EXPORT QualifiedNameId: public Name
{
public:
template <typename _Iterator>
QualifiedNameId(_Iterator first, _Iterator last, bool isGlobal = false)
: _names(first, last), _isGlobal(isGlobal) {}
QualifiedNameId(const Name *base, const Name *name)
: _base(base), _name(name) {}
virtual ~QualifiedNameId();
virtual const Identifier *identifier() const;
unsigned nameCount() const;
const Name *nameAt(unsigned index) const;
const Name *unqualifiedNameId() const;
const Name *const *names() const { return &_names[0]; } // ### remove me
bool isGlobal() const;
const Name *base() const;
const Name *name() const;
virtual bool isEqualTo(const Name *other) const;
virtual const QualifiedNameId *asQualifiedNameId() const
{ return this; }
typedef std::vector<const Name *>::const_iterator NameIterator;
NameIterator firstName() const { return _names.begin(); }
NameIterator lastName() const { return _names.end(); }
protected:
virtual void accept0(NameVisitor *visitor) const;
private:
std::vector<const Name *> _names;
bool _isGlobal;
const Name *_base;
const Name *_name;
};
class CPLUSPLUS_EXPORT NameId: public Name
......
......@@ -101,7 +101,7 @@ protected:
{ _value = 0; } // ### TODO: implement me
virtual void visit(const QualifiedNameId *name)
{ _value = operator()(name->unqualifiedNameId()); }
{ _value = operator()(name->name()); }
virtual void visit(const SelectorNameId *name)
{ _value = name->identifier()->hashCode(); }
......@@ -110,56 +110,6 @@ private:
unsigned _value;
};
class Symbol::IdentityForName: protected NameVisitor
{
public:
IdentityForName()