diff options
author | Iain Sandoe <iain@sandoe.co.uk> | 2021-02-07 17:08:42 +0000 |
---|---|---|
committer | Iain Sandoe <iain@sandoe.co.uk> | 2022-02-25 09:33:14 +0000 |
commit | 6114491441700cc8a614d284407e9a6e9bf74751 (patch) | |
tree | 91a6adb55188a1200597bc15ef93d1716aa3acec /clang/lib/Sema/SemaModule.cpp | |
parent | 2cd675249d8d1c570d7f1ea059f40aecb0f68d74 (diff) | |
download | llvm-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.cpp | 70 |
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); |