In VarDecl nodes, store the thread storage class specifier as written.

llvm-svn: 181113
This commit is contained in:
Enea Zaffanella 2013-05-04 08:27:07 +00:00
parent fee13d1e11
commit acb8ecd664
10 changed files with 62 additions and 30 deletions

View File

@ -667,7 +667,7 @@ private:
friend class ASTDeclReader; friend class ASTDeclReader;
unsigned SClass : 3; unsigned SClass : 3;
unsigned TLSKind : 2; unsigned TSCSpec : 2;
unsigned InitStyle : 2; unsigned InitStyle : 2;
/// \brief Whether this variable is the exception variable in a C++ catch /// \brief Whether this variable is the exception variable in a C++ catch
@ -774,9 +774,23 @@ public:
} }
void setStorageClass(StorageClass SC); void setStorageClass(StorageClass SC);
void setTLSKind(TLSKind TLS) { VarDeclBits.TLSKind = TLS; } void setTSCSpec(ThreadStorageClassSpecifier TSC) {
VarDeclBits.TSCSpec = TSC;
}
ThreadStorageClassSpecifier getTSCSpec() const {
return static_cast<ThreadStorageClassSpecifier>(VarDeclBits.TSCSpec);
}
TLSKind getTLSKind() const { TLSKind getTLSKind() const {
return static_cast<TLSKind>(VarDeclBits.TLSKind); switch (VarDeclBits.TSCSpec) {
case TSCS_unspecified:
return TLS_None;
case TSCS___thread: // Fall through.
case TSCS__Thread_local:
return TLS_Static;
case TSCS_thread_local:
return TLS_Dynamic;
}
llvm_unreachable("Unknown thread storage class specifier!");
} }
/// hasLocalStorage - Returns true if a variable with function scope /// hasLocalStorage - Returns true if a variable with function scope

View File

@ -154,6 +154,19 @@ namespace clang {
TSK_ExplicitInstantiationDefinition TSK_ExplicitInstantiationDefinition
}; };
/// \brief Thread storage-class-specifier.
enum ThreadStorageClassSpecifier {
TSCS_unspecified,
/// GNU __thread.
TSCS___thread,
/// C++11 thread_local. Implies 'static' at block scope, but not at
/// class scope.
TSCS_thread_local,
/// C11 _Thread_local. Must be combined with either 'static' or 'extern'
/// if used at block scope.
TSCS__Thread_local
};
/// \brief Storage classes. /// \brief Storage classes.
enum StorageClass { enum StorageClass {
// These are legal on both functions and variables. // These are legal on both functions and variables.

View File

@ -226,19 +226,14 @@ public:
SCS_private_extern, SCS_private_extern,
SCS_mutable SCS_mutable
}; };
/// \brief Thread storage-class-specifier. These can be combined with
/// SCS_extern and SCS_static. // Import thread storage class specifier enumeration and constants.
enum TSCS { // These can be combined with SCS_extern and SCS_static.
TSCS_unspecified, typedef ThreadStorageClassSpecifier TSCS;
/// GNU __thread. static const TSCS TSCS_unspecified = clang::TSCS_unspecified;
TSCS___thread, static const TSCS TSCS___thread = clang::TSCS___thread;
/// C++11 thread_local. Implies 'static' at block scope, but not at static const TSCS TSCS_thread_local = clang::TSCS_thread_local;
/// class scope. static const TSCS TSCS__Thread_local = clang::TSCS__Thread_local;
TSCS_thread_local,
/// C11 _Thread_local. Must be combined with either 'static' or 'extern'
/// if used at block scope.
TSCS__Thread_local
};
// Import type specifier width enumeration and constants. // Import type specifier width enumeration and constants.
typedef TypeSpecifierWidth TSW; typedef TypeSpecifierWidth TSW;

View File

@ -647,13 +647,16 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
if (SC != SC_None) if (SC != SC_None)
Out << VarDecl::getStorageClassSpecifierString(SC) << " "; Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
switch (D->getTLSKind()) { switch (D->getTSCSpec()) {
case VarDecl::TLS_None: case TSCS_unspecified:
break; break;
case VarDecl::TLS_Static: case TSCS___thread:
Out << "__thread ";
break;
case TSCS__Thread_local:
Out << "_Thread_local "; Out << "_Thread_local ";
break; break;
case VarDecl::TLS_Dynamic: case TSCS_thread_local:
Out << "thread_local "; Out << "thread_local ";
break; break;
} }

View File

@ -1623,7 +1623,7 @@ CodeGenModule::MaybeEmitGlobalStdInitializerListInitializer(const VarDecl *D,
D->getLocStart(), D->getLocation(), D->getLocStart(), D->getLocation(),
name, arrayType, sourceInfo, name, arrayType, sourceInfo,
SC_Static); SC_Static);
backingArray->setTLSKind(D->getTLSKind()); backingArray->setTSCSpec(D->getTSCSpec());
// Now clone the InitListExpr to initialize the array instead. // Now clone the InitListExpr to initialize the array instead.
// Incredible hack: we want to use the existing InitListExpr here, so we need // Incredible hack: we want to use the existing InitListExpr here, so we need

