[clang] 08f9578 - [C++20] [Modules] Don't generate global ctors/dtors for variables which are available externally

Chuanqi Xu via cfe-commits cfe-commits at lists.llvm.org
Sun Jan 8 18:49:47 PST 2023


Author: Chuanqi Xu
Date: 2023-01-09T10:48:43+08:00
New Revision: 08f957808e5f7e44b11d5e9015925955fe1e9d32

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

LOG: [C++20] [Modules] Don't generate global ctors/dtors for variables which are available externally

Closes https://github.com/llvm/llvm-project/issues/59765.

Currently we will generate the global ctor/dtor for variables in
importing modules. It will cause multiple initialization/destructions.
It makes no sense. This patch tries to not generate global ctor/dtor for
variables which are available externally. Note that the variables in
header units and clang modules won't be available externally by default.

Reviewed By: iains

Differential Revision: https://reviews.llvm.org/D140867

Added: 
    clang/test/CodeGenCXX/pr59765-modules-global-ctor-dtor.cppm

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/CodeGen/CodeGenModule.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b623d260dbb30..8718deab35bf2 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -345,6 +345,9 @@ Bug Fixes
   `Issue 59792 <https://github.com/llvm/llvm-project/issues/59792>`_
 - Fix an issue that makes Clang crash on lambda template parameters. This fixes
   `Issue 57960 <https://github.com/llvm/llvm-project/issues/57960>`_
+- Fix issue that the standard C++ modules importer will call global
+  constructor/destructor for the global varaibles in the importing modules.
+  This fixes `Issue 59765 <https://github.com/llvm/llvm-project/issues/59765>`_
 
 Improvements to Clang's diagnostics
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index fbf7c33254779..1239147ca27ff 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4824,7 +4824,13 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
 
   llvm::TrackingVH<llvm::Constant> Init;
   bool NeedsGlobalCtor = false;
+  // Whether the definition of the variable is available externally.
+  // If yes, we shouldn't emit the GloablCtor and GlobalDtor for the variable
+  // since this is the job for its original source.
+  bool IsDefinitionAvailableExternally =
+      getContext().GetGVALinkageForVariable(D) == GVA_AvailableExternally;
   bool NeedsGlobalDtor =
+      !IsDefinitionAvailableExternally &&
       D->needsDestruction(getContext()) == QualType::DK_cxx_destructor;
 
   const VarDecl *InitDecl;
@@ -4878,7 +4884,9 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
         if (InitDecl->hasFlexibleArrayInit(getContext()))
           ErrorUnsupported(D, "flexible array initializer");
         Init = EmitNullConstant(T);
-        NeedsGlobalCtor = true;
+
+        if (!IsDefinitionAvailableExternally)
+          NeedsGlobalCtor = true;
       } else {
         ErrorUnsupported(D, "static initializer");
         Init = llvm::UndefValue::get(getTypes().ConvertType(T));

diff  --git a/clang/test/CodeGenCXX/pr59765-modules-global-ctor-dtor.cppm b/clang/test/CodeGenCXX/pr59765-modules-global-ctor-dtor.cppm
new file mode 100644
index 0000000000000..c89bce5039a5d
--- /dev/null
+++ b/clang/test/CodeGenCXX/pr59765-modules-global-ctor-dtor.cppm
@@ -0,0 +1,58 @@
+// https://github.com/llvm/llvm-project/issues/59765
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/M.cppm -triple %itanium_abi_triple -emit-module-interface -o %t/M.pcm
+// RUN: %clang_cc1 -std=c++20 %t/M.pcm -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/M.cppm
+// RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fprebuilt-module-path=%t -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/Use.cpp
+//
+// Check that the behavior of header units is normal as headers.
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -xc++-user-header %t/foo.h -emit-header-unit -o %t/foo.pcm
+// RUN: %clang_cc1 -std=c++20 %t/UseHU.cpp -fmodule-file=%t/foo.pcm -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/UseHU.cpp
+
+//--- M.cppm
+export module M;
+export class A {
+public:
+    A();
+    ~A();
+    void use();
+};
+export A a;
+
+// CHECK: @_ZW1M1a = {{.*}}global %class.A zeroinitializer
+// CHECK: define{{.*}}void @__cxx_global_var_init()
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call{{.*}}void @_ZNW1M1AC1Ev({{.*}}@_ZW1M1a
+// CHECK-NEXT: call{{.*}}i32 @__cxa_atexit(ptr @_ZNW1M1AD1Ev, ptr @_ZW1M1a
+
+//--- Use.cpp
+import M;
+void use() {
+    a.use();
+}
+
+// CHECK-NOT: @_ZNW1M1AC1Ev
+// CHECK-NOT: @_ZNW1M1AD1Ev
+
+//--- foo.h
+class A {
+public:
+    A();
+    ~A();
+    void use();
+};
+A a;
+
+//--- UseHU.cpp
+import "foo.h";
+void use() {
+    a.use();
+}
+
+// CHECK: @a = {{.*}}global %class.A zeroinitializer
+// CHECK: define{{.*}}void @__cxx_global_var_init()
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call{{.*}}void @_ZN1AC1Ev({{.*}}@a
+// CHECK-NEXT: call{{.*}}i32 @__cxa_atexit(ptr @_ZN1AD1Ev, ptr @a


        


More information about the cfe-commits mailing list