aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaModule.cpp
diff options
context:
space:
mode:
authorIain Sandoe <iain@sandoe.co.uk>2022-06-03 10:43:38 +0100
committerIain Sandoe <iain@sandoe.co.uk>2023-03-29 08:52:28 +0530
commit6e4f870a21e344fdcd61fe613b0aeeafb8a84ed2 (patch)
treea6e16ee5cb1e7c71a5ab467dac93617bb1731535 /clang/lib/Sema/SemaModule.cpp
parent279c7a2f17937836ed13e359c3fb381bef7defaf (diff)
downloadllvm-6e4f870a21e344fdcd61fe613b0aeeafb8a84ed2.zip
llvm-6e4f870a21e344fdcd61fe613b0aeeafb8a84ed2.tar.gz
llvm-6e4f870a21e344fdcd61fe613b0aeeafb8a84ed2.tar.bz2
re-land [C++20][Modules] Introduce an implementation module.
We need to be able to distinguish individual TUs from the same module in cases where TU-local entities either need to be hidden (or, for some cases of ADL in template instantiation, need to be detected as exposures). This creates a module type for the implementation which implicitly imports its primary module interface per C++20: [module.unit/8] 'A module-declaration that contains neither an export-keyword nor a module-partition implicitly imports the primary module interface unit of the module as if by a module-import-declaration. Implementation modules are never serialized (-emit-module-interface for an implementation unit is diagnosed and rejected). Differential Revision: https://reviews.llvm.org/D126959
Diffstat (limited to 'clang/lib/Sema/SemaModule.cpp')
-rw-r--r--clang/lib/Sema/SemaModule.cpp59
1 files changed, 35 insertions, 24 deletions
diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 40ebc9c..6c39cc0 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -301,8 +301,8 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
const_cast<LangOptions&>(getLangOpts()).CurrentModule = ModuleName;
auto &Map = PP.getHeaderSearchInfo().getModuleMap();
- Module *Mod;
-
+ Module *Mod; // The module we are creating.
+ Module *Interface = nullptr; // The interface for an implementation.
switch (MDK) {
case ModuleDeclKind::Interface:
case ModuleDeclKind::PartitionInterface: {
@@ -339,18 +339,19 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
// we're building if `LangOpts.CurrentModule` equals to 'ModuleName'.
// Change the value for `LangOpts.CurrentModule` temporarily to make the
// module loader work properly.
- const_cast<LangOptions&>(getLangOpts()).CurrentModule = "";
- Mod = getModuleLoader().loadModule(ModuleLoc, {ModuleNameLoc},
- Module::AllVisible,
- /*IsInclusionDirective=*/false);
+ const_cast<LangOptions &>(getLangOpts()).CurrentModule = "";
+ Interface = getModuleLoader().loadModule(ModuleLoc, {ModuleNameLoc},
+ Module::AllVisible,
+ /*IsInclusionDirective=*/false);
const_cast<LangOptions&>(getLangOpts()).CurrentModule = ModuleName;
- if (!Mod) {
+ if (!Interface) {
Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName;
// Create an empty module interface unit for error recovery.
Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName);
+ } else {
+ Mod = Map.createModuleForImplementationUnit(ModuleLoc, ModuleName);
}
-
} break;
case ModuleDeclKind::PartitionImplementation:
@@ -389,19 +390,31 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
// statements, so imports are allowed.
ImportState = ModuleImportState::ImportAllowed;
- // For an implementation, We already made an implicit import (its interface).
- // Make and return the import decl to be added to the current TU.
- if (MDK == ModuleDeclKind::Implementation) {
- // Make the import decl for the interface.
- ImportDecl *Import =
- ImportDecl::Create(Context, CurContext, ModuleLoc, Mod, Path[0].second);
- // and return it to be added.
+ getASTContext().setNamedModuleForCodeGen(Mod);
+
+ // We already potentially made an implicit import (in the case of a module
+ // implementation unit importing its interface). Make this module visible
+ // and return the import decl to be added to the current TU.
+ if (Interface) {
+
+ VisibleModules.setVisible(Interface, ModuleLoc);
+
+ // Make the import decl for the interface in the impl module.
+ ImportDecl *Import = ImportDecl::Create(Context, CurContext, ModuleLoc,
+ Interface, Path[0].second);
+ CurContext->addDecl(Import);
+
+ // Sequence initialization of the imported module before that of the current
+ // module, if any.
+ Context.addModuleInitializer(ModuleScopes.back().Module, Import);
+ Mod->Imports.insert(Interface); // As if we imported it.
+ // Also save this as a shortcut to checking for decls in the interface
+ ThePrimaryInterface = Interface;
+ // If we made an implicit import of the module interface, then return the
+ // imported module decl.
return ConvertDeclToDeclGroup(Import);
}
- getASTContext().setNamedModuleForCodeGen(Mod);
-
- // FIXME: Create a ModuleDecl.
return nullptr;
}
@@ -427,19 +440,17 @@ Sema::ActOnPrivateModuleFragmentDecl(SourceLocation ModuleLoc,
Diag(ModuleScopes.back().BeginLoc, diag::note_previous_definition);
return nullptr;
- case Module::ModuleInterfaceUnit:
- break;
- }
-
- if (!ModuleScopes.back().ModuleInterface) {
+ case Module::ModuleImplementationUnit:
Diag(PrivateLoc, diag::err_private_module_fragment_not_module_interface);
Diag(ModuleScopes.back().BeginLoc,
diag::note_not_module_interface_add_export)
<< FixItHint::CreateInsertion(ModuleScopes.back().BeginLoc, "export ");
return nullptr;
+
+ case Module::ModuleInterfaceUnit:
+ break;
}
- // FIXME: Check this isn't a module interface partition.
// FIXME: Check that this translation unit does not import any partitions;
// such imports would violate [basic.link]/2's "shall be the only module unit"
// restriction.