View File

@ -4897,9 +4897,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_thread_unsupported); diag::err_thread_unsupported);
else else
NewVD->setTLSKind(TSCS == DeclSpec::TSCS_thread_local NewVD->setTSCSpec(TSCS);
? VarDecl::TLS_Dynamic
: VarDecl::TLS_Static);
} }
// C99 6.7.4p3 // C99 6.7.4p3

View File

@ -339,7 +339,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
D->getLocation(), D->getIdentifier(), D->getLocation(), D->getIdentifier(),
DI->getType(), DI, DI->getType(), DI,
D->getStorageClass()); D->getStorageClass());
Var->setTLSKind(D->getTLSKind()); Var->setTSCSpec(D->getTSCSpec());
Var->setInitStyle(D->getInitStyle()); Var->setInitStyle(D->getInitStyle());
Var->setCXXForRangeDecl(D->isCXXForRangeDecl()); Var->setCXXForRangeDecl(D->isCXXForRangeDecl());
Var->setConstexpr(D->isConstexpr()); Var->setConstexpr(D->isConstexpr());

View File

@ -904,7 +904,7 @@ void ASTDeclReader::VisitVarDecl(VarDecl *VD) {
VisitDeclaratorDecl(VD); VisitDeclaratorDecl(VD);
VD->VarDeclBits.SClass = (StorageClass)Record[Idx++]; VD->VarDeclBits.SClass = (StorageClass)Record[Idx++];
VD->VarDeclBits.TLSKind = Record[Idx++]; VD->VarDeclBits.TSCSpec = Record[Idx++];
VD->VarDeclBits.InitStyle = Record[Idx++]; VD->VarDeclBits.InitStyle = Record[Idx++];
VD->VarDeclBits.ExceptionVar = Record[Idx++]; VD->VarDeclBits.ExceptionVar = Record[Idx++];
VD->VarDeclBits.NRVOVariable = Record[Idx++]; VD->VarDeclBits.NRVOVariable = Record[Idx++];

View File

@ -687,7 +687,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
VisitRedeclarable(D); VisitRedeclarable(D);
VisitDeclaratorDecl(D); VisitDeclaratorDecl(D);
Record.push_back(D->getStorageClass()); Record.push_back(D->getStorageClass());
Record.push_back(D->getTLSKind()); Record.push_back(D->getTSCSpec());
Record.push_back(D->getInitStyle()); Record.push_back(D->getInitStyle());
Record.push_back(D->isExceptionVariable()); Record.push_back(D->isExceptionVariable());
Record.push_back(D->isNRVOVariable()); Record.push_back(D->isNRVOVariable());
@ -776,7 +776,7 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
// Check things we know are true of *every* PARM_VAR_DECL, which is more than // Check things we know are true of *every* PARM_VAR_DECL, which is more than
// just us assuming it. // just us assuming it.
assert(!D->getTLSKind() && "PARM_VAR_DECL can't use TLS"); assert(!D->getTSCSpec() && "PARM_VAR_DECL can't use TLS");
assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private"); assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private");
assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var"); assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var");
assert(D->getPreviousDecl() == 0 && "PARM_VAR_DECL can't be redecl"); assert(D->getPreviousDecl() == 0 && "PARM_VAR_DECL can't be redecl");
@ -1534,7 +1534,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
// VarDecl // VarDecl
Abv->Add(BitCodeAbbrevOp(0)); // StorageClass Abv->Add(BitCodeAbbrevOp(0)); // StorageClass
Abv->Add(BitCodeAbbrevOp(0)); // getTLSKind Abv->Add(BitCodeAbbrevOp(0)); // getTSCSpec
Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer
Abv->Add(BitCodeAbbrevOp(0)); // isExceptionVariable Abv->Add(BitCodeAbbrevOp(0)); // isExceptionVariable
Abv->Add(BitCodeAbbrevOp(0)); // isNRVOVariable Abv->Add(BitCodeAbbrevOp(0)); // isNRVOVariable
@ -1613,7 +1613,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
// VarDecl // VarDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // StorageClass Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // StorageClass
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // getTLSKind Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // getTSCSpec
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // CXXDirectInitializer Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // CXXDirectInitializer
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isExceptionVariable Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isExceptionVariable
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNRVOVariable Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNRVOVariable

View File

@ -41,3 +41,12 @@ const char *p10 = 3.300e+15_fritz;
// CHECK: ; // CHECK: ;
; ;
// CHECK-NOT: ; // CHECK-NOT: ;
// CHECK: __thread int gnu_tl;
// CHECK: _Thread_local int c11_tl;
// CHECK: thread_local int cxx11_tl;
__thread int gnu_tl;
_Thread_local int c11_tl;
thread_local int cxx11_tl;