diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp | 253 |
1 files changed, 189 insertions, 64 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp index ad06872..d0a55b5 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/Lookup.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" @@ -23,7 +24,9 @@ #include "clang/AST/ExprCXX.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/LangOptions.h" +#include "clang/Lex/HeaderSearch.h" #include "clang/Lex/ModuleLoader.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ExternalSemaSource.h" #include "clang/Sema/Overload.h" @@ -194,10 +197,11 @@ namespace { const_iterator begin() const { return list.begin(); } const_iterator end() const { return list.end(); } - std::pair<const_iterator,const_iterator> + llvm::iterator_range<const_iterator> getNamespacesFor(DeclContext *DC) const { - return std::equal_range(begin(), end(), DC->getPrimaryContext(), - UnqualUsingEntry::Comparator()); + return llvm::make_range(std::equal_range(begin(), end(), + DC->getPrimaryContext(), + UnqualUsingEntry::Comparator())); } }; } @@ -413,6 +417,10 @@ void LookupResult::resolveKind() { if (!Unique.insert(D).second) { // If it's not unique, pull something off the back (and // continue at this index). + // FIXME: This is wrong. We need to take the more recent declaration in + // order to get the right type, default arguments, etc. We also need to + // prefer visible declarations to hidden ones (for redeclaration lookup + // in modules builds). Decls[I] = Decls[--N]; continue; } @@ -670,8 +678,8 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { DeclareImplicitMemberFunctionsWithName(S, R.getLookupName(), DC); // Perform lookup into this declaration context. - DeclContext::lookup_const_result DR = DC->lookup(R.getLookupName()); - for (DeclContext::lookup_const_iterator I = DR.begin(), E = DR.end(); I != E; + DeclContext::lookup_result DR = DC->lookup(R.getLookupName()); + for (DeclContext::lookup_iterator I = DR.begin(), E = DR.end(); I != E; ++I) { NamedDecl *D = *I; if ((D = R.getAcceptableDecl(D))) { @@ -765,11 +773,8 @@ CppNamespaceLookup(Sema &S, LookupResult &R, ASTContext &Context, // Perform direct name lookup into the namespaces nominated by the // using directives whose common ancestor is this namespace. - UnqualUsingDirectiveSet::const_iterator UI, UEnd; - std::tie(UI, UEnd) = UDirs.getNamespacesFor(NS); - - for (; UI != UEnd; ++UI) - if (LookupDirect(S, R, UI->getNominatedNamespace())) + for (const UnqualUsingEntry &UUE : UDirs.getNamespacesFor(NS)) + if (LookupDirect(S, R, UUE.getNominatedNamespace())) Found = true; R.resolveKind(); @@ -1167,8 +1172,71 @@ static Decl *getInstantiatedFrom(Decl *D, MemberSpecializationInfo *MSInfo) { return MSInfo->isExplicitSpecialization() ? D : MSInfo->getInstantiatedFrom(); } +Module *Sema::getOwningModule(Decl *Entity) { + // If it's imported, grab its owning module. + Module *M = Entity->getImportedOwningModule(); + if (M || !isa<NamedDecl>(Entity) || !cast<NamedDecl>(Entity)->isHidden()) + return M; + assert(!Entity->isFromASTFile() && + "hidden entity from AST file has no owning module"); + + if (!getLangOpts().ModulesLocalVisibility) { + // If we're not tracking visibility locally, the only way a declaration + // can be hidden and local is if it's hidden because it's parent is (for + // instance, maybe this is a lazily-declared special member of an imported + // class). + auto *Parent = cast<NamedDecl>(Entity->getDeclContext()); + assert(Parent->isHidden() && "unexpectedly hidden decl"); + return getOwningModule(Parent); + } + + // It's local and hidden; grab or compute its owning module. + M = Entity->getLocalOwningModule(); + if (M) + return M; + + if (auto *Containing = + PP.getModuleContainingLocation(Entity->getLocation())) { + M = Containing; + } else if (Entity->isInvalidDecl() || Entity->getLocation().isInvalid()) { + // Don't bother tracking visibility for invalid declarations with broken + // locations. + cast<NamedDecl>(Entity)->setHidden(false); + } else { + // We need to assign a module to an entity that exists outside of any + // module, so that we can hide it from modules that we textually enter. + // Invent a fake module for all such entities. + if (!CachedFakeTopLevelModule) { + CachedFakeTopLevelModule = + PP.getHeaderSearchInfo().getModuleMap().findOrCreateModule( + "<top-level>", nullptr, false, false).first; + + auto &SrcMgr = PP.getSourceManager(); + SourceLocation StartLoc = + SrcMgr.getLocForStartOfFile(SrcMgr.getMainFileID()); + auto &TopLevel = + VisibleModulesStack.empty() ? VisibleModules : VisibleModulesStack[0]; + TopLevel.setVisible(CachedFakeTopLevelModule, StartLoc); + } + + M = CachedFakeTopLevelModule; + } + + if (M) + Entity->setLocalOwningModule(M); + return M; +} + +void Sema::makeMergedDefinitionVisible(NamedDecl *ND, SourceLocation Loc) { + if (auto *M = PP.getModuleContainingLocation(Loc)) + Context.mergeDefinitionIntoModule(ND, M); + else + // We're not building a module; just make the definition visible. + ND->setHidden(false); +} + /// \brief Find the module in which the given declaration was defined. -static Module *getDefiningModule(Decl *Entity) { +static Module *getDefiningModule(Sema &S, Decl *Entity) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Entity)) { // If this function was instantiated from a template, the defining module is // the module containing the pattern. @@ -1190,15 +1258,16 @@ static Module *getDefiningModule(Decl *Entity) { // from a template. DeclContext *Context = Entity->getDeclContext(); if (Context->isFileContext()) - return Entity->getOwningModule(); - return getDefiningModule(cast<Decl>(Context)); + return S.getOwningModule(Entity); + return getDefiningModule(S, cast<Decl>(Context)); } llvm::DenseSet<Module*> &Sema::getLookupModules() { unsigned N = ActiveTemplateInstantiations.size(); for (unsigned I = ActiveTemplateInstantiationLookupModules.size(); I != N; ++I) { - Module *M = getDefiningModule(ActiveTemplateInstantiations[I].Entity); + Module *M = + getDefiningModule(*this, ActiveTemplateInstantiations[I].Entity); if (M && !LookupModulesCache.insert(M).second) M = nullptr; ActiveTemplateInstantiationLookupModules.push_back(M); @@ -1206,6 +1275,13 @@ llvm::DenseSet<Module*> &Sema::getLookupModules() { return LookupModulesCache; } +bool Sema::hasVisibleMergedDefinition(NamedDecl *Def) { + for (Module *Merged : Context.getModulesWithMergedDefinition(Def)) + if (isModuleVisible(Merged)) + return true; + return false; +} + /// \brief Determine whether a declaration is visible to name lookup. /// /// This routine determines whether the declaration D is visible in the current @@ -1215,10 +1291,48 @@ llvm::DenseSet<Module*> &Sema::getLookupModules() { /// path (by instantiating a template, you allow it to see the declarations that /// your module can see, including those later on in your module). bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { - assert(D->isHidden() && !SemaRef.ActiveTemplateInstantiations.empty() && - "should not call this: not in slow case"); - Module *DeclModule = D->getOwningModule(); - assert(DeclModule && "hidden decl not from a module"); + assert(D->isHidden() && "should not call this: not in slow case"); + Module *DeclModule = SemaRef.getOwningModule(D); + if (!DeclModule) { + // getOwningModule() may have decided the declaration should not be hidden. + assert(!D->isHidden() && "hidden decl not from a module"); + return true; + } + + // If the owning module is visible, and the decl is not module private, + // then the decl is visible too. (Module private is ignored within the same + // top-level module.) + if (!D->isFromASTFile() || !D->isModulePrivate()) { + if (SemaRef.isModuleVisible(DeclModule)) + return true; + // Also check merged definitions. + if (SemaRef.getLangOpts().ModulesLocalVisibility && + SemaRef.hasVisibleMergedDefinition(D)) + return true; + } + + // If this declaration is not at namespace scope nor module-private, + // then it is visible if its lexical parent has a visible definition. + DeclContext *DC = D->getLexicalDeclContext(); + if (!D->isModulePrivate() && + DC && !DC->isFileContext() && !isa<LinkageSpecDecl>(DC)) { + // For a parameter, check whether our current template declaration's + // lexical context is visible, not whether there's some other visible + // definition of it, because parameters aren't "within" the definition. + if ((D->isTemplateParameter() || isa<ParmVarDecl>(D)) + ? isVisible(SemaRef, cast<NamedDecl>(DC)) + : SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC))) { + if (SemaRef.ActiveTemplateInstantiations.empty() && + // FIXME: Do something better in this case. + !SemaRef.getLangOpts().ModulesLocalVisibility) { + // Cache the fact that this declaration is implicitly visible because + // its parent has a visible definition. + D->setHidden(false); + } + return true; + } + return false; + } // Find the extra places where we need to look. llvm::DenseSet<Module*> &LookupModules = SemaRef.getLookupModules(); @@ -1243,6 +1357,10 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { return false; } +bool Sema::isVisibleSlow(const NamedDecl *D) { + return LookupResult::isVisible(*this, const_cast<NamedDecl*>(D)); +} + /// \brief Retrieve the visible declaration corresponding to D, if any. /// /// This routine determines whether the declaration D is visible in the current @@ -1256,6 +1374,9 @@ static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) { for (auto RD : D->redecls()) { if (auto ND = dyn_cast<NamedDecl>(RD)) { + // FIXME: This is wrong in the case where the previous declaration is not + // visible in the same scope as D. This needs to be done much more + // carefully. if (LookupResult::isVisible(SemaRef, ND)) return ND; } @@ -2953,7 +3074,7 @@ class ShadowContextRAII { public: ShadowContextRAII(VisibleDeclsRecord &Visible) : Visible(Visible) { - Visible.ShadowMaps.push_back(ShadowMap()); + Visible.ShadowMaps.emplace_back(); } ~ShadowContextRAII() { @@ -3016,17 +3137,45 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, if (Visited.visitedContext(Ctx->getPrimaryContext())) return; + // Outside C++, lookup results for the TU live on identifiers. + if (isa<TranslationUnitDecl>(Ctx) && + !Result.getSema().getLangOpts().CPlusPlus) { + auto &S = Result.getSema(); + auto &Idents = S.Context.Idents; + + // Ensure all external identifiers are in the identifier table. + if (IdentifierInfoLookup *External = Idents.getExternalIdentifierLookup()) { + std::unique_ptr<IdentifierIterator> Iter(External->getIdentifiers()); + for (StringRef Name = Iter->Next(); !Name.empty(); Name = Iter->Next()) + Idents.get(Name); + } + + // Walk all lookup results in the TU for each identifier. + for (const auto &Ident : Idents) { + for (auto I = S.IdResolver.begin(Ident.getValue()), + E = S.IdResolver.end(); + I != E; ++I) { + if (S.IdResolver.isDeclInScope(*I, Ctx)) { + if (NamedDecl *ND = Result.getAcceptableDecl(*I)) { + Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); + Visited.add(ND); + } + } + } + } + + return; + } + if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) Result.getSema().ForceDeclarationOfImplicitMembers(Class); // Enumerate all of the results in this context. - for (const auto &R : Ctx->lookups()) { - for (auto *I : R) { - if (NamedDecl *ND = dyn_cast<NamedDecl>(I)) { - if ((ND = Result.getAcceptableDecl(ND))) { - Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); - Visited.add(ND); - } + for (DeclContextLookupResult R : Ctx->lookups()) { + for (auto *D : R) { + if (auto *ND = Result.getAcceptableDecl(D)) { + Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); + Visited.add(ND); } } } @@ -3209,10 +3358,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, if (Entity) { // Lookup visible declarations in any namespaces found by using // directives. - UnqualUsingDirectiveSet::const_iterator UI, UEnd; - std::tie(UI, UEnd) = UDirs.getNamespacesFor(Entity); - for (; UI != UEnd; ++UI) - LookupVisibleDecls(const_cast<DeclContext *>(UI->getNominatedNamespace()), + for (const UnqualUsingEntry &UUE : UDirs.getNamespacesFor(Entity)) + LookupVisibleDecls(const_cast<DeclContext *>(UUE.getNominatedNamespace()), Result, /*QualifiedNameLookup=*/false, /*InBaseClass=*/false, Consumer, Visited); } @@ -3682,8 +3829,7 @@ void TypoCorrectionConsumer::performQualifiedLookups() { TypoCorrectionConsumer::NamespaceSpecifierSet::NamespaceSpecifierSet( ASTContext &Context, DeclContext *CurContext, CXXScopeSpec *CurScopeSpec) - : Context(Context), CurContextChain(buildContextChain(CurContext)), - isSorted(false) { + : Context(Context), CurContextChain(buildContextChain(CurContext)) { if (NestedNameSpecifier *NNS = CurScopeSpec ? CurScopeSpec->getScopeRep() : nullptr) { llvm::raw_string_ostream SpecifierOStream(CurNameSpecifier); @@ -3702,7 +3848,6 @@ TypoCorrectionConsumer::NamespaceSpecifierSet::NamespaceSpecifierSet( } // Add the global context as a NestedNameSpecifier - Distances.insert(1); SpecifierInfo SI = {cast<DeclContext>(Context.getTranslationUnitDecl()), NestedNameSpecifier::GlobalSpecifier(Context), 1}; DistanceMap[1].push_back(SI); @@ -3722,22 +3867,6 @@ auto TypoCorrectionConsumer::NamespaceSpecifierSet::buildContextChain( return Chain; } -void TypoCorrectionConsumer::NamespaceSpecifierSet::sortNamespaces() { - SmallVector<unsigned, 4> sortedDistances; - sortedDistances.append(Distances.begin(), Distances.end()); - - if (sortedDistances.size() > 1) - std::sort(sortedDistances.begin(), sortedDistances.end()); - - Specifiers.clear(); - for (auto D : sortedDistances) { - SpecifierInfoList &SpecList = DistanceMap[D]; - Specifiers.append(SpecList.begin(), SpecList.end()); - } - - isSorted = true; -} - unsigned TypoCorrectionConsumer::NamespaceSpecifierSet::buildNestedNameSpecifier( DeclContextList &DeclChain, NestedNameSpecifier *&NNS) { @@ -3818,8 +3947,6 @@ void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier( llvm::makeArrayRef(NewNameSpecifierIdentifiers)); } - isSorted = false; - Distances.insert(NumSpecifiers); SpecifierInfo SI = {Ctx, NNS, NumSpecifiers}; DistanceMap[NumSpecifiers].push_back(SI); } @@ -4294,7 +4421,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // Record the failure's location if needed and return an empty correction. If // this was an unqualified lookup and we believe the callback object did not // filter out possible corrections, also cache the failure for the typo. - return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); + return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure && !SecondBestTC); } /// \brief Try to "correct" a typo in the source code by finding @@ -4347,9 +4474,7 @@ TypoExpr *Sema::CorrectTypoDelayed( TypoCorrection Empty; auto Consumer = makeTypoCorrectionConsumer( TypoName, LookupKind, S, SS, std::move(CCC), MemberContext, - EnteringContext, OPT, - /*SearchModules=*/(Mode == CTK_ErrorRecovery) && getLangOpts().Modules && - getLangOpts().ModulesSearchAll); + EnteringContext, OPT, Mode == CTK_ErrorRecovery); if (!Consumer || Consumer->empty()) return nullptr; @@ -4491,18 +4616,18 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction, /// Find which declaration we should import to provide the definition of /// the given declaration. -static const NamedDecl *getDefinitionToImport(const NamedDecl *D) { - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) +static NamedDecl *getDefinitionToImport(NamedDecl *D) { + if (VarDecl *VD = dyn_cast<VarDecl>(D)) return VD->getDefinition(); if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) - return FD->isDefined(FD) ? FD : nullptr; - if (const TagDecl *TD = dyn_cast<TagDecl>(D)) + return FD->isDefined(FD) ? const_cast<FunctionDecl*>(FD) : nullptr; + if (TagDecl *TD = dyn_cast<TagDecl>(D)) return TD->getDefinition(); - if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) + if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) return ID->getDefinition(); - if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) + if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) return PD->getDefinition(); - if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) + if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) return getDefinitionToImport(TD->getTemplatedDecl()); return nullptr; } @@ -4535,10 +4660,10 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction, // Suggest importing a module providing the definition of this entity, if // possible. - const NamedDecl *Def = getDefinitionToImport(Decl); + NamedDecl *Def = getDefinitionToImport(Decl); if (!Def) Def = Decl; - Module *Owner = Def->getOwningModule(); + Module *Owner = getOwningModule(Def); assert(Owner && "definition of hidden declaration is not in a module"); Diag(Correction.getCorrectionRange().getBegin(), |