wolfgangp created this revision.
wolfgangp added reviewers: rnk, jyu2.
wolfgangp requested review of this revision.

Commit c19f4f8069 
<https://github.com/llvm/llvm-project/commit/c19f4f8069722f6804086d4438a0254104242c46>
 caused some ordered dynamic initialization of static member variables to be 
treated like unordered initialization, i.e. put into global_ctors. This caused 
issues in some configurations, specifically when init_array is not used. This 
patch proposes to restrict this behaviour to the Microsoft ABI, where it is 
apparently necessary for correctness.

2 existing test cases are affected by this change.

This fixes PR50266.


https://reviews.llvm.org/D103495

Files:
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp
  clang/test/CodeGenCXX/static-init-order.cpp
  clang/test/Modules/initializers.cpp


Index: clang/test/Modules/initializers.cpp
===================================================================
--- clang/test/Modules/initializers.cpp
+++ clang/test/Modules/initializers.cpp
@@ -232,9 +232,9 @@
 // CHECK-IMPORT: load {{.*}} (i64* @_ZGV
 // CHECK-IMPORT: store {{.*}}, i32* @[[D]],
 
-
 // CHECK-IMPORT: define {{.*}} @[[TU_INIT]]()
 // CHECK-IMPORT: call void @[[A_INIT]]()
+// CHECK-IMPORT: call void @[[B_INIT]]()
 
 // CHECK-IMPORT: define {{.*}} @__tls_init()
 // CHECK-IMPORT: call void @[[C_INIT]]()
Index: clang/test/CodeGenCXX/static-init-order.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/static-init-order.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 %s -std=c++17 -triple %itanium_abi_triple -emit-llvm -o - | 
FileCheck %s
+// Make sure we generate a single initialization routine and put its address 
into the
+// global_ctors. Check that the initialization routine makes 2 calls to 
individual
+// initializer functions in the correct order.
+
+// CHECK:     @llvm.global_ctors = 
{{.*}}@[[INIT:_GLOBAL__sub_I[A-Za-z0-9_\.]+]]
+// CHECK:     define {{.*}} @[[VARINIT1:__cxx_global_var_init]]
+// CHECK-NOT: }
+// CHECK:     call void @_ZN1AC1Ev
+// CHECK:     define {{.*}} @[[VARINIT2:__cxx_global_var_init\.[0-9]+]]
+// CHECK-NOT: }
+// CHECK:     call void @_ZN1BC1Ev
+// CHECK:     define {{.*}} @[[INIT]]
+// CHECK-NOT: }
+// CHECK:     call void @[[VARINIT1]]
+// CHECK:     call void @[[VARINIT2]]
+
+class A {
+public:
+  A() {
+  }
+};
+
+class B {
+public:
+  B() {
+  }
+};
+
+class StaticsClass {
+private:
+  static inline A A_Var;
+  static inline B B_Var;
+};
Index: clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp
===================================================================
--- clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp
+++ clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp
@@ -47,7 +47,7 @@
 // CHECK: @_ZGVN5test12t2E = linkonce_odr global i64 0, align 8
 // CHECK: @_ZGVN5test21AIvE8instanceE = weak_odr global i64 0, align 8
 // CHECK: @_ZGVN5test12t1IiEE = linkonce_odr global i64 0, align 8
-// CHECK: @llvm.global_ctors = appending global [4 x { i32, void ()*, i8* }] 
[{ i32, void ()*, i8* } { i32 65535, void ()* @__cxx_global_var_init.1, i8* 
null }, { i32, void ()*, i8* } { i32 65535, void ()* @__cxx_global_var_init.2, 
i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* 
@__cxx_global_var_init.4, i8* null }, { i32, void ()*, i8* } { i32 65535, void 
()* @_GLOBAL__sub_I__, i8* null }]
+// CHECK: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] 
[{ i32, void ()*, i8* } { i32 65535, void ()* @__cxx_global_var_init.2, i8* 
null }, { i32, void ()*, i8* } { i32 65535, void ()* @__cxx_global_var_init.4, 
i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I__, i8* 
null }]
 // CHECK: @llvm.global_dtors = appending global [4 x { i32, void ()*, i8* }] 
[{ i32, void ()*, i8* } { i32 65535, void ()* @__finalize__ZN5test12t2E, i8* 
null }, { i32, void ()*, i8* } { i32 65535, void ()* 
@__finalize__ZN5test21AIvE8instanceE, i8* null }, { i32, void ()*, i8* } { i32 
65535, void ()* @__finalize__ZN5test12t1IiEE, i8* null }, { i32, void ()*, i8* 
} { i32 65535, void ()* @_GLOBAL__D_a, i8* null }]
 
 // CHECK: define internal void @__cxx_global_var_init() [[ATTR:#[0-9]+]] {
