<div dir="ltr">Hi Richard!<div><br></div><div style>I'm seeing the following error after this change:</div><div style><div>$ cat tmp/tls/a.cc</div><div>static __thread int per_thread_global[10] = {0};</div><div><div>$ ./bin/clang++ tmp/tls/a.cc -c</div>
<div>tmp/tls/a.cc:1:21: error: initializer for thread-local variable must be a constant expression</div><div>static __thread int per_thread_global[10] = {0};</div><div> ^</div><div>1 error generated.</div>
</div></div><div style><br></div><div style><br></div><div style>Is Clang right here?</div><div style><br></div><div style><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Apr 15, 2013 at 12:11 AM, Richard Smith <span dir="ltr"><<a href="mailto:richard-llvm@metafoo.co.uk" target="_blank">richard-llvm@metafoo.co.uk</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Sun Apr 14 15:11:31 2013<br>
New Revision: 179491<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=179491&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=179491&view=rev</a><br>
Log:<br>
Diagnose if a __thread or _Thread_local variable has a non-constant initializer<br>
or non-trivial destructor.<br>
<br>
Modified:<br>
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
cfe/trunk/lib/Sema/SemaDecl.cpp<br>
cfe/trunk/test/Sema/thread-specifier.c<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=179491&r1=179490&r2=179491&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=179491&r1=179490&r2=179491&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Apr 14 15:11:31 2013<br>
@@ -5418,6 +5418,13 @@ def ext_in_class_initializer_non_constan<br>
"in-class initializer for static data member is not a constant expression; "<br>
"folding it to a constant is a GNU extension">, InGroup<GNU>;<br>
<br>
+def err_thread_dynamic_init : Error<<br>
+ "initializer for thread-local variable must be a constant expression">;<br>
+def err_thread_nontrivial_dtor : Error<<br>
+ "type of thread-local variable has non-trivial destruction">;<br>
+def note_use_thread_local : Note<<br>
+ "use 'thread_local' to allow this">;<br>
+<br>
// C++ anonymous unions and GNU anonymous structs/unions<br>
def ext_anonymous_union : Extension<<br>
"anonymous unions are a C11 extension">, InGroup<C11>;<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=179491&r1=179490&r2=179491&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=179491&r1=179490&r2=179491&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Apr 14 15:11:31 2013<br>
@@ -7627,6 +7627,18 @@ void Sema::AddInitializerToDecl(Decl *Re<br>
// C99 6.7.8p4. All file scoped initializers need to be constant.<br>
if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl())<br>
CheckForConstantInitializer(Init, DclT);<br>
+ else if (VDecl->getTLSKind() == VarDecl::TLS_Static &&<br>
+ !VDecl->isInvalidDecl() && !DclT->isDependentType() &&<br>
+ !Init->isValueDependent() && !VDecl->isConstexpr() &&<br>
+ !Init->isEvaluatable(Context)) {<br>
+ // GNU C++98 edits for __thread, [basic.start.init]p4:<br>
+ // An object of thread storage duration shall not require dynamic<br>
+ // initialization.<br>
+ // FIXME: Need strict checking here.<br>
+ Diag(VDecl->getLocation(), diag::err_thread_dynamic_init);<br>
+ if (getLangOpts().CPlusPlus11)<br>
+ Diag(VDecl->getLocation(), diag::note_use_thread_local);<br>
+ }<br>
}<br>
<br>
// We will represent direct-initialization similarly to copy-initialization:<br>
@@ -7972,6 +7984,16 @@ void Sema::CheckCompleteVariableDeclarat<br>
Diag(var->getLocation(), diag::warn_missing_variable_declarations) << var;<br>
}<br>
<br>
+ if (var->getTLSKind() == VarDecl::TLS_Static &&<br>
+ var->getType().isDestructedType()) {<br>
+ // GNU C++98 edits for __thread, [basic.start.term]p3:<br>
+ // The type of an object with thread storage duration shall not<br>
+ // have a non-trivial destructor.<br>
+ Diag(var->getLocation(), diag::err_thread_nontrivial_dtor);<br>
+ if (getLangOpts().CPlusPlus11)<br>
+ Diag(var->getLocation(), diag::note_use_thread_local);<br>
+ }<br>
+<br>
// All the following checks are C++ only.<br>
if (!getLangOpts().CPlusPlus) return;<br>
<br>
<br>
Modified: cfe/trunk/test/Sema/thread-specifier.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/thread-specifier.c?rev=179491&r1=179490&r2=179491&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/thread-specifier.c?rev=179491&r1=179490&r2=179491&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Sema/thread-specifier.c (original)<br>
+++ cfe/trunk/test/Sema/thread-specifier.c Sun Apr 14 15:11:31 2013<br>
@@ -3,6 +3,7 @@<br>
// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify -pedantic %s -DC11 -D__thread=_Thread_local<br>
// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify -pedantic -x c++ %s -DC11 -D__thread=_Thread_local<br>
// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify -pedantic -x c++ %s -DCXX11 -D__thread=thread_local -std=c++11<br>
+// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify -pedantic -x c++ %s -DC11 -D__thread=_Thread_local -std=c++11<br>
<br>
#ifdef __cplusplus<br>
// In C++, we define __private_extern__ to extern.<br>
@@ -51,8 +52,8 @@ int f(__thread int t7) { // expected-err<br>
__thread auto int t12a; // expected-error-re {{cannot combine with previous '(__thread|_Thread_local)' declaration specifier}}<br>
auto __thread int t12b; // expected-error {{cannot combine with previous 'auto' declaration specifier}}<br>
#else<br>
- __thread auto t12a = 0; // expected-error {{'thread_local' variables must have global storage}}<br>
- auto __thread t12b = 0; // expected-error {{'thread_local' variables must have global storage}}<br>
+ __thread auto t12a = 0; // expected-error-re {{'(t|_T)hread_local' variables must have global storage}}<br>
+ auto __thread t12b = 0; // expected-error-re {{'(t|_T)hread_local' variables must have global storage}}<br>
#endif<br>
__thread register int t13a; // expected-error-re {{cannot combine with previous '(__thread|_Thread_local|thread_local)' declaration specifier}}<br>
register __thread int t13b; // expected-error {{cannot combine with previous 'register' declaration specifier}}<br>
@@ -83,3 +84,27 @@ void g() {<br>
#if __cplusplus >= 201103L<br>
constexpr int *thread_int_ptr_2 = &thread_int; // expected-error {{must be initialized by a constant expression}}<br>
#endif<br>
+<br>
+int non_const();<br>
+__thread int non_const_init = non_const();<br>
+#if !defined(__cplusplus)<br>
+// expected-error@-2 {{initializer element is not a compile-time constant}}<br>
+#elif !defined(CXX11)<br>
+// expected-error@-4 {{initializer for thread-local variable must be a constant expression}}<br>
+#if __cplusplus >= 201103L<br>
+// expected-note@-6 {{use 'thread_local' to allow this}}<br>
+#endif<br>
+#endif<br>
+<br>
+#ifdef __cplusplus<br>
+struct S {<br>
+ ~S();<br>
+};<br>
+__thread S s;<br>
+#if !defined(CXX11)<br>
+// expected-error@-2 {{type of thread-local variable has non-trivial destruction}}<br>
+#if __cplusplus >= 201103L<br>
+// expected-note@-4 {{use 'thread_local' to allow this}}<br>
+#endif<br>
+#endif<br>
+#endif<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div>Alexey Samsonov, MSK</div>
</div>