Add a separate llvm.global_ctors entry for linkonce_odr data initializers
Summary:
These typically come from static data members of class template
specializations. This accomplishes two things:
1. May expose GlobalOpt optimizations for Itanium C++ ABI code.
2. Works toward fixing double initialization in the Microsoft C++ ABI.
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1475
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189051 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp b/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
index 94fd9aa..e499efd 100644
--- a/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
+++ b/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
// CHECK: ; ModuleID
+
template<typename> struct A { static int a; };
// CHECK-NOT: @_ZN1AIcE1aE
@@ -8,4 +9,28 @@
// CHECK: @_ZN1AIbE1aE = global i32 10
template<> int A<bool>::a = 10;
+// CHECK: @llvm.global_ctors = appending global [2 x { i32, void ()* }]
+// CHECK: [{ i32, void ()* } { i32 65535, void ()* @__cxx_global_var_init },
+// CHECK: { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+extern "C" int foo();
+template<> int A<short>::a = foo(); // Separate global_ctor entry
+int b = foo(); // Goes in _GLOBAL__I_a
+int c = foo(); // Goes in _GLOBAL__I_a
+
+// An explicit specialization is ordered, and goes in __GLOBAL_I_a.
+template<> struct A<int> { static int a; };
+int A<int>::a = foo();
+
+// CHECK: define internal void @__cxx_global_var_init()
+// CHECK: call i32 @foo()
+// CHECK: store {{.*}} @_ZN1AIsE1aE
+// CHECK: ret
+
+// CHECK: define internal void @_GLOBAL__I_a()
+// We call unique stubs for every ordered dynamic initializer in the TU.
+// CHECK: call
+// CHECK: call
+// CHECK: call
+// CHECK-NOT: call
+// CHECK: ret