Simplify the logic for emitting guard variables for template static
data members by delaying the emission of the initializer until after
linkage and visibility have been set on the global. Also, don't
emit a guard unless the variable actually ends up with vague linkage,
and don't use thread-safe statics in any case.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@118336 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CodeGenCXX/static-data-member.cpp b/test/CodeGenCXX/static-data-member.cpp
index b3a2af2..64fca2e 100644
--- a/test/CodeGenCXX/static-data-member.cpp
+++ b/test/CodeGenCXX/static-data-member.cpp
@@ -1,18 +1,66 @@
-// RUN: %clang_cc1 -emit-llvm -o - %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
-// CHECK: @_ZN1A1aE = constant i32 10
+// CHECK: @_ZN5test11A1aE = constant i32 10, align 4
+// CHECK: @_ZN5test212_GLOBAL__N_11AIiE1xE = internal global i32 0, align 4
+// CHECK: @_ZN5test31AIiE1xE = weak global i32 0, align 4
+// CHECK: @_ZGVN5test31AIiE1xE = weak global i64 0
// PR5564.
-struct A {
- static const int a = 10;
-};
+namespace test1 {
+ struct A {
+ static const int a = 10;
+ };
-const int A::a;
+ const int A::a;
-struct S {
- static int i;
-};
+ struct S {
+ static int i;
+ };
-void f() {
- int a = S::i;
+ void f() {
+ int a = S::i;
+ }
+}
+
+// Test that we don't use guards for initializing template static data
+// members with internal linkage.
+namespace test2 {
+ int foo();
+
+ namespace {
+ template <class T> struct A {
+ static int x;
+ };
+
+ template <class T> int A<T>::x = foo();
+ template struct A<int>;
+ }
+
+ // CHECK: define internal void @__cxx_global_var_init()
+ // CHECK: [[TMP:%.*]] = call i32 @_ZN5test23fooEv()
+ // CHECK-NEXT: store i32 [[TMP]], i32* @_ZN5test212_GLOBAL__N_11AIiE1xE, align 4
+ // CHECK-NEXT: ret void
+}
+
+// Test that we don't use threadsafe statics when initializing
+// template static data members.
+namespace test3 {
+ int foo();
+
+ template <class T> struct A {
+ static int x;
+ };
+
+ template <class T> int A<T>::x = foo();
+ template struct A<int>;
+
+ // CHECK: define internal void @__cxx_global_var_init1()
+ // CHECK: [[GUARDBYTE:%.*]] = load i8* bitcast (i64* @_ZGVN5test31AIiE1xE to i8*)
+ // CHECK-NEXT: [[UNINITIALIZED:%.*]] = icmp eq i8 [[GUARDBYTE]], 0
+ // CHECK-NEXT: br i1 [[UNINITIALIZED]]
+ // CHECK: [[TMP:%.*]] = call i32 @_ZN5test33fooEv()
+ // CHECK-NEXT: store i32 [[TMP]], i32* @_ZN5test31AIiE1xE, align 4
+ // CHECK-NEXT: store i64 1, i64* @_ZGVN5test31AIiE1xE
+ // CHECK-NEXT: br label
+ // CHECK: ret void
}