diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-12-14 16:03:29 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-12-14 16:03:29 +0000 |
commit | 553689148f546783e127749438bf6d7806e6bb1d (patch) | |
tree | 438e4a5e2d383b74603984df6e54f714f62771f2 /lib/Sema/SemaLookup.cpp | |
parent | 80fb7dd8e0c56632dc68f5864f70abb2fde0e1df (diff) |
When name lookup comes across a declaration that is in a module that
is not visible, look for any previous declarations of that entity that
might be visible.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146563 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaLookup.cpp')
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 83 |
1 files changed, 63 insertions, 20 deletions
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 9f1e9a5516..a6ad8f8fcf 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -321,6 +321,12 @@ void LookupResult::deletePaths(CXXBasePaths *Paths) { delete Paths; } +static NamedDecl *getVisibleDecl(NamedDecl *D); + +NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const { + return getVisibleDecl(D); +} + /// Resolves the result kind of this lookup. void LookupResult::resolveKind() { unsigned N = Decls.size(); @@ -649,7 +655,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { DeclContext::lookup_const_iterator I, E; for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) { NamedDecl *D = *I; - if (R.isAcceptableDecl(D)) { + if ((D = R.getAcceptableDecl(D))) { R.addDecl(D); Found = true; } @@ -875,9 +881,9 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // Check whether the IdResolver has anything in this scope. bool Found = false; for (; I != IEnd && S->isDeclScope(*I); ++I) { - if (R.isAcceptableDecl(*I)) { + if (NamedDecl *ND = R.getAcceptableDecl(*I)) { Found = true; - R.addDecl(*I); + R.addDecl(ND); } } if (Found) { @@ -926,8 +932,8 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable( Name.getAsIdentifierInfo(), ClassDeclared)) { - if (R.isAcceptableDecl(Ivar)) { - R.addDecl(Ivar); + if (NamedDecl *ND = R.getAcceptableDecl(Ivar)) { + R.addDecl(ND); R.resolveKind(); return true; } @@ -977,13 +983,13 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // Check whether the IdResolver has anything in this scope. bool Found = false; for (; I != IEnd && S->isDeclScope(*I); ++I) { - if (R.isAcceptableDecl(*I)) { + if (NamedDecl *ND = R.getAcceptableDecl(*I)) { // We found something. Look for anything else in our scope // with this same name and in an acceptable identifier // namespace, so that we can construct an overload set if we // need to. Found = true; - R.addDecl(*I); + R.addDecl(ND); } } @@ -1047,6 +1053,40 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { return !R.empty(); } +/// \brief Retrieve the previous declaration of D. +static NamedDecl *getPreviousDeclaration(NamedDecl *D) { + if (TagDecl *TD = dyn_cast<TagDecl>(D)) + return TD->getPreviousDeclaration(); + if (VarDecl *VD = dyn_cast<VarDecl>(D)) + return VD->getPreviousDeclaration(); + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + return FD->getPreviousDeclaration(); + if (RedeclarableTemplateDecl *RTD = dyn_cast<RedeclarableTemplateDecl>(D)) + return RTD->getPreviousDeclaration(); + + return 0; +} + +/// \brief Retrieve the visible declaration corresponding to D, if any. +/// +/// This routine determines whether the declaration D is visible in the current +/// module, with the current imports. If not, it checks whether any +/// redeclaration of D is visible, and if so, returns that declaration. +/// +/// \returns D, or a visible previous declaration of D, whichever is more recent +/// and visible. If no declaration of D is visible, returns null. +static NamedDecl *getVisibleDecl(NamedDecl *D) { + if (LookupResult::isVisible(D)) + return D; + + while ((D = getPreviousDeclaration(D))) { + if (LookupResult::isVisible(D)) + return D; + } + + return 0; +} + /// @brief Perform unqualified name lookup starting from a given /// scope. /// @@ -1125,10 +1165,11 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { // If this declaration is module-private and it came from an AST // file, we can't see it. - if ((*I)->isModulePrivate() && (*I)->isFromASTFile()) + NamedDecl *D = getVisibleDecl(*I); + if (!D) continue; - - R.addDecl(*I); + + R.addDecl(D); if ((*I)->getAttr<OverloadableAttr>()) { // If this declaration has the "overloadable" attribute, we @@ -1145,7 +1186,10 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { for (++LastI; LastI != IEnd; ++LastI) { if (!S->isDeclScope(*LastI)) break; - R.addDecl(*LastI); + + D = getVisibleDecl(*LastI); + if (D) + R.addDecl(D); } } @@ -2712,7 +2756,7 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, DEnd = CurCtx->decls_end(); D != DEnd; ++D) { if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) { - if (Result.isAcceptableDecl(ND)) { + if ((ND = Result.getAcceptableDecl(ND))) { Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); Visited.add(ND); } @@ -2723,17 +2767,16 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, PEnd = ForwardProto->protocol_end(); P != PEnd; ++P) { - if (Result.isAcceptableDecl(*P)) { - Consumer.FoundDecl(*P, Visited.checkHidden(*P), Ctx, InBaseClass); - Visited.add(*P); + if (NamedDecl *ND = Result.getAcceptableDecl(*P)) { + Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); + Visited.add(ND); } } } else if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D)) { ObjCInterfaceDecl *IFace = Class->getForwardInterfaceDecl(); - if (Result.isAcceptableDecl(IFace)) { - Consumer.FoundDecl(IFace, Visited.checkHidden(IFace), Ctx, - InBaseClass); - Visited.add(IFace); + if (NamedDecl *ND = Result.getAcceptableDecl(IFace)) { + Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); + Visited.add(ND); } } @@ -2873,7 +2916,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); D != DEnd; ++D) { if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) - if (Result.isAcceptableDecl(ND)) { + if ((ND = Result.getAcceptableDecl(ND))) { Consumer.FoundDecl(ND, Visited.checkHidden(ND), 0, false); Visited.add(ND); } |