diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaModule.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Sema/SemaModule.cpp | 115 |
1 files changed, 82 insertions, 33 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaModule.cpp b/contrib/llvm-project/clang/lib/Sema/SemaModule.cpp index f5c24bd10daa..f52c0247f01c 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaModule.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaModule.cpp @@ -15,6 +15,7 @@ #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/SemaInternal.h" +#include <optional> using namespace clang; using namespace sema; @@ -119,12 +120,12 @@ void Sema::HandleStartOfHeaderUnit() { // TODO: Make the C++20 header lookup independent. // When the input is pre-processed source, we need a file ref to the original // file for the header map. - auto F = SourceMgr.getFileManager().getFile(HUName); + auto F = SourceMgr.getFileManager().getOptionalFileRef(HUName); // For the sake of error recovery (if someone has moved the original header // after creating the pre-processed output) fall back to obtaining the file // ref for the input file, which must be present. if (!F) - F = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); + F = SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID()); assert(F && "failed to find the header unit source?"); Module::Header H{HUName.str(), HUName.str(), *F}; auto &Map = PP.getHeaderSearchInfo().getModuleMap(); @@ -144,6 +145,36 @@ void Sema::HandleStartOfHeaderUnit() { TU->setLocalOwningModule(Mod); } +/// Tests whether the given identifier is reserved as a module name and +/// diagnoses if it is. Returns true if a diagnostic is emitted and false +/// otherwise. +static bool DiagReservedModuleName(Sema &S, const IdentifierInfo *II, + SourceLocation Loc) { + enum { + Valid = -1, + Invalid = 0, + Reserved = 1, + } Reason = Valid; + + if (II->isStr("module") || II->isStr("import")) + Reason = Invalid; + else if (II->isReserved(S.getLangOpts()) != + ReservedIdentifierStatus::NotReserved) + Reason = Reserved; + + // If the identifier is reserved (not invalid) but is in a system header, + // we do not diagnose (because we expect system headers to use reserved + // identifiers). + if (Reason == Reserved && S.getSourceManager().isInSystemHeader(Loc)) + Reason = Valid; + + if (Reason != Valid) { + S.Diag(Loc, diag::err_invalid_module_name) << II << (int)Reason; + return true; + } + return false; +} + Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, ModuleDeclKind MDK, ModuleIdPath Path, @@ -195,9 +226,8 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, Diag(ModuleLoc, diag::err_module_decl_in_module_map_module); return nullptr; - case LangOptions::CMK_HeaderModule: case LangOptions::CMK_HeaderUnit: - Diag(ModuleLoc, diag::err_module_decl_in_header_module); + Diag(ModuleLoc, diag::err_module_decl_in_header_unit); return nullptr; } @@ -207,22 +237,15 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, // here, in order to support macro import. // Only one module-declaration is permitted per source file. - if (!ModuleScopes.empty() && - ModuleScopes.back().Module->isModulePurview()) { + if (isCurrentModulePurview()) { Diag(ModuleLoc, diag::err_module_redeclaration); Diag(VisibleModules.getImportLoc(ModuleScopes.back().Module), diag::note_prev_module_declaration); return nullptr; } - // Find the global module fragment we're adopting into this module, if any. - Module *GlobalModuleFragment = nullptr; - if (!ModuleScopes.empty() && - ModuleScopes.back().Module->Kind == Module::GlobalModuleFragment) - GlobalModuleFragment = ModuleScopes.back().Module; - assert((!getLangOpts().CPlusPlusModules || getLangOpts().ModulesTS || - SeenGMF == (bool)GlobalModuleFragment) && + SeenGMF == (bool)this->GlobalModuleFragment) && "mismatched global module state"); // In C++20, the module-declaration must be the first declaration if there @@ -239,6 +262,32 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, } } + // C++2b [module.unit]p1: ... The identifiers module and import shall not + // appear as identifiers in a module-name or module-partition. All + // module-names either beginning with an identifier consisting of std + // followed by zero or more digits or containing a reserved identifier + // ([lex.name]) are reserved and shall not be specified in a + // module-declaration; no diagnostic is required. + + // Test the first part of the path to see if it's std[0-9]+ but allow the + // name in a system header. + StringRef FirstComponentName = Path[0].first->getName(); + if (!getSourceManager().isInSystemHeader(Path[0].second) && + (FirstComponentName == "std" || + (FirstComponentName.startswith("std") && + llvm::all_of(FirstComponentName.drop_front(3), &llvm::isDigit)))) { + Diag(Path[0].second, diag::err_invalid_module_name) + << Path[0].first << /*reserved*/ 1; + return nullptr; + } + + // Then test all of the components in the path to see if any of them are + // using another kind of reserved or invalid identifier. + for (auto Part : Path) { + if (DiagReservedModuleName(*this, Part.first, Part.second)) + return nullptr; + } + // Flatten the dots in a module name. Unlike Clang's hierarchical module map // modules, the dots here are just another character that can appear in a // module name. @@ -272,7 +321,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, Diag(Path[0].second, diag::err_module_redefinition) << ModuleName; if (M->DefinitionLoc.isValid()) Diag(M->DefinitionLoc, diag::note_prev_module_definition); - else if (Optional<FileEntryRef> FE = M->getASTFile()) + else if (OptionalFileEntryRef FE = M->getASTFile()) Diag(M->DefinitionLoc, diag::note_prev_module_definition_from_ast_file) << FE->getName(); Mod = M; @@ -280,8 +329,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, } // Create a Module for the module that we're defining. - Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName, - GlobalModuleFragment); + Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName); if (MDK == ModuleDeclKind::PartitionInterface) Mod->Kind = Module::ModulePartitionInterface; assert(Mod && "module creation should not fail"); @@ -301,21 +349,19 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, if (!Mod) { Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName; // Create an empty module interface unit for error recovery. - Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName, - GlobalModuleFragment); + Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName); } } break; case ModuleDeclKind::PartitionImplementation: // Create an interface, but note that it is an implementation // unit. - Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName, - GlobalModuleFragment); + Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName); Mod->Kind = Module::ModulePartitionImplementation; break; } - if (!GlobalModuleFragment) { + if (!this->GlobalModuleFragment) { ModuleScopes.push_back({}); if (getLangOpts().ModulesLocalVisibility) ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules); @@ -495,7 +541,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc, // of the same top-level module. Until we do, make it an error rather than // silently ignoring the import. // FIXME: Should we warn on a redundant import of the current module? - if (Mod->getTopLevelModuleName() == getLangOpts().CurrentModule && + if (Mod->isForBuilding(getLangOpts()) && (getLangOpts().isCompilingModule() || !getLangOpts().ModulesTS)) { Diag(ImportLoc, getLangOpts().isCompilingModule() ? diag::err_module_self_import @@ -545,9 +591,6 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc, (ModuleScopes.back().ModuleInterface || (getLangOpts().CPlusPlusModules && ModuleScopes.back().Module->isGlobalModule()))) { - assert((!ModuleScopes.back().Module->isGlobalModule() || - Mod->Kind == Module::ModuleKind::ModuleHeaderUnit) && - "should only be importing a header unit into the GMF"); // Re-export the module if the imported module is exported. // Note that we don't need to add re-exported module to Imports field // since `Exports` implies the module is imported already. @@ -562,11 +605,6 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc, Diag(ExportLoc, diag::err_export_not_in_module_interface) << (!ModuleScopes.empty() && !ModuleScopes.back().ImplicitGlobalModuleFragment); - } else if (getLangOpts().isCompilingModule()) { - Module *ThisModule = PP.getHeaderSearchInfo().lookupModule( - getLangOpts().CurrentModule, ExportLoc, false, false); - (void)ThisModule; - assert(ThisModule && "was expecting a module if building one"); } // In some cases we need to know if an entity was present in a directly- @@ -717,7 +755,7 @@ Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc, // An export-declaration shall appear only [...] in the purview of a module // interface unit. An export-declaration shall not appear directly or // indirectly within [...] a private-module-fragment. - if (ModuleScopes.empty() || !ModuleScopes.back().Module->isModulePurview()) { + if (!isCurrentModulePurview()) { Diag(ExportLoc, diag::err_export_not_in_module_interface) << 0; D->setInvalidDecl(); return D; @@ -786,7 +824,7 @@ enum class UnnamedDeclKind { }; } -static llvm::Optional<UnnamedDeclKind> getUnnamedDeclKind(Decl *D) { +static std::optional<UnnamedDeclKind> getUnnamedDeclKind(Decl *D) { if (isa<EmptyDecl>(D)) return UnnamedDeclKind::Empty; if (isa<StaticAssertDecl>(D)) @@ -796,7 +834,7 @@ static llvm::Optional<UnnamedDeclKind> getUnnamedDeclKind(Decl *D) { if (isa<UsingDirectiveDecl>(D)) return UnnamedDeclKind::UsingDirective; // Everything else either introduces one or more names or is ill-formed. - return llvm::None; + return std::nullopt; } unsigned getUnnamedDeclDiag(UnnamedDeclKind UDK, bool InBlock) { @@ -911,6 +949,17 @@ Decl *Sema::ActOnFinishExportDecl(Scope *S, Decl *D, SourceLocation RBraceLoc) { diagExportedUnnamedDecl(*this, UnnamedDeclKind::Context, Child, BlockStart); } + if (auto *FD = dyn_cast<FunctionDecl>(Child)) { + // [dcl.inline]/7 + // If an inline function or variable that is attached to a named module + // is declared in a definition domain, it shall be defined in that + // domain. + // So, if the current declaration does not have a definition, we must + // check at the end of the TU (or when the PMF starts) to see that we + // have a definition at that point. + if (FD->isInlineSpecified() && !FD->isDefined()) + PendingInlineFuncDecls.insert(FD); + } } } |