diff options
author | Reid Kleckner <reid@kleckner.net> | 2014-10-15 16:38:00 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2014-10-15 16:38:00 +0000 |
commit | 72d03bee6497a80e70ffbf43a6e28cd55bf3527b (patch) | |
tree | 09fea6116d7e6dda7d48a943cbcf219e4d508aee | |
parent | 8476abe288582a290f47a9808a32b82ea0dfb303 (diff) | |
download | bcm5719-llvm-72d03bee6497a80e70ffbf43a6e28cd55bf3527b.tar.gz bcm5719-llvm-72d03bee6497a80e70ffbf43a6e28cd55bf3527b.zip |
Don't use a global_ctors comdat for globals that aren't externally visible
In particular, if you have two identical templates in different TUs in
anonymous namespaces, we would use the same global_ctors comdat key for
both. As a result, only one would be run.
llvm-svn: 219806
-rw-r--r-- | clang/lib/CodeGen/CGDeclCXX.cpp | 18 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp | 16 |
2 files changed, 24 insertions, 10 deletions
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index ee3172ebc54..dcfc45ff84f 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -292,7 +292,8 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D, CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr, PerformInit); - llvm::GlobalVariable *Key = supportsCOMDAT() ? Addr : nullptr; + llvm::GlobalVariable *COMDATKey = + supportsCOMDAT() && D->isExternallyVisible() ? Addr : nullptr; if (D->getTLSKind()) { // FIXME: Should we support init_priority for thread_local? @@ -310,8 +311,7 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D, OrderGlobalInits Key(IPA->getPriority(), PrioritizedCXXGlobalInits.size()); PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn)); DelayedCXXInitPosition.erase(D); - } else if (D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization && - D->getTemplateSpecializationKind() != TSK_Undeclared) { + } else if (isTemplateInstantiation(D->getTemplateSpecializationKind())) { // C++ [basic.start.init]p2: // Definitions of explicitly specialized class template static data // members have ordered initialization. Other class template static data @@ -320,16 +320,16 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D, // // As a consequence, we can put them into their own llvm.global_ctors entry. // - // In addition, put the initializer into a COMDAT group with the global - // being initialized. On most platforms, this is a minor startup time - // optimization. In the MS C++ ABI, there are no guard variables, so this - // COMDAT key is required for correctness. - AddGlobalCtor(Fn, 65535, Key); + // If the global is externally visible, put the initializer into a COMDAT + // group with the global being initialized. On most platforms, this is a + // minor startup time optimization. In the MS C++ ABI, there are no guard + // variables, so this COMDAT key is required for correctness. + AddGlobalCtor(Fn, 65535, COMDATKey); DelayedCXXInitPosition.erase(D); } else if (D->hasAttr<SelectAnyAttr>()) { // SelectAny globals will be comdat-folded. Put the initializer into a COMDAT // group associated with the global, so the initializers get folded too. - AddGlobalCtor(Fn, 65535, Key); + AddGlobalCtor(Fn, 65535, COMDATKey); DelayedCXXInitPosition.erase(D); } else { llvm::DenseMap<const Decl *, unsigned>::iterator I = diff --git a/clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp b/clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp index 04bf79fd155..430fa2b08d5 100644 --- a/clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp +++ b/clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp @@ -14,7 +14,7 @@ template<> int A<char>::a; // ALL: @_ZN1AIbE1aE = global i32 10 template<> int A<bool>::a = 10; -// ALL: @llvm.global_ctors = appending global [7 x { i32, void ()*, i8* }] +// ALL: @llvm.global_ctors = appending global [8 x { i32, void ()*, i8* }] // ELF: [{ i32, void ()*, i8* } { i32 65535, void ()* @[[unordered1:[^,]*]], i8* bitcast (i32* @_ZN1AIsE1aE to i8*) }, // MACHO: [{ i32, void ()*, i8* } { i32 65535, void ()* @[[unordered1:[^,]*]], i8* null }, @@ -34,6 +34,8 @@ template<> int A<bool>::a = 10; // ELF: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered6:[^,]*]], i8* @_Z1xIcE }, // MACHO: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered6:[^,]*]], i8* null }, +// ALL: { i32, void ()*, i8* } { i32 65535, void ()* @[[unordered7:[^,]*]], i8* null }, + // ALL: { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp, i8* null }] template int A<short>::a; // Unordered @@ -67,6 +69,13 @@ struct b { template<typename T> T b::i = foo(); template int b::i<int>; } + +namespace { +template<typename T> struct Internal { static int a; }; +template<typename T> int Internal<T>::a = foo(); +} +int *use_internal_a = &Internal<int>::a; + // ALL: define internal void @[[unordered1]] // ALL: call i32 @foo() // ALL: store {{.*}} @_ZN1AIsE1aE @@ -97,6 +106,11 @@ template int b::i<int>; // ALL: store {{.*}} @_Z1xIcE // ALL: ret +// ALL: define internal void @[[unordered7]] +// ALL: call i32 @foo() +// ALL: store {{.*}} @_ZN12_GLOBAL__N_18InternalIiE1aE +// ALL: ret + // ALL: define internal void @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp() // We call unique stubs for every ordered dynamic initializer in the TU. // ALL: call |