diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Decl.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Frontend/FrontendActions.cpp | 17 | ||||
-rw-r--r-- | clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Lex/ModuleMap.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaModule.cpp | 42 |
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. |