iains updated this revision to Diff 434774.
iains added a comment.
rebased and tidied (still changes planned).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D126959/new/
https://reviews.llvm.org/D126959
Files:
clang/include/clang/Basic/Module.h
clang/include/clang/Lex/ModuleMap.h
clang/lib/AST/Decl.cpp
clang/lib/Frontend/FrontendActions.cpp
clang/lib/Lex/ModuleMap.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaModule.cpp
Index: clang/lib/Sema/SemaModule.cpp
===================================================================
--- clang/lib/Sema/SemaModule.cpp
+++ clang/lib/Sema/SemaModule.cpp
@@ -254,8 +254,8 @@
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 fir an implementation.
switch (MDK) {
case ModuleDeclKind::Interface:
case ModuleDeclKind::PartitionInterface: {
@@ -288,15 +288,20 @@
// 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) {
+
+ // First find the interface we need to import.
+ Interface = getModuleLoader().loadModule(ModuleLoc, {ModuleNameLoc},
+ Module::AllVisible,
+ /*IsInclusionDirective=*/false);
+ if (!Interface) {
Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName;
// Create an empty module interface unit for error recovery.
Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName,
GlobalModuleFragment);
- }
+ } else
+ // We found the interface, now create the implementation module
+ Mod = Map.createModuleForImplementationUnit(ModuleLoc, ModuleName,
+ GlobalModuleFragment);
} break;
case ModuleDeclKind::PartitionImplementation:
@@ -335,6 +340,19 @@
// statements, so imports are allowed.
ImportState = ModuleImportState::ImportAllowed;
+ // 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) {
+ // Make the import decl for the interface.
+ ImportDecl *Import = ImportDecl::Create(Context, CurContext, ModuleLoc,
+ Interface, Path[0].second);
+ VisibleModules.setVisible(Interface, ModuleLoc);
+
+ // If we made an implicit import of the module interface, then return the
+ // imported module decl.
+ return ConvertDeclToDeclGroup(Import);
+ }
// FIXME: Create a ModuleDecl.
return nullptr;
}
@@ -360,19 +378,17 @@
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.
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -1641,6 +1641,13 @@
if (NewM == OldM)
return false;
+ // A module implementation unit has visibility of the decls in its implicitly
+ // imported interface.
+ if (getLangOpts().CPlusPlusModules && NewM && OldM &&
+ NewM->Kind == Module::ModuleImplementationUnit &&
+ OldM->Kind == Module::ModuleInterfaceUnit)
+ return NewM->Name == OldM->Name;
+
bool NewIsModuleInterface = NewM && NewM->isModulePurview();
bool OldIsModuleInterface = OldM && OldM->isModulePurview();
if (NewIsModuleInterface || OldIsModuleInterface) {
Index: clang/lib/Lex/ModuleMap.cpp
===================================================================
--- clang/lib/Lex/ModuleMap.cpp
+++ clang/lib/Lex/ModuleMap.cpp
@@ -881,6 +881,34 @@
return Result;
}
+Module *ModuleMap::createModuleForImplementationUnit(SourceLocation Loc,
+ StringRef Name,
+ Module *GlobalModule) {
+ assert(LangOpts.CurrentModule == Name && "module name mismatch");
+ // The interface for this implementation must exist and be loaded.
+ assert(Modules[Name] && Modules[Name]->Kind == Module::ModuleInterfaceUnit &&
+ "creating implementation module without an interface");
+
+ auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false,
+ /*IsExplicit*/ false, NumCreatedModules++);
+ Result->Kind = Module::ModuleImplementationUnit;
+ SourceModule = Result;
+
+ // Reparent the current global module fragment as a submodule of this module.
+ for (auto &Submodule : PendingSubmodules) {
+ Submodule->setParent(Result);
+ Submodule.release(); // now owned by parent
+ }
+ PendingSubmodules.clear();
+
+ // Mark the main source file as being within the newly-created module so that
+ // declarations and macros are properly visibility-restricted to it.
+ auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
+ assert(MainFile && "no input file for module implementation");
+
+ return Result;
+}
+
Module *ModuleMap::createHeaderModule(StringRef Name,
ArrayRef<Module::Header> Headers) {
assert(LangOpts.CurrentModule == Name && "module name mismatch");
Index: clang/lib/Frontend/FrontendActions.cpp
===================================================================
--- clang/lib/Frontend/FrontendActions.cpp
+++ clang/lib/Frontend/FrontendActions.cpp
@@ -831,6 +831,8 @@
return "Module Map Module";
case Module::ModuleInterfaceUnit:
return "Interface Unit";
+ case Module::ModuleImplementationUnit:
+ return "Implementation Unit (should never be serialized)";
case Module::ModulePartitionInterface:
return "Partition Interface";
case Module::ModulePartitionImplementation:
Index: clang/lib/AST/Decl.cpp
===================================================================
--- clang/lib/AST/Decl.cpp
+++ clang/lib/AST/Decl.cpp
@@ -1565,6 +1565,7 @@
return nullptr;
case Module::ModuleInterfaceUnit:
+ case Module::ModuleImplementationUnit:
case Module::ModulePartitionInterface:
case Module::ModulePartitionImplementation:
return M;
Index: clang/include/clang/Lex/ModuleMap.h
===================================================================
--- clang/include/clang/Lex/ModuleMap.h
+++ clang/include/clang/Lex/ModuleMap.h
@@ -561,6 +561,14 @@
Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name,
Module *GlobalModule);
+ /// Create a new module for a C++ module implementation unit.
+ /// The interface module for this implementation (implicitly imported) must
+ /// exist and be loaded and present in the modules map.
+ ///
+ /// \returns The newly-created module.
+ Module *createModuleForImplementationUnit(SourceLocation Loc, StringRef Name,
+ Module *GlobalModule);
+
/// Create a header module from the specified list of headers.
Module *createHeaderModule(StringRef Name, ArrayRef<Module::Header> Headers);
Index: clang/include/clang/Basic/Module.h
===================================================================
--- clang/include/clang/Basic/Module.h
+++ clang/include/clang/Basic/Module.h
@@ -109,6 +109,9 @@
/// This is a C++20 module interface unit.
ModuleInterfaceUnit,
+ /// This is a C++20 module implementation unit.
+ ModuleImplementationUnit,
+
/// This is a C++ 20 header unit.
ModuleHeaderUnit,
@@ -159,9 +162,16 @@
/// Does this Module scope describe part of the purview of a named C++ module?
bool isModulePurview() const {
- return Kind == ModuleInterfaceUnit || Kind == ModulePartitionInterface ||
- Kind == ModulePartitionImplementation ||
- Kind == PrivateModuleFragment;
+ switch (Kind) {
+ case ModuleInterfaceUnit:
+ case ModuleImplementationUnit:
+ case ModulePartitionInterface:
+ case ModulePartitionImplementation:
+ case PrivateModuleFragment:
+ return true;
+ default:
+ return false;
+ }
}
/// Does this Module scope describe a fragment of the global module within
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits