]> granicus.if.org Git - clang/commitdiff
Don't elide the use of the thread wrapper for a thread_local constinit
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 1 Oct 2019 01:23:23 +0000 (01:23 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 1 Oct 2019 01:23:23 +0000 (01:23 +0000)
variable with non-trivial destruction.

We still need to invoke the thread wrapper to trigger registration of
the destructor call on thread shutdown.

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

lib/CodeGen/ItaniumCXXABI.cpp
test/CodeGenCXX/cxx2a-thread-local-constinit.cpp

index 35e707243ea0f0bdc0b3a69481690643930fdc58..1f5bc73ba977375902bf9af9012220105a410a3f 100644 (file)
@@ -360,7 +360,8 @@ public:
   }
 
   bool usesThreadWrapperFunction(const VarDecl *VD) const override {
-    return !isEmittedWithConstantInitializer(VD);
+    return !isEmittedWithConstantInitializer(VD) ||
+           VD->needsDestruction(getContext());
   }
   LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
                                       QualType LValType) override;
@@ -2606,7 +2607,7 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
     llvm::GlobalValue *Init = nullptr;
     bool InitIsInitFunc = false;
     bool HasConstantInitialization = false;
-    if (isEmittedWithConstantInitializer(VD)) {
+    if (!usesThreadWrapperFunction(VD)) {
       HasConstantInitialization = true;
     } else if (VD->hasDefinition()) {
       InitIsInitFunc = true;
index 149d5b99d46282c141f39eb6ae83e963649c0faa..af46a92c7dc2db92e67deea2fc7fb554e92774ad 100644 (file)
@@ -33,11 +33,6 @@ extern thread_local int c;
 // CHECK: }
 int h() { return c; }
 
-thread_local int c = 0;
-
-int d_init();
-thread_local int d = d_init();
-
 // Note: use of 'c' does not trigger initialization of 'd', because 'c' has a
 // constant initializer.
 // CHECK-LABEL: define weak_odr {{.*}} @_ZTW1c()
@@ -45,3 +40,30 @@ thread_local int d = d_init();
 // CHECK-NOT: call
 // CHECK: ret i32* @c
 // CHECK: }
+
+thread_local int c = 0;
+
+int d_init();
+
+// CHECK: define {{.*}}[[D_INIT:@__cxx_global_var_init[^(]*]](
+// CHECK: call {{.*}} @_Z6d_initv()
+thread_local int d = d_init();
+
+struct Destructed {
+  int n;
+  ~Destructed();
+};
+
+extern thread_local constinit Destructed e;
+// CHECK-LABEL: define i32 @_Z1iv()
+// CHECK: call {{.*}}* @_ZTW1e()
+// CHECK: }
+int i() { return e.n; }
+
+// CHECK: define {{.*}}[[E2_INIT:@__cxx_global_var_init[^(]*]](
+// CHECK: call {{.*}} @__cxa_thread_atexit({{.*}} @_ZN10DestructedD1Ev {{.*}} @e2
+thread_local constinit Destructed e2;
+
+// CHECK-LABEL: define {{.*}}__tls_init
+// CHECK: call {{.*}} [[D_INIT]]
+// CHECK: call {{.*}} [[E2_INIT]]