From c47063e1e647c3749b1851e42c78ac52938d2fbb Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 4 Sep 2013 00:54:24 +0000 Subject: [PATCH] Order initializers of static data members of explicit specializations I tried to implement this properly in r189051, but I didn't have enough test coverage. Richard kindly provided more test cases than I could possibly imagine and now we should have the correct condition. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189898 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDeclCXX.cpp | 11 ++-- ...ember-variable-explicit-specialization.cpp | 51 ++++++++++++++++--- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index bf5e37733b..868820a081 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -276,12 +276,13 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D, OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size()); PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn)); DelayedCXXInitPosition.erase(D); - } else if (D->getInstantiatedFromStaticDataMember()) { + } else if (D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization && + D->getTemplateSpecializationKind() != TSK_Undeclared) { // C++ [basic.start.init]p2: - // Defnitions of explicitly specialized class template static data members - // have ordered initialization. Other class template static data members - // (i.e., implicitly or explicitly instantiated specializations) have - // unordered initialization. + // Definitions of explicitly specialized class template static data + // members have ordered initialization. Other class template static data + // members (i.e., implicitly or explicitly instantiated specializations) + // have unordered initialization. // // As a consequence, we can put them into their own llvm.global_ctors entry. // This should allow GlobalOpt to fire more often, and allow us to implement diff --git a/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp b/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp index e499efd2d0..a069e8bd72 100644 --- a/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp +++ b/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp @@ -1,7 +1,10 @@ // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s // CHECK: ; ModuleID -template struct A { static int a; }; +extern "C" int foo(); + +template struct A { static int a; }; +template int A::a = foo(); // CHECK-NOT: @_ZN1AIcE1aE template<> int A::a; @@ -9,28 +12,60 @@ template<> int A::a; // CHECK: @_ZN1AIbE1aE = global i32 10 template<> int A::a = 10; -// CHECK: @llvm.global_ctors = appending global [2 x { i32, void ()* }] -// CHECK: [{ i32, void ()* } { i32 65535, void ()* @__cxx_global_var_init }, +// CHECK: @llvm.global_ctors = appending global [5 x { i32, void ()* }] +// CHECK: [{ i32, void ()* } { i32 65535, void ()* @[[unordered1:[^ ]*]] }, +// CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered2:[^ ]*]] }, +// CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered3:[^ ]*]] }, +// CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered4:[^ ]*]] }, // CHECK: { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }] -extern "C" int foo(); -template<> int A::a = foo(); // Separate global_ctor entry -int b = foo(); // Goes in _GLOBAL__I_a -int c = foo(); // Goes in _GLOBAL__I_a +template int A::a; // Unordered +int b = foo(); +int c = foo(); +int d = A::a; // Unordered // An explicit specialization is ordered, and goes in __GLOBAL_I_a. template<> struct A { static int a; }; int A::a = foo(); -// CHECK: define internal void @__cxx_global_var_init() +template struct S { static T x; static T y; }; +template<> int S::x = foo(); +template<> int S::y = S::x; + +template T x = foo(); +template short x; // Unordered +template<> int x = foo(); +int e = x; // Unordered + +// CHECK: define internal void @[[unordered1]] // CHECK: call i32 @foo() // CHECK: store {{.*}} @_ZN1AIsE1aE // CHECK: ret +// CHECK: define internal void @[[unordered2]] +// CHECK: call i32 @foo() +// CHECK: store {{.*}} @_Z1xIsE +// CHECK: ret + +// CHECK: define internal void @[[unordered3]] +// CHECK: call i32 @foo() +// CHECK: store {{.*}} @_ZN1AIvE1aE +// CHECK: ret + +// CHECK: define internal void @[[unordered4]] +// CHECK: call i32 @foo() +// CHECK: store {{.*}} @_Z1xIcE +// 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: call +// CHECK: call +// CHECK: call +// CHECK: call +// CHECK: call // CHECK-NOT: call // CHECK: ret -- 2.50.1