diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 50 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 115 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 8 |
4 files changed, 138 insertions, 36 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 6825dfa41fa..e9619b369c1 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -99,6 +99,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, GlobalNewDeleteDeclared(false), TUKind(TUKind), NumSFINAEErrors(0), + CachedFakeTopLevelModule(nullptr), AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1), CurrentInstantiationScope(nullptr), DisableTypoCorrection(false), diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 8be7286f66f..8c079f8647d 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1784,11 +1784,11 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, /// should not consider because they are not permitted to conflict, e.g., /// because they come from hidden sub-modules and do not refer to the same /// entity. -static void filterNonConflictingPreviousDecls(ASTContext &context, +static void filterNonConflictingPreviousDecls(Sema &S, NamedDecl *decl, LookupResult &previous){ // This is only interesting when modules are enabled. - if (!context.getLangOpts().Modules) + if (!S.getLangOpts().Modules) return; // Empty sets are uninteresting. @@ -1800,7 +1800,7 @@ static void filterNonConflictingPreviousDecls(ASTContext &context, NamedDecl *old = filter.next(); // Non-hidden declarations are never ignored. - if (!old->isHidden()) + if (S.isVisible(old)) continue; if (!old->isExternallyVisible()) @@ -1814,11 +1814,11 @@ static void filterNonConflictingPreviousDecls(ASTContext &context, /// entity if their types are the same. /// FIXME: This is notionally doing the same thing as ASTReaderDecl's /// isSameEntity. -static void filterNonConflictingPreviousTypedefDecls(ASTContext &Context, +static void filterNonConflictingPreviousTypedefDecls(Sema &S, TypedefNameDecl *Decl, LookupResult &Previous) { // This is only interesting when modules are enabled. - if (!Context.getLangOpts().Modules) + if (!S.getLangOpts().Modules) return; // Empty sets are uninteresting. @@ -1830,19 +1830,19 @@ static void filterNonConflictingPreviousTypedefDecls(ASTContext &Context, NamedDecl *Old = Filter.next(); // Non-hidden declarations are never ignored. - if (!Old->isHidden()) + if (S.isVisible(Old)) continue; // Declarations of the same entity are not ignored, even if they have // different linkages. if (auto *OldTD = dyn_cast<TypedefNameDecl>(Old)) { - if (Context.hasSameType(OldTD->getUnderlyingType(), - Decl->getUnderlyingType())) + if (S.Context.hasSameType(OldTD->getUnderlyingType(), + Decl->getUnderlyingType())) continue; // If both declarations give a tag declaration a typedef name for linkage // purposes, then they declare the same entity. - if (OldTD->getAnonDeclWithTypedefName() && + if (OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true) && Decl->getAnonDeclWithTypedefName()) continue; } @@ -1957,7 +1957,7 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { return New->setInvalidDecl(); if (auto *OldTD = dyn_cast<TypedefNameDecl>(Old)) { - auto *OldTag = OldTD->getAnonDeclWithTypedefName(); + auto *OldTag = OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true); auto *NewTag = New->getAnonDeclWithTypedefName(); NamedDecl *Hidden = nullptr; if (getLangOpts().CPlusPlus && OldTag && NewTag && @@ -5065,7 +5065,7 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD, // in an outer scope, it isn't the same thing. FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/false, /*AllowInlineNamespace*/false); - filterNonConflictingPreviousTypedefDecls(Context, NewTD, Previous); + filterNonConflictingPreviousTypedefDecls(*this, NewTD, Previous); if (!Previous.empty()) { Redeclaration = true; MergeTypedefNameDecl(NewTD, Previous); @@ -6381,7 +6381,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) { Previous.setShadowed(); // Filter out any non-conflicting previous declarations. - filterNonConflictingPreviousDecls(Context, NewVD, Previous); + filterNonConflictingPreviousDecls(*this, NewVD, Previous); if (!Previous.empty()) { MergeVarDecl(NewVD, Previous); @@ -7930,7 +7930,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, !Previous.isShadowed(); // Filter out any non-conflicting previous declarations. - filterNonConflictingPreviousDecls(Context, NewFD, Previous); + filterNonConflictingPreviousDecls(*this, NewFD, Previous); bool Redeclaration = false; NamedDecl *OldDecl = nullptr; @@ -7985,7 +7985,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // Check for a previous extern "C" declaration with this name. if (!Redeclaration && checkForConflictWithNonVisibleExternC(*this, NewFD, Previous)) { - filterNonConflictingPreviousDecls(Context, NewFD, Previous); + filterNonConflictingPreviousDecls(*this, NewFD, Previous); if (!Previous.empty()) { // This is an extern "C" declaration with the same name as a previous // declaration, and thus redeclares that entity... @@ -14076,6 +14076,8 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc, if (!Mod) return true; + VisibleModules.setVisible(Mod, ImportLoc); + checkModuleImportContext(*this, Mod, ImportLoc, CurContext); // FIXME: we should support importing a submodule within a different submodule @@ -14113,6 +14115,25 @@ void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) { // FIXME: Should we synthesize an ImportDecl here? getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc); + VisibleModules.setVisible(Mod, DirectiveLoc); +} + +void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) { + checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext); + + if (getLangOpts().ModulesLocalVisibility) + VisibleModulesStack.push_back(std::move(VisibleModules)); + VisibleModules.setVisible(Mod, DirectiveLoc); +} + +void Sema::ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod) { + checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext); + + if (getLangOpts().ModulesLocalVisibility) { + VisibleModules = std::move(VisibleModulesStack.back()); + VisibleModulesStack.pop_back(); + VisibleModules.setVisible(Mod, DirectiveLoc); + } } void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc, @@ -14130,6 +14151,7 @@ void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc, // Make the module visible. getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc); + VisibleModules.setVisible(Mod, Loc); } void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name, diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 5e7e34a8928..a8a143fa9a9 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -24,6 +24,7 @@ #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" @@ -1171,15 +1172,59 @@ 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"); + + // 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 *Listener = getASTMutationListener()) - Listener->RedefinedHiddenDefinition(ND, - PP.getModuleContainingLocation(Loc)); - ND->setHidden(false); + auto *M = PP.getModuleContainingLocation(Loc); + assert(M && "hidden definition not in any module"); + Context.mergeDefinitionIntoModule(ND, M); } /// \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. @@ -1201,15 +1246,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); @@ -1217,6 +1263,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 @@ -1227,8 +1280,24 @@ llvm::DenseSet<Module*> &Sema::getLookupModules() { /// your module can see, including those later on in your module). bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { assert(D->isHidden() && "should not call this: not in slow case"); - Module *DeclModule = D->getOwningModule(); - assert(DeclModule && "hidden decl not from a module"); + 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. @@ -1236,7 +1305,9 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { if (!D->isModulePrivate() && DC && !DC->isFileContext() && !isa<LinkageSpecDecl>(DC)) { if (SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC))) { - if (SemaRef.ActiveTemplateInstantiations.empty()) { + 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); @@ -1269,6 +1340,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 @@ -4524,18 +4599,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; } @@ -4568,10 +4643,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(), diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 8729f481d6d..0c6eac1e95a 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5148,7 +5148,11 @@ bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested) { // If this definition was instantiated from a template, map back to the // pattern from which it was instantiated. - if (auto *RD = dyn_cast<CXXRecordDecl>(D)) { + if (isa<TagDecl>(D) && cast<TagDecl>(D)->isBeingDefined()) { + // We're in the middle of defining it; this definition should be treated + // as visible. + return true; + } else if (auto *RD = dyn_cast<CXXRecordDecl>(D)) { if (auto *Pattern = RD->getTemplateInstantiationPattern()) RD = Pattern; D = RD->getDefinition(); @@ -5231,7 +5235,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, // repeating the diagnostic. // FIXME: Add a Fix-It that imports the corresponding module or includes // the header. - Module *Owner = SuggestedDef->getOwningModule(); + Module *Owner = getOwningModule(SuggestedDef); Diag(Loc, diag::err_module_private_definition) << T << Owner->getFullModuleName(); Diag(SuggestedDef->getLocation(), diag::note_previous_definition); |