From 9cbcab88d441761b5c5d7811c4d0c205250991bf Mon Sep 17 00:00:00 2001 From: Enea Zaffanella Date: Fri, 10 May 2013 20:34:44 +0000 Subject: [PATCH] Avoid patching storage class for block scope thread_local variables. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181627 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Decl.h | 8 ++++-- lib/Sema/SemaDecl.cpp | 33 ++++++++++++----------- test/SemaCXX/cxx11-thread-local-print.cpp | 6 +++++ 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index a0c76c069b..d5e6ebee4a 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -797,7 +797,8 @@ public: /// is a non-static local variable. bool hasLocalStorage() const { if (getStorageClass() == SC_None) - return !isFileVarDecl(); + // Second check is for C++11 [dcl.stc]p4. + return !isFileVarDecl() && getTSCSpec() != TSCS_thread_local; // Return true for: Auto, Register. // Return false for: Extern, Static, PrivateExtern, OpenCLWorkGroupLocal. @@ -808,7 +809,10 @@ public: /// isStaticLocal - Returns true if a variable with function scope is a /// static local variable. bool isStaticLocal() const { - return getStorageClass() == SC_Static && !isFileVarDecl(); + return (getStorageClass() == SC_Static || + // C++11 [dcl.stc]p4 + (getStorageClass() == SC_None && getTSCSpec() == TSCS_thread_local)) + && !isFileVarDecl(); } /// \brief Returns true if a variable has extern or __private_extern__ diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index d14b10559d..5d8839a65b 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4718,16 +4718,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, SC = SC_None; } - // C++11 [dcl.stc]p4: - // When thread_local is applied to a variable of block scope the - // storage-class-specifier static is implied if it does not appear - // explicitly. - // Core issue: 'static' is not implied if the variable is declared 'extern'. - if (SCSpec == DeclSpec::SCS_unspecified && - D.getDeclSpec().getThreadStorageClassSpec() == - DeclSpec::TSCS_thread_local && DC->isFunctionOrMethod()) - SC = SC_Static; - IdentifierInfo *II = Name.getAsIdentifierInfo(); if (!II) { Diag(D.getIdentifierLoc(), diag::err_bad_variable_name) @@ -4885,11 +4875,22 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewVD->setLexicalDeclContext(CurContext); if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) { - if (NewVD->hasLocalStorage()) - Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), - diag::err_thread_non_global) - << DeclSpec::getSpecifierName(TSCS); - else if (!Context.getTargetInfo().isTLSSupported()) + if (NewVD->hasLocalStorage()) { + // C++11 [dcl.stc]p4: + // When thread_local is applied to a variable of block scope the + // storage-class-specifier static is implied if it does not appear + // explicitly. + // Core issue: 'static' is not implied if the variable is declared + // 'extern'. + if (SCSpec == DeclSpec::SCS_unspecified && + TSCS == DeclSpec::TSCS_thread_local && + DC->isFunctionOrMethod()) + NewVD->setTSCSpec(TSCS); + else + Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), + diag::err_thread_non_global) + << DeclSpec::getSpecifierName(TSCS); + } else if (!Context.getTargetInfo().isTLSSupported()) Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), diag::err_thread_unsupported); else @@ -5237,7 +5238,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { if (NewVD->isFileVarDecl()) Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope) << SizeRange; - else if (NewVD->getStorageClass() == SC_Static) + else if (NewVD->isStaticLocal()) Diag(NewVD->getLocation(), diag::err_vla_decl_has_static_storage) << SizeRange; else diff --git a/test/SemaCXX/cxx11-thread-local-print.cpp b/test/SemaCXX/cxx11-thread-local-print.cpp index 9d9a82b7e6..1adafbda49 100644 --- a/test/SemaCXX/cxx11-thread-local-print.cpp +++ b/test/SemaCXX/cxx11-thread-local-print.cpp @@ -7,3 +7,9 @@ __thread int gnu_tl; _Thread_local int c11_tl; thread_local int cxx11_tl; +// CHECK: void foo() { +// CHECK: thread_local int cxx11_tl; +// CHECK: } +void foo() { + thread_local int cxx11_tl; +} -- 2.40.0