]> granicus.if.org Git - clang/commitdiff
PR42111: Use guarded initialization for thread-local variables with
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 5 Jun 2019 00:04:33 +0000 (00:04 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 5 Jun 2019 00:04:33 +0000 (00:04 +0000)
unordered initialization and internal linkage.

We'll run their initializers once on each reference, so we need a guard
variable even though they only have a single definition.

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

lib/CodeGen/CGDeclCXX.cpp
test/CodeGenCXX/cxx1y-variable-template.cpp

index ce0163723c4732cc0fea3e572f58a453de1b0ef9..199e0ac99e81d774575228662e320143e2b24e05 100644 (file)
@@ -630,7 +630,13 @@ void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
   // Use guarded initialization if the global variable is weak. This
   // occurs for, e.g., instantiated static data members and
   // definitions explicitly marked weak.
-  if (Addr->hasWeakLinkage() || Addr->hasLinkOnceLinkage()) {
+  //
+  // Also use guarded initialization for a variable with dynamic TLS and
+  // unordered initialization. (If the initialization is ordered, the ABI
+  // layer will guard the whole-TU initialization for us.)
+  if (Addr->hasWeakLinkage() || Addr->hasLinkOnceLinkage() ||
+      (D->getTLSKind() == VarDecl::TLS_Dynamic &&
+       isTemplateInstantiation(D->getTemplateSpecializationKind()))) {
     EmitCXXGuardedInit(*D, Addr, PerformInit);
   } else {
     EmitCXXGlobalVarDeclInit(*D, Addr, PerformInit);
index dd8f28e42992c39e9fb683bc71b178da315a57c3..51d1b54b37a7fcb7d60753e3878daae16ae6194f 100644 (file)
@@ -27,4 +27,21 @@ int *p = &n<0>;
 // CHECK: @_ZN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = linkonce_odr global [123 x i32] zeroinitializer
 // CHECK: @_ZGVN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = linkonce_odr global
 
+// CHECK: @_ZTHN7PR4211112_GLOBAL__N_11nILi0EEE = internal alias {{.*}} @[[PR42111_CTOR:.*]]
+
 // CHECK: call {{.*}}@_Z8init_arrv
+
+// Ensure that we use guarded initialization for an instantiated thread_local
+// variable with internal linkage.
+namespace PR42111 {
+  int f();
+  namespace { template <int = 0> thread_local int n = f(); }
+  // CHECK: define {{.*}}@[[PR42111_CTOR]](
+  // CHECK: load {{.*}} @_ZGVN7PR4211112_GLOBAL__N_11nILi0EEE
+  // CHECK: icmp eq i8 {{.*}}, 0
+  // CHECK: br i1
+  // CHECK: call i32 @_ZN7PR421111fEv(
+  // CHECK: store i32 {{.*}}, i32* @_ZN7PR4211112_GLOBAL__N_11nILi0EEE
+  // CHECK: store i8 1, i8* @_ZGVN7PR4211112_GLOBAL__N_11nILi0EEE
+  int g() { return n<> + n<>; }
+}