summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2014-04-30 17:10:18 +0000
committerReid Kleckner <reid@kleckner.net>2014-04-30 17:10:18 +0000
commit92fc0178c61db0fa9a9f52b4873fa366e47f658c (patch)
tree4cc38cce0458b874203d8727009b6bad1abd48c8
parent553e5ebe4a79836a462a872609913174280a9255 (diff)
downloadbcm5719-llvm-92fc0178c61db0fa9a9f52b4873fa366e47f658c.tar.gz
bcm5719-llvm-92fc0178c61db0fa9a9f52b4873fa366e47f658c.zip
__thread: Move constant init check to CheckCompleteVariableDeclaration
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; llvm-svn: 207675
-rw-r--r--clang/lib/Sema/SemaDecl.cpp41
-rw-r--r--clang/test/Sema/thread-specifier.c13
2 files changed, 33 insertions, 21 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e9c3c39b132..283b41683d1 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -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() &&
diff --git a/clang/test/Sema/thread-specifier.c b/clang/test/Sema/thread-specifier.c
index 39243d1a760..d49b350667a 100644
--- a/clang/test/Sema/thread-specifier.c
+++ b/clang/test/Sema/thread-specifier.c
@@ -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};
OpenPOWER on IntegriCloud