diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2944,8 +2944,10 @@ SourceLocation SemiLoc); enum class ModuleDeclKind { - Interface, ///< 'export module X;' - Implementation, ///< 'module X;' + Interface, ///< 'export module X;' + Implementation, ///< 'module X;' + PartitionInterface, ///< 'export module X:Y;' + PartitionImplementation, ///< 'module X:Y;' }; /// The parser has processed a module-declaration that begins the definition diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -100,9 +100,21 @@ assert((getLangOpts().ModulesTS || getLangOpts().CPlusPlusModules) && "should only have module decl in Modules TS or C++20"); - // 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: assert (0 && "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. @@ -113,7 +125,7 @@ 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; @@ -162,11 +174,10 @@ } } - // Flatten the dots in a module name. Unlike Clang's hierarchical module map - // modules, the dots here are just another character that can appear in a - // module name. + // Flatten the periods in a module name. Unlike Clang's hierarchical module + // map modules, the dots here are just another character that can appear in + // a module name. std::string ModuleName = stringFromPath(NamePath); - bool IsPartition = !Partition.empty(); if (IsPartition) { ModuleName += ":"; ModuleName += stringFromPath(Partition); @@ -188,7 +199,8 @@ 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)) { @@ -205,22 +217,15 @@ // 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: - std::pair ModuleNameLoc( + case ModuleDeclKind::Implementation: { + std::pair ModuleNameLoc( PP.getIdentifierInfo(ModuleName), NamePath[0].second); - if (IsPartition) { - // Create an interface, but note that it is an implementation - // unit. - 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- @@ -236,6 +241,14 @@ } } 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; } if (!GlobalModuleFragment) { @@ -250,8 +263,7 @@ // 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);