From: Reid Kleckner Date: Wed, 30 Apr 2014 17:10:18 +0000 (+0000) Subject: __thread: Move constant init check to CheckCompleteVariableDeclaration X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=84062d98f7de53d86da97efa06f89d8ad56d3fdd;p=clang __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; git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@207675 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index e9c3c39b13..283b41683d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/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/test/Sema/thread-specifier.c b/test/Sema/thread-specifier.c index 39243d1a76..d49b350667 100644 --- a/test/Sema/thread-specifier.c +++ b/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};