aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Decl.cpp4
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp4
-rw-r--r--clang/lib/Frontend/FrontendActions.cpp17
-rw-r--r--clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp2
-rw-r--r--clang/lib/Lex/ModuleMap.cpp13
-rw-r--r--clang/lib/Parse/Parser.cpp5
-rw-r--r--clang/lib/Sema/Sema.cpp10
-rw-r--r--clang/lib/Sema/SemaModule.cpp42
8 files changed, 89 insertions, 8 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 6b68e51..9b8585b 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1561,6 +1561,7 @@ Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const {
case Module::ModulePartitionImplementation:
return M;
+ case Module::ModuleHeaderUnit:
case Module::GlobalModuleFragment: {
// External linkage declarations in the global module have no owning module
// for linkage purposes. But internal linkage declarations in the global
@@ -1576,7 +1577,8 @@ Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const {
InternalLinkage = !ND->hasExternalFormalLinkage();
else
InternalLinkage = isInAnonymousNamespace();
- return InternalLinkage ? M->Parent : nullptr;
+ return InternalLinkage ? M->Kind == Module::ModuleHeaderUnit ? M : M->Parent
+ : nullptr;
}
case Module::PrivateModuleFragment:
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index cac443d..e18c7ed 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2420,6 +2420,7 @@ static const auto &getFrontendActionTable() {
{frontend::GenerateModule, OPT_emit_module},
{frontend::GenerateModuleInterface, OPT_emit_module_interface},
{frontend::GenerateHeaderModule, OPT_emit_header_module},
+ {frontend::GenerateHeaderUnit, OPT_emit_header_unit},
{frontend::GeneratePCH, OPT_emit_pch},
{frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs},
{frontend::InitOnly, OPT_init_only},
@@ -2436,7 +2437,7 @@ static const auto &getFrontendActionTable() {
{frontend::MigrateSource, OPT_migrate},
{frontend::RunPreprocessorOnly, OPT_Eonly},
{frontend::PrintDependencyDirectivesSourceMinimizerOutput,
- OPT_print_dependency_directives_minimized_source},
+ OPT_print_dependency_directives_minimized_source},
};
return Table;
@@ -4160,6 +4161,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
case frontend::GenerateModule:
case frontend::GenerateModuleInterface:
case frontend::GenerateHeaderModule:
+ case frontend::GenerateHeaderUnit:
case frontend::GeneratePCH:
case frontend::GenerateInterfaceStubs:
case frontend::ParseSyntaxOnly:
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index 65cbc946..2cd2096 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -336,6 +336,21 @@ GenerateHeaderModuleAction::CreateOutputFile(CompilerInstance &CI,
return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
}
+bool GenerateHeaderUnitAction::BeginSourceFileAction(CompilerInstance &CI) {
+ if (!CI.getLangOpts().CPlusPlusModules) {
+ CI.getDiagnostics().Report(diag::err_module_interface_requires_cpp_modules);
+ return false;
+ }
+ CI.getLangOpts().setCompilingModule(LangOptions::CMK_HeaderUnit);
+ return GenerateModuleAction::BeginSourceFileAction(CI);
+}
+
+std::unique_ptr<raw_pwrite_stream>
+GenerateHeaderUnitAction::CreateOutputFile(CompilerInstance &CI,
+ StringRef InFile) {
+ return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
+}
+
SyntaxOnlyAction::~SyntaxOnlyAction() {
}
@@ -818,6 +833,8 @@ static StringRef ModuleKindName(Module::ModuleKind MK) {
return "Partition Interface";
case Module::ModulePartitionImplementation:
return "Partition Implementation";
+ case Module::ModuleHeaderUnit:
+ return "Header Unit";
case Module::GlobalModuleFragment:
return "Global Module Fragment";
case Module::PrivateModuleFragment:
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 4525a2c..6927d2e 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -67,6 +67,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
return std::make_unique<GenerateModuleInterfaceAction>();
case GenerateHeaderModule:
return std::make_unique<GenerateHeaderModuleAction>();
+ case GenerateHeaderUnit:
+ return std::make_unique<GenerateHeaderUnitAction>();
case GeneratePCH: return std::make_unique<GeneratePCHAction>();
case GenerateInterfaceStubs:
return std::make_unique<GenerateInterfaceStubsAction>();
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index a5eca40..75a0e6b 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -905,6 +905,19 @@ Module *ModuleMap::createHeaderModule(StringRef Name,
return Result;
}
+Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
+ Module::Header H) {
+ assert(LangOpts.CurrentModule == Name && "module name mismatch");
+ assert(!Modules[Name] && "redefining existing module");
+
+ auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false,
+ /*IsExplicit*/ false, NumCreatedModules++);
+ Result->Kind = Module::ModuleHeaderUnit;
+ Modules[Name] = SourceModule = Result;
+ addHeader(Result, H, NormalHeader);
+ return Result;
+}
+
/// For a framework module, infer the framework against which we
/// should link.
static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 8bba3d4..9c8892e 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -2468,8 +2468,9 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc,
break;
case Sema::ModuleImportState::GlobalFragment:
// We can only have pre-processor directives in the global module
- // fragment. We can, however have a header unit import here.
- if (!HeaderUnit)
+ // fragment. We cannot import a named modules here, however we have a
+ // header unit import.
+ if (!HeaderUnit || HeaderUnit->Kind != Module::ModuleKind::ModuleHeaderUnit)
Diag(ImportLoc, diag::err_import_in_wrong_fragment) << IsPartition << 0;
else
SeenError = false;
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index b0e47c0e..52f38c0 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1030,9 +1030,13 @@ void Sema::emitAndClearUnusedLocalTypedefWarnings() {
/// is parsed. Note that the ASTContext may have already injected some
/// declarations.
void Sema::ActOnStartOfTranslationUnit() {
- if (getLangOpts().ModulesTS &&
- (getLangOpts().getCompilingModule() == LangOptions::CMK_ModuleInterface ||
- getLangOpts().getCompilingModule() == LangOptions::CMK_None)) {
+ if (getLangOpts().CPlusPlusModules &&
+ getLangOpts().getCompilingModule() == LangOptions::CMK_HeaderUnit)
+ HandleStartOfHeaderUnit();
+ else if (getLangOpts().ModulesTS &&
+ (getLangOpts().getCompilingModule() ==
+ LangOptions::CMK_ModuleInterface ||
+ getLangOpts().getCompilingModule() == LangOptions::CMK_None)) {
// We start in an implied global module fragment.
SourceLocation StartOfTU =
SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
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.