aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaModule.cpp
diff options
context:
space:
mode:
authorChuanqi Xu <yedeng.yd@linux.alibaba.com>2023-03-03 10:31:48 +0800
committerChuanqi Xu <yedeng.yd@linux.alibaba.com>2023-03-03 10:31:48 +0800
commitbf52ead24ca4fe1b73bceec7bba3abfe15541649 (patch)
tree356336638558c02b5ad2f31be9060cd1642c2985 /clang/lib/Sema/SemaModule.cpp
parent87cf39aa349b83ae3b7d16c30ac7a8ffa0ad098c (diff)
downloadllvm-bf52ead24ca4fe1b73bceec7bba3abfe15541649.zip
llvm-bf52ead24ca4fe1b73bceec7bba3abfe15541649.tar.gz
llvm-bf52ead24ca4fe1b73bceec7bba3abfe15541649.tar.bz2
[C++20] [Modules] Support to export declarations in language linkage
Close https://github.com/llvm/llvm-project/issues/60405 See the discussion in the above link for the background. What the patch does: - Rename `Module::ModuleKind::GlobalModuleFragment` to `Module::ModuleKind::ExplicitGlobalModuleFragment`. - Add another module kind `ImplicitGlobalModuleFragment` to `ModuleKind`. - Create an implicit global module fragment for the language linkage declarations inside a module purview. - If the language linkage lives inside the scope of an export decl, the created modules is marked as exported to outer modules. - In fact, Sema will only create at most 2 implicit global module fragments to avoid creating a lot of unnecessary modules in the edging case. Reviewed By: iains Differential Revision: https://reviews.llvm.org/D144367
Diffstat (limited to 'clang/lib/Sema/SemaModule.cpp')
-rw-r--r--clang/lib/Sema/SemaModule.cpp50
1 files changed, 39 insertions, 11 deletions
diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 59891ec..8c120d2 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -233,7 +233,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
}
assert((!getLangOpts().CPlusPlusModules ||
- SeenGMF == (bool)this->GlobalModuleFragment) &&
+ SeenGMF == (bool)this->TheGlobalModuleFragment) &&
"mismatched global module state");
// In C++20, the module-declaration must be the first declaration if there
@@ -358,7 +358,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
break;
}
- if (!this->GlobalModuleFragment) {
+ if (!this->TheGlobalModuleFragment) {
ModuleScopes.push_back({});
if (getLangOpts().ModulesLocalVisibility)
ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules);
@@ -408,10 +408,11 @@ Sema::ActOnPrivateModuleFragmentDecl(SourceLocation ModuleLoc,
// C++20 [basic.link]/2:
// A private-module-fragment shall appear only in a primary module
// interface unit.
- switch (ModuleScopes.empty() ? Module::GlobalModuleFragment
+ switch (ModuleScopes.empty() ? Module::ExplicitGlobalModuleFragment
: ModuleScopes.back().Module->Kind) {
case Module::ModuleMapModule:
- case Module::GlobalModuleFragment:
+ case Module::ExplicitGlobalModuleFragment:
+ case Module::ImplicitGlobalModuleFragment:
case Module::ModulePartitionImplementation:
case Module::ModulePartitionInterface:
case Module::ModuleHeaderUnit:
@@ -958,25 +959,52 @@ Decl *Sema::ActOnFinishExportDecl(Scope *S, Decl *D, SourceLocation RBraceLoc) {
Module *Sema::PushGlobalModuleFragment(SourceLocation BeginLoc) {
// We shouldn't create new global module fragment if there is already
// one.
- if (!GlobalModuleFragment) {
+ if (!TheGlobalModuleFragment) {
ModuleMap &Map = PP.getHeaderSearchInfo().getModuleMap();
- GlobalModuleFragment = Map.createGlobalModuleFragmentForModuleUnit(
+ TheGlobalModuleFragment = Map.createGlobalModuleFragmentForModuleUnit(
BeginLoc, getCurrentModule());
}
- assert(GlobalModuleFragment && "module creation should not fail");
+ assert(TheGlobalModuleFragment && "module creation should not fail");
// Enter the scope of the global module.
- ModuleScopes.push_back({BeginLoc, GlobalModuleFragment,
+ ModuleScopes.push_back({BeginLoc, TheGlobalModuleFragment,
/*ModuleInterface=*/false,
/*OuterVisibleModules=*/{}});
- VisibleModules.setVisible(GlobalModuleFragment, BeginLoc);
+ VisibleModules.setVisible(TheGlobalModuleFragment, BeginLoc);
- return GlobalModuleFragment;
+ return TheGlobalModuleFragment;
}
void Sema::PopGlobalModuleFragment() {
- assert(!ModuleScopes.empty() && getCurrentModule()->isGlobalModule() &&
+ assert(!ModuleScopes.empty() &&
+ getCurrentModule()->isExplicitGlobalModule() &&
+ "left the wrong module scope, which is not global module fragment");
+ ModuleScopes.pop_back();
+}
+
+Module *Sema::PushImplicitGlobalModuleFragment(SourceLocation BeginLoc,
+ bool IsExported) {
+ Module **M = IsExported ? &TheExportedImplicitGlobalModuleFragment
+ : &TheImplicitGlobalModuleFragment;
+ if (!*M) {
+ ModuleMap &Map = PP.getHeaderSearchInfo().getModuleMap();
+ *M = Map.createImplicitGlobalModuleFragmentForModuleUnit(
+ BeginLoc, IsExported, getCurrentModule());
+ }
+ assert(*M && "module creation should not fail");
+
+ // Enter the scope of the global module.
+ ModuleScopes.push_back({BeginLoc, *M,
+ /*ModuleInterface=*/false,
+ /*OuterVisibleModules=*/{}});
+ VisibleModules.setVisible(*M, BeginLoc);
+ return *M;
+}
+
+void Sema::PopImplicitGlobalModuleFragment() {
+ assert(!ModuleScopes.empty() &&
+ getCurrentModule()->isImplicitGlobalModule() &&
"left the wrong module scope, which is not global module fragment");
ModuleScopes.pop_back();
}