diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/DeclBase.cpp | 16 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 42 |
2 files changed, 38 insertions, 20 deletions
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 34bc2b97e3..8d16139fcd 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -420,6 +420,22 @@ void DeclContext::DestroyDecls(ASTContext &C) { (*D++)->Destroy(C); } +/// \brief Find the parent context of this context that will be +/// used for unqualified name lookup. +/// +/// Generally, the parent lookup context is the semantic context. However, for +/// a friend function the parent lookup context is the lexical context, which +/// is the class in which the friend is declared. +DeclContext *DeclContext::getLookupParent() { + // FIXME: Find a better way to identify friends + if (isa<FunctionDecl>(this)) + if (getParent()->getLookupContext()->isFileContext() && + getLexicalParent()->getLookupContext()->isRecord()) + return getLexicalParent(); + + return getParent(); +} + bool DeclContext::isDependentContext() const { if (isFileContext()) return false; diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 44c76a86e0..67674206fb 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -636,6 +636,15 @@ static bool isNamespaceOrTranslationUnitScope(Scope *S) { return false; } +// Find the next outer declaration context corresponding to this scope. +static DeclContext *findOuterContext(Scope *S) { + for (S = S->getParent(); S; S = S->getParent()) + if (S->getEntity()) + return static_cast<DeclContext *>(S->getEntity())->getPrimaryContext(); + + return 0; +} + std::pair<bool, Sema::LookupResult> Sema::CppLookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind, bool RedeclarationOnly) { @@ -694,30 +703,23 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, } if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) { LookupResult R; - // Perform member lookup into struct. - // FIXME: In some cases, we know that every name that could be found by - // this qualified name lookup will also be on the identifier chain. For - // example, inside a class without any base classes, we never need to - // perform qualified lookup because all of the members are on top of the - // identifier chain. - if (isa<RecordDecl>(Ctx)) { + + DeclContext *OuterCtx = findOuterContext(S); + for (; Ctx && Ctx->getPrimaryContext() != OuterCtx; + Ctx = Ctx->getLookupParent()) { + if (Ctx->isFunctionOrMethod()) + continue; + + // Perform qualified name lookup into this context. + // FIXME: In some cases, we know that every name that could be found by + // this qualified name lookup will also be on the identifier chain. For + // example, inside a class without any base classes, we never need to + // perform qualified lookup because all of the members are on top of the + // identifier chain. R = LookupQualifiedName(Ctx, Name, NameKind, RedeclarationOnly); if (R) return std::make_pair(true, R); } - if (Ctx->getParent() != Ctx->getLexicalParent() - || isa<CXXMethodDecl>(Ctx)) { - // It is out of line defined C++ method or struct, we continue - // doing name lookup in parent context. Once we will find namespace - // or translation-unit we save it for possible checking - // using-directives later. - for (OutOfLineCtx = Ctx; OutOfLineCtx && !OutOfLineCtx->isFileContext(); - OutOfLineCtx = OutOfLineCtx->getParent()) { - R = LookupQualifiedName(OutOfLineCtx, Name, NameKind, RedeclarationOnly); - if (R) - return std::make_pair(true, R); - } - } } } |