diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaModule.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/Sema/SemaModule.cpp | 102 |
1 files changed, 57 insertions, 45 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaModule.cpp b/contrib/llvm-project/clang/lib/Sema/SemaModule.cpp index 3b84e7bd4277..7c982bcd63d7 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaModule.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaModule.cpp @@ -15,9 +15,9 @@ #include "clang/AST/ASTMutationListener.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/ParsedAttr.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/StringExtras.h" -#include <optional> using namespace clang; using namespace sema; @@ -69,7 +69,7 @@ static std::string stringFromPath(ModuleIdPath Path) { for (auto &Piece : Path) { if (!Name.empty()) Name += "."; - Name += Piece.first->getName(); + Name += Piece.getIdentifierInfo()->getName(); } return Name; } @@ -136,6 +136,7 @@ makeTransitiveImportsVisible(ASTContext &Ctx, VisibleModuleSet &VisibleModules, "modules only."); llvm::SmallVector<Module *, 4> Worklist; + llvm::SmallSet<Module *, 16> Visited; Worklist.push_back(Imported); Module *FoundPrimaryModuleInterface = @@ -144,18 +145,22 @@ makeTransitiveImportsVisible(ASTContext &Ctx, VisibleModuleSet &VisibleModules, while (!Worklist.empty()) { Module *Importing = Worklist.pop_back_val(); - if (VisibleModules.isVisible(Importing)) + if (Visited.count(Importing)) continue; + Visited.insert(Importing); // FIXME: The ImportLoc here is not meaningful. It may be problematic if we // use the sourcelocation loaded from the visible modules. VisibleModules.setVisible(Importing, ImportLoc); if (isImportingModuleUnitFromSameModule(Ctx, Importing, CurrentModule, - FoundPrimaryModuleInterface)) + FoundPrimaryModuleInterface)) { for (Module *TransImported : Importing->Imports) - if (!VisibleModules.isVisible(TransImported)) - Worklist.push_back(TransImported); + Worklist.push_back(TransImported); + + for (auto [Exports, _] : Importing->Exports) + Worklist.push_back(Exports); + } } } @@ -258,11 +263,11 @@ static bool DiagReservedModuleName(Sema &S, const IdentifierInfo *II, Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, ModuleDeclKind MDK, ModuleIdPath Path, - ModuleIdPath Partition, ModuleImportState &ImportState) { + ModuleIdPath Partition, ModuleImportState &ImportState, + bool IntroducerIsFirstPPToken) { assert(getLangOpts().CPlusPlusModules && "should only have module decl in standard C++ modules"); - bool IsFirstDecl = ImportState == ModuleImportState::FirstDecl; bool SeenGMF = ImportState == ModuleImportState::GlobalFragment; // If any of the steps here fail, we count that as invalidating C++20 // module state; @@ -328,18 +333,13 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, SeenGMF == (bool)this->TheGlobalModuleFragment) && "mismatched global module state"); - // In C++20, the module-declaration must be the first declaration if there - // is no global module fragment. - if (getLangOpts().CPlusPlusModules && !IsFirstDecl && !SeenGMF) { + // In C++20, A module directive may only appear as the first preprocessing + // tokens in a file (excluding the global module fragment.). + if (getLangOpts().CPlusPlusModules && !IntroducerIsFirstPPToken && !SeenGMF) { Diag(ModuleLoc, diag::err_module_decl_not_at_start); - SourceLocation BeginLoc = - ModuleScopes.empty() - ? SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()) - : ModuleScopes.back().BeginLoc; - if (BeginLoc.isValid()) { - Diag(BeginLoc, diag::note_global_module_introducer_missing) - << FixItHint::CreateInsertion(BeginLoc, "module;\n"); - } + SourceLocation BeginLoc = PP.getMainFileFirstPPTokenLoc(); + Diag(BeginLoc, diag::note_global_module_introducer_missing) + << FixItHint::CreateInsertion(BeginLoc, "module;\n"); } // C++23 [module.unit]p1: ... The identifiers module and import shall not @@ -351,17 +351,18 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, // 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) && + StringRef FirstComponentName = Path[0].getIdentifierInfo()->getName(); + if (!getSourceManager().isInSystemHeader(Path[0].getLoc()) && (FirstComponentName == "std" || (FirstComponentName.starts_with("std") && llvm::all_of(FirstComponentName.drop_front(3), &llvm::isDigit)))) - Diag(Path[0].second, diag::warn_reserved_module_name) << Path[0].first; + Diag(Path[0].getLoc(), diag::warn_reserved_module_name) + << Path[0].getIdentifierInfo(); // 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)) + if (DiagReservedModuleName(*this, Part.getIdentifierInfo(), Part.getLoc())) return nullptr; } @@ -377,10 +378,10 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, // correct. if (!getLangOpts().CurrentModule.empty() && getLangOpts().CurrentModule != ModuleName) { - Diag(Path.front().second, diag::err_current_module_name_mismatch) - << SourceRange(Path.front().second, IsPartition - ? Partition.back().second - : Path.back().second) + Diag(Path.front().getLoc(), diag::err_current_module_name_mismatch) + << SourceRange(Path.front().getLoc(), IsPartition + ? Partition.back().getLoc() + : Path.back().getLoc()) << getLangOpts().CurrentModule; return nullptr; } @@ -394,8 +395,8 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, case ModuleDeclKind::PartitionInterface: { // We can't have parsed or imported a definition of this module or parsed a // module map defining it already. - if (auto *M = Map.findModule(ModuleName)) { - Diag(Path[0].second, diag::err_module_redefinition) << ModuleName; + if (auto *M = Map.findOrLoadModule(ModuleName)) { + Diag(Path[0].getLoc(), diag::err_module_redefinition) << ModuleName; if (M->DefinitionLoc.isValid()) Diag(M->DefinitionLoc, diag::note_prev_module_definition); else if (OptionalFileEntryRef FE = M->getASTFile()) @@ -418,8 +419,8 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, // keyword nor a module-partition implicitly imports the primary // module interface unit of the module as if by a module-import- // declaration. - std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc( - PP.getIdentifierInfo(ModuleName), Path[0].second); + IdentifierLoc ModuleNameLoc(Path[0].getLoc(), + PP.getIdentifierInfo(ModuleName)); // The module loader will assume we're trying to import the module that // we're building if `LangOpts.CurrentModule` equals to 'ModuleName'. @@ -491,7 +492,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, // Make the import decl for the interface in the impl module. ImportDecl *Import = ImportDecl::Create(Context, CurContext, ModuleLoc, - Interface, Path[0].second); + Interface, Path[0].getLoc()); CurContext->addDecl(Import); // Sequence initialization of the imported module before that of the current @@ -580,7 +581,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc, // For a C++20 module name, flatten into a single identifier with the source // location of the first component. - std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc; + IdentifierLoc ModuleNameLoc; std::string ModuleName; if (IsPartition) { @@ -592,11 +593,13 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc, ModuleName = NamedMod->getPrimaryModuleInterfaceName().str(); ModuleName += ":"; ModuleName += stringFromPath(Path); - ModuleNameLoc = {PP.getIdentifierInfo(ModuleName), Path[0].second}; + ModuleNameLoc = + IdentifierLoc(Path[0].getLoc(), PP.getIdentifierInfo(ModuleName)); Path = ModuleIdPath(ModuleNameLoc); } else if (getLangOpts().CPlusPlusModules) { ModuleName = stringFromPath(Path); - ModuleNameLoc = {PP.getIdentifierInfo(ModuleName), Path[0].second}; + ModuleNameLoc = + IdentifierLoc(Path[0].getLoc(), PP.getIdentifierInfo(ModuleName)); Path = ModuleIdPath(ModuleNameLoc); } @@ -650,6 +653,14 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc, else VisibleModules.setVisible(Mod, ImportLoc); + assert((!Mod->isModulePartitionImplementation() || getCurrentModule()) && + "We can only import a partition unit in a named module."); + if (Mod->isModulePartitionImplementation() && + getCurrentModule()->isModuleInterfaceUnit()) + Diag(ImportLoc, + diag::warn_import_implementation_partition_unit_in_interface_unit) + << Mod->Name; + checkModuleImportContext(*this, Mod, ImportLoc, CurContext); // FIXME: we should support importing a submodule within a different submodule @@ -673,7 +684,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc, IdentifierLocs.push_back(SourceLocation()); } else if (getLangOpts().CPlusPlusModules && !Mod->Parent) { // A single identifier for the whole name. - IdentifierLocs.push_back(Path[0].second); + IdentifierLocs.push_back(Path[0].getLoc()); } else { Module *ModCheck = Mod; for (unsigned I = 0, N = Path.size(); I != N; ++I) { @@ -683,7 +694,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc, break; ModCheck = ModCheck->Parent; - IdentifierLocs.push_back(Path[I].second); + IdentifierLocs.push_back(Path[I].getLoc()); } } @@ -700,8 +711,14 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc, if (getLangOpts().CPlusPlusModules && ExportLoc.isValid() && Mod->Kind == Module::ModuleKind::ModulePartitionImplementation) { Diag(ExportLoc, diag::err_export_partition_impl) - << SourceRange(ExportLoc, Path.back().second); - } else if (!ModuleScopes.empty() && !currentModuleIsImplementation()) { + << SourceRange(ExportLoc, Path.back().getLoc()); + } else if (ExportLoc.isValid() && + (ModuleScopes.empty() || currentModuleIsImplementation())) { + // [module.interface]p1: + // An export-declaration shall inhabit a namespace scope and appear in the + // purview of a module interface unit. + Diag(ExportLoc, diag::err_export_not_in_module_interface); + } else if (!ModuleScopes.empty()) { // 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. @@ -709,11 +726,6 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc, getCurrentModule()->Exports.emplace_back(Mod, false); else getCurrentModule()->Imports.insert(Mod); - } else if (ExportLoc.isValid()) { - // [module.interface]p1: - // An export-declaration shall inhabit a namespace scope and appear in the - // purview of a module interface unit. - Diag(ExportLoc, diag::err_export_not_in_module_interface); } return Import; @@ -931,7 +943,7 @@ static bool checkExportedDecl(Sema &S, Decl *D, SourceLocation BlockStart) { // HLSL: export declaration is valid only on functions if (S.getLangOpts().HLSL) { // Export-within-export was already diagnosed in ActOnStartExportDecl - if (!dyn_cast<FunctionDecl>(D) && !dyn_cast<ExportDecl>(D)) { + if (!isa<FunctionDecl, ExportDecl>(D)) { S.Diag(D->getBeginLoc(), diag::err_hlsl_export_not_on_function); D->setInvalidDecl(); return false; |
