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