Index: clang/lib/CodeGen/CGDeclCXX.cpp
===================================================================
--- clang/lib/CodeGen/CGDeclCXX.cpp
+++ clang/lib/CodeGen/CGDeclCXX.cpp
@@ -503,7 +503,8 @@
                                           PrioritizedCXXGlobalInits.size());
     PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
   } else if (isTemplateInstantiation(D->getTemplateSpecializationKind()) ||
-             getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR) {
+             (getTarget().getCXXABI().isMicrosoft() &&
+              getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR)) 
{
     // C++ [basic.start.init]p2:
     //   Definitions of explicitly specialized class template static data
     //   members have ordered initialization. Other class template static data


Index: clang/test/Modules/initializers.cpp
===================================================================
--- clang/test/Modules/initializers.cpp
+++ clang/test/Modules/initializers.cpp
@@ -232,9 +232,9 @@
 // CHECK-IMPORT: load {{.*}} (i64* @_ZGV
 // CHECK-IMPORT: store {{.*}}, i32* @[[D]],
 
-
 // CHECK-IMPORT: define {{.*}} @[[TU_INIT]]()
 // CHECK-IMPORT: call void @[[A_INIT]]()
+// CHECK-IMPORT: call void @[[B_INIT]]()
 
 // CHECK-IMPORT: define {{.*}} @__tls_init()
 // CHECK-IMPORT: call void @[[C_INIT]]()
Index: clang/test/CodeGenCXX/static-init-order.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/static-init-order.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 %s -std=c++17 -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s
+// Make sure we generate a single initialization routine and put its address into the
+// global_ctors. Check that the initialization routine makes 2 calls to individual
+// initializer functions in the correct order.
+
+// CHECK:     @llvm.global_ctors = {{.*}}@[[INIT:_GLOBAL__sub_I[A-Za-z0-9_\.]+]]
+// CHECK:     define {{.*}} @[[VARINIT1:__cxx_global_var_init]]
+// CHECK-NOT: }
+// CHECK:     call void @_ZN1AC1Ev
+// CHECK:     define {{.*}} @[[VARINIT2:__cxx_global_var_init\.[0-9]+]]
+// CHECK-NOT: }
+// CHECK:     call void @_ZN1BC1Ev
+// CHECK:     define {{.*}} @[[INIT]]
+// CHECK-NOT: }
+// CHECK:     call void @[[VARINIT1]]
+// CHECK:     call void @[[VARINIT2]]
+
+class A {
+public:
+  A() {
+  }
+};
+
+class B {
+public:
+  B() {
+  }
+};
+
+class StaticsClass {
+private:
+  static inline A A_Var;
+  static inline B B_Var;
+};
Index: clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp
===================================================================
--- clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp
+++ clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp
@@ -47,7 +47,7 @@
 // CHECK: @_ZGVN5test12t2E = linkonce_odr global i64 0, align 8
 // CHECK: @_ZGVN5test21AIvE8instanceE = weak_odr global i64 0, align 8
 // CHECK: @_ZGVN5test12t1IiEE = linkonce_odr global i64 0, align 8
-// CHECK: @llvm.global_ctors = appending global [4 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @__cxx_global_var_init.1, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @__cxx_global_var_init.2, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @__cxx_global_var_init.4, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I__, i8* null }]
+// CHECK: @llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @__cxx_global_var_init.2, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @__cxx_global_var_init.4, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I__, i8* null }]
 // CHECK: @llvm.global_dtors = appending global [4 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @__finalize__ZN5test12t2E, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @__finalize__ZN5test21AIvE8instanceE, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @__finalize__ZN5test12t1IiEE, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__D_a, i8* null }]
 
 // CHECK: define internal void @__cxx_global_var_init() [[ATTR:#[0-9]+]] {
Index: clang/lib/CodeGen/CGDeclCXX.cpp
===================================================================
--- clang/lib/CodeGen/CGDeclCXX.cpp
+++ clang/lib/CodeGen/CGDeclCXX.cpp
@@ -503,7 +503,8 @@
                                           PrioritizedCXXGlobalInits.size());
     PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
   } else if (isTemplateInstantiation(D->getTemplateSpecializationKind()) ||
-             getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR) {
+             (getTarget().getCXXABI().isMicrosoft() &&
+              getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR)) {
     // C++ [basic.start.init]p2:
     //   Definitions of explicitly specialized class template static data
     //   members have ordered initialization. Other class template static data
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to