Skip to content

Commit cbbe555

Browse files
committed
[C++20] [Modules] Generate init calls for the modules imported in GMF or PMF
I just found that we didn't handle the imports in GMF of PMF when we're generating the init functions for the current module unit. This looks like a simple oversight and I'm going to fix that in this patch directly.
1 parent 9511432 commit cbbe555

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

clang/lib/CodeGen/CGDeclCXX.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,10 @@ void CodeGenModule::EmitCXXThreadLocalInitFunc() {
655655
*/
656656

657657
void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) {
658+
assert(Primary->isInterfaceOrPartition() &&
659+
"The function should only be called for C++20 named module interface"
660+
" or partition.");
661+
658662
while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
659663
CXXGlobalInits.pop_back();
660664

@@ -669,6 +673,18 @@ void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) {
669673
// Ones that we only import.
670674
for (Module *M : Primary->Imports)
671675
AllImports.push_back(M);
676+
// Ones that we import in the global module fragment or the private module
677+
// fragment.
678+
llvm::for_each(Primary->submodules(), [&AllImports](Module *SubM) {
679+
assert((SubM->isGlobalModule() || SubM->isPrivateModule()) &&
680+
"The sub modules of C++20 module unit should only be global module "
681+
"fragments or private module framents.");
682+
assert(SubM->Exports.empty() &&
683+
"The global mdoule fragments and the private module fragments are "
684+
"not allowed to export import modules.");
685+
for (Module *M : SubM->Imports)
686+
AllImports.push_back(M);
687+
});
672688

673689
SmallVector<llvm::Function *, 8> ModuleInits;
674690
for (Module *M : AllImports) {

clang/test/CodeGenCXX/module-initializer-guard-elision.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@
2727
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 S.pcm -S -emit-llvm \
2828
// RUN: -o - | FileCheck %s --check-prefix=CHECK-S
2929

30+
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 T.cpp \
31+
// RUN: -emit-module-interface -fmodule-file=S=S.pcm -fmodule-file=R=R.pcm -o T.pcm
32+
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 T.pcm -S -emit-llvm \
33+
// RUN: -o - | FileCheck %s --check-prefix=CHECK-T
34+
35+
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 U.cpp \
36+
// RUN: -emit-module-interface -fmodule-file=T=T.pcm -fmodule-file=R=R.pcm -o U.pcm
37+
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 U.pcm -S -emit-llvm \
38+
// RUN: -o - | FileCheck %s --check-prefix=CHECK-U
39+
3040
// Testing cases where we can elide the module initializer guard variable.
3141

3242
// This module has no global inits and does not import any other module
@@ -96,3 +106,25 @@ export import R;
96106
// CHECK-S: define void @_ZGIW1S
97107
// CHECK-S: store i8 1, ptr @_ZGIW1S__in_chrg
98108
// CHECK-S: call{{.*}}@_ZGIW1R
109+
110+
// The module itself doesn't have a global init and it doesn't import any module.
111+
// But the global module fragment imports a module that needs an init. So needs a guard.
112+
//--- T.cpp
113+
module;
114+
import S;
115+
export module T;
116+
117+
// CHECK-T: define void @_ZGIW1T
118+
// CHECK-T: store i8 1, ptr @_ZGIW1T__in_chrg
119+
// CHECK-T: call{{.*}}@_ZGIW1S
120+
121+
// The module itself doesn't have a global init and it doesn't import any module.
122+
// But the private module fragment imports a module that needs an init. So needs a guard.
123+
//--- U.cpp
124+
export module U;
125+
module :private;
126+
import T;
127+
128+
// CHECK-U: define void @_ZGIW1U
129+
// CHECK-U: store i8 1, ptr @_ZGIW1U__in_chrg
130+
// CHECK-U: call{{.*}}@_ZGIW1T

0 commit comments

Comments
 (0)