From 774bd6ef1c93265f07499e25ea5a0d72f9d998cc Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Mon, 26 Aug 2019 19:44:07 +0000 Subject: [PATCH] Diagnose use of _Thread_local as an extension when not in C11 mode. llvm-svn: 369954 --- .../clang/Basic/DiagnosticParseKinds.td | 2 +- clang/lib/Parse/ParseDecl.cpp | 4 +- clang/lib/Parse/ParseExpr.cpp | 2 +- clang/test/PCH/thread-local.cpp | 4 +- clang/test/Sema/thread-specifier.c | 77 +++++++++++-------- clang/test/SemaOpenCLCXX/restricted.cl | 2 + 6 files changed, 54 insertions(+), 37 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 735722fe654a..1b5f335e01d0 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -126,7 +126,7 @@ def err_duplicate_default_assoc : Error< def note_previous_default_assoc : Note< "previous default generic association is here">; -def ext_c11_alignment : Extension< +def ext_c11_feature : Extension< "%0 is a C11-specific feature">, InGroup; def ext_c11_noreturn : Extension< diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 3de52ce8754f..1375409a7536 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3574,6 +3574,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isStorageClass = true; break; case tok::kw__Thread_local: + if (!getLangOpts().C11) + Diag(Tok, diag::ext_c11_feature) << Tok.getName(); isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local, Loc, PrevSpec, DiagID); isStorageClass = true; @@ -3631,7 +3633,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // alignment-specifier case tok::kw__Alignas: if (!getLangOpts().C11) - Diag(Tok, diag::ext_c11_alignment) << Tok.getName(); + Diag(Tok, diag::ext_c11_feature) << Tok.getName(); ParseAlignmentSpecifier(DS.getAttributes()); continue; diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 43b87b951b41..2eb8ff9a8b04 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1191,7 +1191,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, } case tok::kw__Alignof: // unary-expression: '_Alignof' '(' type-name ')' if (!getLangOpts().C11) - Diag(Tok, diag::ext_c11_alignment) << Tok.getName(); + Diag(Tok, diag::ext_c11_feature) << Tok.getName(); LLVM_FALLTHROUGH; case tok::kw_alignof: // unary-expression: 'alignof' '(' type-id ')' case tok::kw___alignof: // unary-expression: '__alignof' unary-expression diff --git a/clang/test/PCH/thread-local.cpp b/clang/test/PCH/thread-local.cpp index ab37f7b3f7ed..678fe34899d5 100644 --- a/clang/test/PCH/thread-local.cpp +++ b/clang/test/PCH/thread-local.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -pedantic-errors -std=c++11 -triple x86_64-linux-gnu -emit-pch %s -o %t -// RUN: %clang_cc1 -pedantic-errors -std=c++11 -triple x86_64-linux-gnu -include-pch %t -verify %s +// RUN: %clang_cc1 -pedantic-errors -Wno-c11-extensions -std=c++11 -triple x86_64-linux-gnu -emit-pch %s -o %t +// RUN: %clang_cc1 -pedantic-errors -Wno-c11-extensions -std=c++11 -triple x86_64-linux-gnu -include-pch %t -verify %s // REQUIRES: x86-registered-target #ifndef HEADER_INCLUDED diff --git a/clang/test/Sema/thread-specifier.c b/clang/test/Sema/thread-specifier.c index a93850da0077..3f1a124aef22 100644 --- a/clang/test/Sema/thread-specifier.c +++ b/clang/test/Sema/thread-specifier.c @@ -1,25 +1,26 @@ // RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify -pedantic %s -DGNU // RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify -pedantic -x c++ %s -DGNU -std=c++98 -// 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 -std=c++98 +// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify -pedantic %s -std=c11 -DC11 -D__thread=_Thread_local +// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify=expected,thread-local -pedantic -x c++ %s -DC11 -D__thread=_Thread_local -std=c++98 // 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 -Wno-deprecated -// 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 -Wno-deprecated +// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify=expected,thread-local -pedantic -x c++ %s -DC11 -D__thread=_Thread_local -std=c++11 -Wno-deprecated +// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-private-extern -verify=expected,thread-local -pedantic %s -std=c99 -D__thread=_Thread_local -DC99 #ifdef __cplusplus // In C++, we define __private_extern__ to extern. #undef __private_extern__ #endif -__thread int t1; -__thread extern int t2; -__thread static int t3; +__thread int t1; // thread-local-warning {{_Thread_local is a C11-specific feature}} +__thread extern int t2; // thread-local-warning {{_Thread_local is a C11-specific feature}} +__thread static int t3; // thread-local-warning {{_Thread_local is a C11-specific feature}} #ifdef GNU // expected-warning@-3 {{'__thread' before 'extern'}} // expected-warning@-3 {{'__thread' before 'static'}} #endif -__thread __private_extern__ int t4; -struct t5 { __thread int x; }; +__thread __private_extern__ int t4; // thread-local-warning {{_Thread_local is a C11-specific feature}} +struct t5 { __thread int x; }; // thread-local-warning {{_Thread_local is a C11-specific feature}} #ifdef __cplusplus // expected-error-re@-2 {{'{{__thread|_Thread_local|thread_local}}' is only allowed on variable declarations}} #else @@ -27,51 +28,63 @@ struct t5 { __thread int x; }; // expected-error@-5 {{type name does not allow storage class to be specified}} #endif -__thread int t6(); +__thread int t6(); // thread-local-warning {{_Thread_local is a C11-specific feature}} #if defined(GNU) // expected-error@-2 {{'__thread' is only allowed on variable declarations}} -#elif defined(C11) +#elif defined(C11) || defined(C99) // expected-error@-4 {{'_Thread_local' is only allowed on variable declarations}} #else // expected-error@-6 {{'thread_local' is only allowed on variable declarations}} #endif -int f(__thread int t7) { // expected-error {{' is only allowed on variable declarations}} - __thread int t8; +int f(__thread int t7) { // expected-error {{' is only allowed on variable declarations}} \ + // thread-local-warning {{_Thread_local is a C11-specific feature}} + __thread int t8; // thread-local-warning {{_Thread_local is a C11-specific feature}} #if defined(GNU) // expected-error@-2 {{'__thread' variables must have global storage}} -#elif defined(C11) +#elif defined(C11) || defined(C99) // expected-error@-4 {{'_Thread_local' variables must have global storage}} #endif - extern __thread int t9; - static __thread int t10; - __thread __private_extern__ int t11; + extern __thread int t9; // thread-local-warning {{_Thread_local is a C11-specific feature}} + static __thread int t10; // thread-local-warning {{_Thread_local is a C11-specific feature}} + __thread __private_extern__ int t11; // thread-local-warning {{_Thread_local is a C11-specific feature}} #if __cplusplus < 201103L - __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}} + __thread auto int t12a; // expected-error-re {{cannot combine with previous '{{__thread|_Thread_local}}' declaration specifier}} \ + // thread-local-warning {{_Thread_local is a C11-specific feature}} + auto __thread int t12b; // expected-error {{cannot combine with previous 'auto' declaration specifier}} \ + // thread-local-warning {{_Thread_local is a C11-specific feature}} #elif !defined(CXX11) - __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 {{'_Thread_local' variables must have global storage}} \ + // thread-local-warning {{_Thread_local is a C11-specific feature}} + auto __thread t12b = 0; // expected-error {{'_Thread_local' variables must have global storage}} \ + // thread-local-warning {{_Thread_local is a C11-specific feature}} #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}} + __thread register int t13a; // expected-error-re {{cannot combine with previous '{{__thread|_Thread_local|thread_local}}' declaration specifier}} \ + // thread-local-warning {{_Thread_local is a C11-specific feature}} + register __thread int t13b; // expected-error {{cannot combine with previous 'register' declaration specifier}} \ + // thread-local-warning {{_Thread_local is a C11-specific feature}} } -__thread typedef int t14; // expected-error-re {{cannot combine with previous '{{__thread|_Thread_local|thread_local}}' declaration specifier}} -__thread int t15; // expected-note {{previous definition is here}} +__thread typedef int t14; // expected-error-re {{cannot combine with previous '{{__thread|_Thread_local|thread_local}}' declaration specifier}} \ + // thread-local-warning {{_Thread_local is a C11-specific feature}} +__thread int t15; // expected-note {{previous definition is here}} \ + // thread-local-warning {{_Thread_local is a C11-specific feature}} extern int t15; // expected-error {{non-thread-local declaration of 't15' follows thread-local declaration}} extern int t16; // expected-note {{previous declaration is here}} -__thread int t16; // expected-error {{thread-local declaration of 't16' follows non-thread-local declaration}} +__thread int t16; // expected-error {{thread-local declaration of 't16' follows non-thread-local declaration}} \ + // thread-local-warning {{_Thread_local is a C11-specific feature}} #ifdef CXX11 extern thread_local int t17; // expected-note {{previous declaration is here}} -_Thread_local int t17; // expected-error {{thread-local declaration of 't17' with static initialization follows declaration with dynamic initialization}} -extern _Thread_local int t18; // expected-note {{previous declaration is here}} +_Thread_local int t17; // expected-error {{thread-local declaration of 't17' with static initialization follows declaration with dynamic initialization}} \ + // expected-warning {{_Thread_local is a C11-specific feature}} +extern _Thread_local int t18; // expected-note {{previous declaration is here}} \ + // expected-warning {{_Thread_local is a C11-specific feature}} thread_local int t18; // expected-error {{thread-local declaration of 't18' with dynamic initialization follows declaration with static initialization}} #endif // PR13720 -__thread int thread_int; +__thread int thread_int; // thread-local-warning {{_Thread_local is a C11-specific feature}} int *thread_int_ptr = &thread_int; #ifndef __cplusplus // expected-error@-2 {{initializer element is not a compile-time constant}} @@ -84,7 +97,7 @@ constexpr int *thread_int_ptr_2 = &thread_int; // expected-error {{must be initi #endif int non_const(); -__thread int non_const_init = non_const(); +__thread int non_const_init = non_const(); // thread-local-warning {{_Thread_local is a C11-specific feature}} #if !defined(__cplusplus) // expected-error@-2 {{initializer element is not a compile-time constant}} #elif !defined(CXX11) @@ -98,7 +111,7 @@ __thread int non_const_init = non_const(); struct S { ~S(); }; -__thread S s; +__thread S s; // thread-local-warning {{_Thread_local is a C11-specific feature}} #if !defined(CXX11) // expected-error@-2 {{type of thread-local variable has non-trivial destruction}} #if __cplusplus >= 201103L @@ -111,7 +124,7 @@ __thread S s; struct HasCtor { HasCtor(); }; -__thread HasCtor var_with_ctor; +__thread HasCtor var_with_ctor; // thread-local-warning {{_Thread_local is a C11-specific feature}} #if !defined(CXX11) // expected-error@-2 {{initializer for thread-local variable must be a constant expression}} #if __cplusplus >= 201103L @@ -120,4 +133,4 @@ __thread HasCtor var_with_ctor; #endif #endif -__thread int aggregate[10] = {0}; +__thread int aggregate[10] = {0}; // thread-local-warning {{_Thread_local is a C11-specific feature}} diff --git a/clang/test/SemaOpenCLCXX/restricted.cl b/clang/test/SemaOpenCLCXX/restricted.cl index 3487285b6081..9798c92b6d76 100644 --- a/clang/test/SemaOpenCLCXX/restricted.cl +++ b/clang/test/SemaOpenCLCXX/restricted.cl @@ -31,6 +31,8 @@ B *test_dynamic_cast(B *p) { // Test storage class qualifiers. __constant _Thread_local int a = 1; // expected-error@-1 {{C++ for OpenCL version 1.0 does not support the '_Thread_local' storage class specifier}} +// expected-warning@-2 {{_Thread_local is a C11-specific feature}} + __constant __thread int b = 2; // expected-error@-1 {{C++ for OpenCL version 1.0 does not support the '__thread' storage class specifier}} kernel void test_storage_classes() {