aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Sema/SemaModule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaModule.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaModule.cpp102
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;