forked from OSchip/llvm-project
In VarDecl nodes, store the thread storage class specifier as written.
llvm-svn: 181113
This commit is contained in:
parent
fee13d1e11
commit
acb8ecd664
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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++];
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue