]> granicus.if.org Git - clang/commitdiff
Don't use a global_ctors comdat for globals that aren't externally visible
authorReid Kleckner <reid@kleckner.net>
Wed, 15 Oct 2014 16:38:00 +0000 (16:38 +0000)
committerReid Kleckner <reid@kleckner.net>
Wed, 15 Oct 2014 16:38:00 +0000 (16:38 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@219806 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGDeclCXX.cpp
test/CodeGenCXX/static-member-variable-explicit-specialization.cpp

index ee3172ebc5453490f21148c88b505a64c1c24f37..dcfc45ff84fcd178c3cc70cc3813f398bb6b2d02 100644 (file)
@@ -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 =
index 04bf79fd15591811ae788ce7c163faa6ff2d0d70..430fa2b08d5d82e537a33b41feec0db954cc5457 100644 (file)
@@ -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