aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaModule.cpp
diff options
context:
space:
mode:
authorIain Sandoe <iain@sandoe.co.uk>2021-02-07 17:08:42 +0000
committerIain Sandoe <iain@sandoe.co.uk>2022-02-25 09:33:14 +0000
commit6114491441700cc8a614d284407e9a6e9bf74751 (patch)
tree91a6adb55188a1200597bc15ef93d1716aa3acec /clang/lib/Sema/SemaModule.cpp
parent2cd675249d8d1c570d7f1ea059f40aecb0f68d74 (diff)
downloadllvm-6114491441700cc8a614d284407e9a6e9bf74751.zip
llvm-6114491441700cc8a614d284407e9a6e9bf74751.tar.gz
llvm-6114491441700cc8a614d284407e9a6e9bf74751.tar.bz2
[C++20][Modules][4/8] Handle generation of partition implementation CMIs.
Partition implementations are special, they generate a CMI, but it does not have an 'export' line, and we cannot export anything from the it [that is it can only make decls available to other members of the owning module, not to importers of that]. Add initial testcases for partition handling, derived from the examples in Section 10 of the C++20 standard, which identifies what should be accepted and/or rejected. Differential Revision: https://reviews.llvm.org/D118587
Diffstat (limited to 'clang/lib/Sema/SemaModule.cpp')
-rw-r--r--clang/lib/Sema/SemaModule.cpp70
1 files changed, 42 insertions, 28 deletions
diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index a797644..b251507 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -110,9 +110,24 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
// module state;
ImportState = ModuleImportState::NotACXX20Module;
- // A module implementation unit requires that we are not compiling a module
- // of any kind. A module interface unit requires that we are not compiling a
- // module map.
+ bool IsPartition = !Partition.empty();
+ if (IsPartition)
+ switch (MDK) {
+ case ModuleDeclKind::Implementation:
+ MDK = ModuleDeclKind::PartitionImplementation;
+ break;
+ case ModuleDeclKind::Interface:
+ MDK = ModuleDeclKind::PartitionInterface;
+ break;
+ default:
+ llvm_unreachable("how did we get a partition type set?");
+ }
+
+ // A (non-partition) module implementation unit requires that we are not
+ // compiling a module of any kind. A partition implementation emits an
+ // interface (and the AST for the implementation), which will subsequently
+ // be consumed to emit a binary.
+ // A module interface unit requires that we are not compiling a module map.
switch (getLangOpts().getCompilingModule()) {
case LangOptions::CMK_None:
// It's OK to compile a module interface as a normal translation unit.
@@ -123,7 +138,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
break;
// We were asked to compile a module interface unit but this is a module
- // implementation unit. That indicates the 'export' is missing.
+ // implementation unit.
Diag(ModuleLoc, diag::err_module_interface_implementation_mismatch)
<< FixItHint::CreateInsertion(ModuleLoc, "export ");
MDK = ModuleDeclKind::Interface;
@@ -180,7 +195,6 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
// modules, the dots here are just another character that can appear in a
// module name.
std::string ModuleName = stringFromPath(Path);
- bool IsPartition = !Partition.empty();
if (IsPartition) {
ModuleName += ":";
ModuleName += stringFromPath(Partition);
@@ -202,7 +216,8 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
Module *Mod;
switch (MDK) {
- case ModuleDeclKind::Interface: {
+ case ModuleDeclKind::Interface:
+ 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)) {
@@ -219,36 +234,36 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
// Create a Module for the module that we're defining.
Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName,
GlobalModuleFragment);
- if (IsPartition)
+ if (MDK == ModuleDeclKind::PartitionInterface)
Mod->Kind = Module::ModulePartitionInterface;
assert(Mod && "module creation should not fail");
break;
}
- case ModuleDeclKind::Implementation:
+ case ModuleDeclKind::Implementation: {
std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc(
PP.getIdentifierInfo(ModuleName), Path[0].second);
- if (IsPartition) {
- // Create an interface, but note that it is an implementation
- // unit.
+ // C++20 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.
+ Mod = getModuleLoader().loadModule(ModuleLoc, {ModuleNameLoc},
+ Module::AllVisible,
+ /*IsInclusionDirective=*/false);
+ 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->Kind = Module::ModulePartitionImplementation;
- } else {
- // C++20 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.
- Mod = getModuleLoader().loadModule(ModuleLoc, {ModuleNameLoc},
- Module::AllVisible,
- /*IsInclusionDirective=*/false);
- 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);
- }
}
+ } break;
+
+ case ModuleDeclKind::PartitionImplementation:
+ // Create an interface, but note that it is an implementation
+ // unit.
+ Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName,
+ GlobalModuleFragment);
+ Mod->Kind = Module::ModulePartitionImplementation;
break;
}
@@ -264,8 +279,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
// Switch from the global module fragment (if any) to the named module.
ModuleScopes.back().BeginLoc = StartLoc;
ModuleScopes.back().Module = Mod;
- ModuleScopes.back().ModuleInterface =
- (MDK != ModuleDeclKind::Implementation || IsPartition);
+ ModuleScopes.back().ModuleInterface = MDK != ModuleDeclKind::Implementation;
ModuleScopes.back().IsPartition = IsPartition;
VisibleModules.setVisible(Mod, ModuleLoc);