Avoid patching storage class for block scope thread_local variables.

llvm-svn: 181627
This commit is contained in:
Enea Zaffanella 2013-05-10 20:34:44 +00:00
parent b8a98241fc
commit 28f36ba693
3 changed files with 29 additions and 18 deletions

View File

@ -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__

View File

@ -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

View File

@ -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;
}