diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 0b2fd4bba26a2ba6056a83a631873a2b0b118bab..410e1fac786979f42977b3fa67713fa2e555a645 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -130,26 +130,66 @@ QList<Symbol *> LookupContext::resolveQualifiedNameId(QualifiedNameId *q, const QList<Scope *> &visibleScopes, ResolveMode mode) const { - QList<Scope *> scopes; + QList<Symbol *> candidates; - if (q->nameCount() == 1) - scopes = visibleScopes; // ### handle global scope lookup - else - scopes = resolveNestedNameSpecifier(q, visibleScopes); + for (int i = 0; i < visibleScopes.size(); ++i) { + Scope *scope = visibleScopes.at(i); - QList<Scope *> expanded; - foreach (Scope *scope, scopes) { - expanded.append(scope); + for (Symbol *symbol = scope->lookat(q); symbol; symbol = symbol->next()) { + if (! symbol->name()) + continue; - for (unsigned i = 0; i < scope->symbolCount(); ++i) { - Symbol *member = scope->symbolAt(i); + QualifiedNameId *qq = symbol->name()->asQualifiedNameId(); - if (ScopedSymbol *scopedSymbol = member->asScopedSymbol()) - expandEnumOrAnonymousSymbol(scopedSymbol, &expanded); + if (! qq) + continue; + else if (! maybeValidSymbol(symbol, mode, candidates)) + continue; + + if (! q->unqualifiedNameId()->isEqualTo(qq->unqualifiedNameId())) + continue; + + else if (qq->nameCount() == q->nameCount()) { + unsigned j = 0; + + for (; j < q->nameCount(); ++j) { + Name *classOrNamespaceName1 = q->nameAt(j); + Name *classOrNamespaceName2 = qq->nameAt(j); + + if (! classOrNamespaceName1->isEqualTo(classOrNamespaceName2)) + break; + } + + if (j == q->nameCount()) + candidates.append(symbol); + } } } - return resolve(q->unqualifiedNameId(), expanded, mode); + if (candidates.isEmpty()) { + QList<Scope *> scopes; + + if (q->nameCount() == 1) + scopes = visibleScopes; // ### handle global scope lookup + else + scopes = resolveNestedNameSpecifier(q, visibleScopes); + + QList<Scope *> expanded; + foreach (Scope *scope, scopes) { + expanded.append(scope); + + for (unsigned i = 0; i < scope->symbolCount(); ++i) { + Symbol *member = scope->symbolAt(i); + + if (ScopedSymbol *scopedSymbol = member->asScopedSymbol()) + expandEnumOrAnonymousSymbol(scopedSymbol, &expanded); + } + } + + candidates += resolve(q->unqualifiedNameId(), expanded, mode); + } + + return candidates; } QList<Symbol *> LookupContext::resolveOperatorNameId(OperatorNameId *opId, @@ -198,13 +238,11 @@ QList<Symbol *> LookupContext::resolve(Name *name, const QList<Scope *> &visible else if (! maybeValidSymbol(symbol, mode, candidates)) continue; // skip it, we're not looking for this kind of symbols - else if (Identifier *symbolId = symbol->identifier()) { if (! symbolId->isEqualTo(id)) continue; // skip it, the symbol's id is not compatible with this lookup. } - if (QualifiedNameId *q = symbol->name()->asQualifiedNameId()) { if (name->isDestructorNameId() != q->unqualifiedNameId()->isDestructorNameId()) diff --git a/src/shared/cplusplus/Scope.cpp b/src/shared/cplusplus/Scope.cpp index 6c910c072c6fee8d7b1ae9642ff8ce544356b6d8..fcb5a68027cd80c317c3f9da376fe5aa5eea8ffa 100644 --- a/src/shared/cplusplus/Scope.cpp +++ b/src/shared/cplusplus/Scope.cpp @@ -208,6 +208,21 @@ void Scope::enterSymbol(Symbol *symbol) } } +Symbol *Scope::lookat(Name *name) const +{ + if (! name) + return 0; + + else if (OperatorNameId *opId = name->asOperatorNameId()) + return lookat(opId->kind()); + + else if (Identifier *id = name->identifier()) + return lookat(id); + + else + return 0; +} + Symbol *Scope::lookat(Identifier *id) const { if (! _hash || ! id) diff --git a/src/shared/cplusplus/Scope.h b/src/shared/cplusplus/Scope.h index 5fb9eb3ac7caa768d7547bad7956712db2c3391b..1abc41530df381cebbf5f1626812f81d2a0c7784 100644 --- a/src/shared/cplusplus/Scope.h +++ b/src/shared/cplusplus/Scope.h @@ -129,6 +129,7 @@ public: /// Returns the last Symbol in the scope. iterator lastSymbol() const; + Symbol *lookat(Name *name) const; Symbol *lookat(Identifier *id) const; Symbol *lookat(int operatorId) const;