r179491 - Diagnose if a __thread or _Thread_local variable has a non-constant initializer
Alexey Samsonov
samsonov at google.com
Mon Apr 15 00:22:18 PDT 2013
Hi Richard!
I'm seeing the following error after this change:
$ cat tmp/tls/a.cc
static __thread int per_thread_global[10] = {0};
$ ./bin/clang++ tmp/tls/a.cc -c
tmp/tls/a.cc:1:21: error: initializer for thread-local variable must be a
constant expression
static __thread int per_thread_global[10] = {0};
^
1 error generated.
Is Clang right here?
On Mon, Apr 15, 2013 at 12:11 AM, Richard Smith
<richard-llvm at metafoo.co.uk>wrote:
> Author: rsmith
> Date: Sun Apr 14 15:11:31 2013
> New Revision: 179491
>
> URL: http://llvm.org/viewvc/llvm-project?rev=179491&view=rev
> Log:
> Diagnose if a __thread or _Thread_local variable has a non-constant
> initializer
> or non-trivial destructor.
>
> Modified:
> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> cfe/trunk/lib/Sema/SemaDecl.cpp
> cfe/trunk/test/Sema/thread-specifier.c
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=179491&r1=179490&r2=179491&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Apr 14
> 15:11:31 2013
> @@ -5418,6 +5418,13 @@ def ext_in_class_initializer_non_constan
> "in-class initializer for static data member is not a constant
> expression; "
> "folding it to a constant is a GNU extension">, InGroup<GNU>;
>
> +def err_thread_dynamic_init : Error<
> + "initializer for thread-local variable must be a constant expression">;
> +def err_thread_nontrivial_dtor : Error<
> + "type of thread-local variable has non-trivial destruction">;
> +def note_use_thread_local : Note<
> + "use 'thread_local' to allow this">;
> +
> // C++ anonymous unions and GNU anonymous structs/unions
> def ext_anonymous_union : Extension<
> "anonymous unions are a C11 extension">, InGroup<C11>;
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=179491&r1=179490&r2=179491&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Apr 14 15:11:31 2013
> @@ -7627,6 +7627,18 @@ void Sema::AddInitializerToDecl(Decl *Re
> // 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->isEvaluatable(Context)) {
> + // 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:
> @@ -7972,6 +7984,16 @@ void Sema::CheckCompleteVariableDeclarat
> 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);
> + }
> +
> // All the following checks are C++ only.
> if (!getLangOpts().CPlusPlus) return;
>
>
> Modified: cfe/trunk/test/Sema/thread-specifier.c
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/thread-specifier.c?rev=179491&r1=179490&r2=179491&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/Sema/thread-specifier.c (original)
> +++ cfe/trunk/test/Sema/thread-specifier.c Sun Apr 14 15:11:31 2013
> @@ -3,6 +3,7 @@
> // RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only
> -Wno-private-extern -verify -pedantic %s -DC11 -D__thread=_Thread_local
> // RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only
> -Wno-private-extern -verify -pedantic -x c++ %s -DC11
> -D__thread=_Thread_local
> // 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
> +// 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
>
> #ifdef __cplusplus
> // In C++, we define __private_extern__ to extern.
> @@ -51,8 +52,8 @@ int f(__thread int t7) { // expected-err
> __thread auto int t12a; // expected-error-re {{cannot combine with
> previous '(__thread|_Thread_local)' declaration specifier}}
> auto __thread int t12b; // expected-error {{cannot combine with
> previous 'auto' declaration specifier}}
> #else
> - __thread auto t12a = 0; // expected-error {{'thread_local' variables
> must have global storage}}
> - auto __thread t12b = 0; // expected-error {{'thread_local' variables
> must have global storage}}
> + __thread auto t12a = 0; // expected-error-re {{'(t|_T)hread_local'
> variables must have global storage}}
> + auto __thread t12b = 0; // expected-error-re {{'(t|_T)hread_local'
> variables must have global storage}}
> #endif
> __thread register int t13a; // expected-error-re {{cannot combine with
> previous '(__thread|_Thread_local|thread_local)' declaration specifier}}
> register __thread int t13b; // expected-error {{cannot combine with
> previous 'register' declaration specifier}}
> @@ -83,3 +84,27 @@ void g() {
> #if __cplusplus >= 201103L
> constexpr int *thread_int_ptr_2 = &thread_int; // expected-error {{must
> be initialized by a constant expression}}
> #endif
> +
> +int non_const();
> +__thread int non_const_init = non_const();
> +#if !defined(__cplusplus)
> +// expected-error at -2 {{initializer element is not a compile-time
> constant}}
> +#elif !defined(CXX11)
> +// expected-error at -4 {{initializer for thread-local variable must be a
> constant expression}}
> +#if __cplusplus >= 201103L
> +// expected-note at -6 {{use 'thread_local' to allow this}}
> +#endif
> +#endif
> +
> +#ifdef __cplusplus
> +struct S {
> + ~S();
> +};
> +__thread S s;
> +#if !defined(CXX11)
> +// expected-error at -2 {{type of thread-local variable has non-trivial
> destruction}}
> +#if __cplusplus >= 201103L
> +// expected-note at -4 {{use 'thread_local' to allow this}}
> +#endif
> +#endif
> +#endif
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
--
Alexey Samsonov, MSK
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130415/0199f045/attachment.html>
More information about the cfe-commits
mailing list