aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaModule.cpp
diff options
context:
space:
mode:
authorIain Sandoe <iain@sandoe.co.uk>2020-09-20 09:29:14 +0100
committerIain Sandoe <iain@sandoe.co.uk>2022-03-25 09:17:14 +0000
commit6c0e60e884a20016ccc0d7c7e6f06df089a0de86 (patch)
tree9e39107ec89a3a8d97bb0b3583c7000725ec8c24 /clang/lib/Sema/SemaModule.cpp
parentc48b4641c7baf9f7280d352c13299b3aa0203179 (diff)
downloadllvm-6c0e60e884a20016ccc0d7c7e6f06df089a0de86.zip
llvm-6c0e60e884a20016ccc0d7c7e6f06df089a0de86.tar.gz
llvm-6c0e60e884a20016ccc0d7c7e6f06df089a0de86.tar.bz2
[C++20][Modules][HU 1/5] Introduce header units as a module type.
This is the first in a series of patches that introduce C++20 importable header units. These differ from clang header modules in that: (a) they are identifiable by an internal name (b) they represent the top level source for a single header - although that might include or import other headers. We name importable header units with the path by which they are specified (although that need not be the absolute path for the file). So "foo/bar.h" would have a name "foo/bar.h". Header units are made a separate module type so that we can deal with diagnosing places where they are permitted but a named module is not. Differential Revision: https://reviews.llvm.org/D121095
Diffstat (limited to 'clang/lib/Sema/SemaModule.cpp')
-rw-r--r--clang/lib/Sema/SemaModule.cpp42
1 files changed, 41 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 9de95e2..a115834 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -97,6 +97,38 @@ Sema::ActOnGlobalModuleFragmentDecl(SourceLocation ModuleLoc) {
return nullptr;
}
+void Sema::HandleStartOfHeaderUnit() {
+ assert(getLangOpts().CPlusPlusModules &&
+ "Header units are only valid for C++20 modules");
+ SourceLocation StartOfTU =
+ SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+
+ StringRef HUName = getLangOpts().CurrentModule;
+ if (HUName.empty()) {
+ HUName = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID())->getName();
+ const_cast<LangOptions &>(getLangOpts()).CurrentModule = HUName.str();
+ }
+
+ auto &Map = PP.getHeaderSearchInfo().getModuleMap();
+ // TODO: Make the C++20 header lookup independent.
+ Module::Header H{getLangOpts().CurrentModule, getLangOpts().CurrentModule,
+ SourceMgr.getFileEntryForID(SourceMgr.getMainFileID())};
+ Module *Mod = Map.createHeaderUnit(StartOfTU, HUName, H);
+ assert(Mod && "module creation should not fail");
+ ModuleScopes.push_back({}); // No GMF
+ ModuleScopes.back().BeginLoc = StartOfTU;
+ ModuleScopes.back().Module = Mod;
+ ModuleScopes.back().ModuleInterface = true;
+ ModuleScopes.back().IsPartition = false;
+ VisibleModules.setVisible(Mod, StartOfTU);
+
+ // From now on, we have an owning module for all declarations we see.
+ // All of these are implicitly exported.
+ auto *TU = Context.getTranslationUnitDecl();
+ TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::Visible);
+ TU->setLocalOwningModule(Mod);
+}
+
Sema::DeclGroupPtrTy
Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
ModuleDeclKind MDK, ModuleIdPath Path,
@@ -149,6 +181,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
return nullptr;
case LangOptions::CMK_HeaderModule:
+ case LangOptions::CMK_HeaderUnit:
Diag(ModuleLoc, diag::err_module_decl_in_header_module);
return nullptr;
}
@@ -310,6 +343,7 @@ Sema::ActOnPrivateModuleFragmentDecl(SourceLocation ModuleLoc,
case Module::GlobalModuleFragment:
case Module::ModulePartitionImplementation:
case Module::ModulePartitionInterface:
+ case Module::ModuleHeaderUnit:
Diag(PrivateLoc, diag::err_private_module_fragment_not_module);
return nullptr;
@@ -480,7 +514,13 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
Mod->Kind == Module::ModuleKind::ModulePartitionImplementation) {
Diag(ExportLoc, diag::err_export_partition_impl)
<< SourceRange(ExportLoc, Path.back().second);
- } else if (!ModuleScopes.empty() && ModuleScopes.back().ModuleInterface) {
+ } else if (!ModuleScopes.empty() &&
+ (ModuleScopes.back().ModuleInterface ||
+ (getLangOpts().CPlusPlusModules &&
+ ModuleScopes.back().Module->isGlobalModule()))) {
+ assert((!ModuleScopes.back().Module->isGlobalModule() ||
+ Mod->Kind == Module::ModuleKind::ModuleHeaderUnit) &&
+ "should only be importing a header unit into the GMF");
// Re-export the module if the imported module is exported.
// Note that we don't need to add re-exported module to Imports field
// since `Exports` implies the module is imported already.