]> granicus.if.org Git - clang/commitdiff
__thread: Move constant init check to CheckCompleteVariableDeclaration
authorReid Kleckner <reid@kleckner.net>
Wed, 30 Apr 2014 17:10:18 +0000 (17:10 +0000)
committerReid Kleckner <reid@kleckner.net>
Wed, 30 Apr 2014 17:10:18 +0000 (17:10 +0000)
We were emitting dynamic initializers for __thread variables if there
was no explicit initializer, as in this test case:

struct S { S(); };
__thread S s;

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

lib/Sema/SemaDecl.cpp
test/Sema/thread-specifier.c

index e9c3c39b132389145d6c9ef080f698c5c09ffd53..283b41683d19fbe4ceb2b7b6101160729b888cb9 100644 (file)
@@ -8539,19 +8539,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
     // C99 6.7.8p4. All file scoped initializers need to be constant.
     if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl())
       CheckForConstantInitializer(Init, DclT);
-    else if (VDecl->getTLSKind() == VarDecl::TLS_Static &&
-             !VDecl->isInvalidDecl() && !DclT->isDependentType() &&
-             !Init->isValueDependent() && !VDecl->isConstexpr() &&
-             !Init->isConstantInitializer(
-                 Context, VDecl->getType()->isReferenceType())) {
-      // GNU C++98 edits for __thread, [basic.start.init]p4:
-      //   An object of thread storage duration shall not require dynamic
-      //   initialization.
-      // FIXME: Need strict checking here.
-      Diag(VDecl->getLocation(), diag::err_thread_dynamic_init);
-      if (getLangOpts().CPlusPlus11)
-        Diag(VDecl->getLocation(), diag::note_use_thread_local);
-    }
   }
 
   // We will represent direct-initialization similarly to copy-initialization:
@@ -8913,14 +8900,26 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
       Diag(var->getLocation(), diag::warn_missing_variable_declarations) << var;
   }
 
-  if (var->getTLSKind() == VarDecl::TLS_Static &&
-      var->getType().isDestructedType()) {
-    // GNU C++98 edits for __thread, [basic.start.term]p3:
-    //   The type of an object with thread storage duration shall not
-    //   have a non-trivial destructor.
-    Diag(var->getLocation(), diag::err_thread_nontrivial_dtor);
-    if (getLangOpts().CPlusPlus11)
-      Diag(var->getLocation(), diag::note_use_thread_local);
+  if (var->getTLSKind() == VarDecl::TLS_Static) {
+    if (var->getType().isDestructedType()) {
+      // GNU C++98 edits for __thread, [basic.start.term]p3:
+      //   The type of an object with thread storage duration shall not
+      //   have a non-trivial destructor.
+      Diag(var->getLocation(), diag::err_thread_nontrivial_dtor);
+      if (getLangOpts().CPlusPlus11)
+        Diag(var->getLocation(), diag::note_use_thread_local);
+    } else if (getLangOpts().CPlusPlus && var->hasInit() &&
+               !var->getInit()->isConstantInitializer(
+                   Context, var->getType()->isReferenceType())) {
+      // GNU C++98 edits for __thread, [basic.start.init]p4:
+      //   An object of thread storage duration shall not require dynamic
+      //   initialization.
+      // FIXME: Need strict checking here.
+      Diag(var->getLocation(), diag::err_thread_dynamic_init);
+      if (getLangOpts().CPlusPlus11)
+        Diag(var->getLocation(), diag::note_use_thread_local);
+    }
+
   }
 
   if (var->isThisDeclarationADefinition() &&
index 39243d1a760526807d9b4dfb883916cd289c8d53..d49b350667a8b2eb82e9b28b968c490f45d32d37 100644 (file)
@@ -107,4 +107,17 @@ __thread S s;
 #endif
 #endif
 
+#ifdef __cplusplus
+struct HasCtor {
+  HasCtor();
+};
+__thread HasCtor var_with_ctor;
+#if !defined(CXX11)
+// expected-error@-2 {{initializer for thread-local variable must be a constant expression}}
+#if __cplusplus >= 201103L
+// expected-note@-4 {{use 'thread_local' to allow this}}
+#endif
+#endif
+#endif
+
 __thread int aggregate[10] = {0};