[clang] cbbe555 - [C++20] [Modules] Generate init calls for the modules imported in GMF or PMF

Chuanqi Xu via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 29 07:17:26 PDT 2023


Author: Chuanqi Xu
Date: 2023-09-29T22:16:31+08:00
New Revision: cbbe55590414d5b698dcb7f7125f0508b29cadf8

URL: https://github.com/llvm/llvm-project/commit/cbbe55590414d5b698dcb7f7125f0508b29cadf8
DIFF: https://github.com/llvm/llvm-project/commit/cbbe55590414d5b698dcb7f7125f0508b29cadf8.diff

LOG: [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.

Added: 
    

Modified: 
    clang/lib/CodeGen/CGDeclCXX.cpp
    clang/test/CodeGenCXX/module-initializer-guard-elision.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index c576128e8eb6c62..8a05e4893196ad2 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -655,6 +655,10 @@ void CodeGenModule::EmitCXXThreadLocalInitFunc() {
 */
 
 void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) {
+  assert(Primary->isInterfaceOrPartition() &&
+         "The function should only be called for C++20 named module interface"
+         " or partition.");
+
   while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
     CXXGlobalInits.pop_back();
 
@@ -669,6 +673,18 @@ void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) {
   // Ones that we only import.
   for (Module *M : Primary->Imports)
     AllImports.push_back(M);
+  // Ones that we import in the global module fragment or the private module
+  // fragment.
+  llvm::for_each(Primary->submodules(), [&AllImports](Module *SubM) {
+    assert((SubM->isGlobalModule() || SubM->isPrivateModule()) &&
+           "The sub modules of C++20 module unit should only be global module "
+           "fragments or private module framents.");
+    assert(SubM->Exports.empty() &&
+           "The global mdoule fragments and the private module fragments are "
+           "not allowed to export import modules.");
+    for (Module *M : SubM->Imports)
+      AllImports.push_back(M);
+  });
 
   SmallVector<llvm::Function *, 8> ModuleInits;
   for (Module *M : AllImports) {

diff  --git a/clang/test/CodeGenCXX/module-initializer-guard-elision.cpp b/clang/test/CodeGenCXX/module-initializer-guard-elision.cpp
index 58189ca949d8e01..bae7c930b51029c 100644
--- a/clang/test/CodeGenCXX/module-initializer-guard-elision.cpp
+++ b/clang/test/CodeGenCXX/module-initializer-guard-elision.cpp
@@ -27,6 +27,16 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 S.pcm -S -emit-llvm \
 // RUN:    -o - | FileCheck %s --check-prefix=CHECK-S
 
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 T.cpp \
+// RUN:    -emit-module-interface -fmodule-file=S=S.pcm -fmodule-file=R=R.pcm -o T.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 T.pcm -S -emit-llvm \
+// RUN:    -o - | FileCheck %s --check-prefix=CHECK-T
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 U.cpp \
+// RUN:    -emit-module-interface -fmodule-file=T=T.pcm -fmodule-file=R=R.pcm -o U.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 U.pcm -S -emit-llvm \
+// RUN:    -o - | FileCheck %s --check-prefix=CHECK-U
+
 // Testing cases where we can elide the module initializer guard variable.
 
 // This module has no global inits and does not import any other module
@@ -96,3 +106,25 @@ export import R;
 // CHECK-S: define void @_ZGIW1S
 // CHECK-S: store i8 1, ptr @_ZGIW1S__in_chrg
 // CHECK-S: call{{.*}}@_ZGIW1R
+
+// The module itself doesn't have a global init and it doesn't import any module.
+// But the global module fragment imports a module that needs an init. So needs a guard.
+//--- T.cpp
+module;
+import S;
+export module T;
+
+// CHECK-T: define void @_ZGIW1T
+// CHECK-T: store i8 1, ptr @_ZGIW1T__in_chrg
+// CHECK-T: call{{.*}}@_ZGIW1S
+
+// The module itself doesn't have a global init and it doesn't import any module.
+// But the private module fragment imports a module that needs an init. So needs a guard.
+//--- U.cpp
+export module U;
+module :private;
+import T;
+
+// CHECK-U: define void @_ZGIW1U
+// CHECK-U: store i8 1, ptr @_ZGIW1U__in_chrg
+// CHECK-U: call{{.*}}@_ZGIW1T


        


More information about the cfe-commits mailing list