From dc17384581e37436582a007be4d9185bcf7003ec Mon Sep 17 00:00:00 2001 From: Enea Zaffanella Date: Sat, 4 May 2013 08:27:07 +0000 Subject: [PATCH] In VarDecl nodes, store the thread storage class specifier as written. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181113 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Decl.h | 20 +++++++++++++++++--- include/clang/Basic/Specifiers.h | 13 +++++++++++++ include/clang/Sema/DeclSpec.h | 21 ++++++++------------- lib/AST/DeclPrinter.cpp | 11 +++++++---- lib/CodeGen/CodeGenModule.cpp | 2 +- lib/Sema/SemaDecl.cpp | 4 +--- lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 +- lib/Serialization/ASTReaderDecl.cpp | 2 +- lib/Serialization/ASTWriterDecl.cpp | 8 ++++---- test/SemaCXX/cxx11-ast-print.cpp | 9 +++++++++ 10 files changed, 62 insertions(+), 30 deletions(-) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index ea6479ad28..d0bf559d1e 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -667,7 +667,7 @@ private: friend class ASTDeclReader; unsigned SClass : 3; - unsigned TLSKind : 2; + unsigned TSCSpec : 2; unsigned InitStyle : 2; /// \brief Whether this variable is the exception variable in a C++ catch @@ -774,9 +774,23 @@ public: } void setStorageClass(StorageClass SC); - void setTLSKind(TLSKind TLS) { VarDeclBits.TLSKind = TLS; } + void setTSCSpec(ThreadStorageClassSpecifier TSC) { + VarDeclBits.TSCSpec = TSC; + } + ThreadStorageClassSpecifier getTSCSpec() const { + return static_cast(VarDeclBits.TSCSpec); + } TLSKind getTLSKind() const { - return static_cast(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 diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index b9fda06b45..eb3fc659a8 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -154,6 +154,19 @@ namespace clang { 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. enum StorageClass { // These are legal on both functions and variables. diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index fc818953d8..059919a35b 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -226,19 +226,14 @@ public: SCS_private_extern, SCS_mutable }; - /// \brief Thread storage-class-specifier. These can be combined with - /// SCS_extern and SCS_static. - enum TSCS { - 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 - }; + + // Import thread storage class specifier enumeration and constants. + // These can be combined with SCS_extern and SCS_static. + typedef ThreadStorageClassSpecifier TSCS; + static const TSCS TSCS_unspecified = clang::TSCS_unspecified; + static const TSCS TSCS___thread = clang::TSCS___thread; + static const TSCS TSCS_thread_local = clang::TSCS_thread_local; + static const TSCS TSCS__Thread_local = clang::TSCS__Thread_local; // Import type specifier width enumeration and constants. typedef TypeSpecifierWidth TSW; diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index ba590d61c8..d47972bc61 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -647,13 +647,16 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) { if (SC != SC_None) Out << VarDecl::getStorageClassSpecifierString(SC) << " "; - switch (D->getTLSKind()) { - case VarDecl::TLS_None: + switch (D->getTSCSpec()) { + case TSCS_unspecified: break; - case VarDecl::TLS_Static: + case TSCS___thread: + Out << "__thread "; + break; + case TSCS__Thread_local: Out << "_Thread_local "; break; - case VarDecl::TLS_Dynamic: + case TSCS_thread_local: Out << "thread_local "; break; } diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 66c3983a4b..6ebd1d1410 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1623,7 +1623,7 @@ CodeGenModule::MaybeEmitGlobalStdInitializerListInitializer(const VarDecl *D, D->getLocStart(), D->getLocation(), name, arrayType, sourceInfo, SC_Static); - backingArray->setTLSKind(D->getTLSKind()); + backingArray->setTSCSpec(D->getTSCSpec()); // Now clone the InitListExpr to initialize the array instead. // Incredible hack: we want to use the existing InitListExpr here, so we need diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 06697fafe6..84aa07927c 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4897,9 +4897,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), diag::err_thread_unsupported); else - NewVD->setTLSKind(TSCS == DeclSpec::TSCS_thread_local - ? VarDecl::TLS_Dynamic - : VarDecl::TLS_Static); + NewVD->setTSCSpec(TSCS); } // C99 6.7.4p3 diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 688a7360ad..42e1757bcb 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -339,7 +339,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { D->getLocation(), D->getIdentifier(), DI->getType(), DI, D->getStorageClass()); - Var->setTLSKind(D->getTLSKind()); + Var->setTSCSpec(D->getTSCSpec()); Var->setInitStyle(D->getInitStyle()); Var->setCXXForRangeDecl(D->isCXXForRangeDecl()); Var->setConstexpr(D->isConstexpr()); diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 06cdeaf8a0..f7fa818e9b 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -904,7 +904,7 @@ void ASTDeclReader::VisitVarDecl(VarDecl *VD) { VisitDeclaratorDecl(VD); VD->VarDeclBits.SClass = (StorageClass)Record[Idx++]; - VD->VarDeclBits.TLSKind = Record[Idx++]; + VD->VarDeclBits.TSCSpec = Record[Idx++]; VD->VarDeclBits.InitStyle = Record[Idx++]; VD->VarDeclBits.ExceptionVar = Record[Idx++]; VD->VarDeclBits.NRVOVariable = Record[Idx++]; diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 73cdda5212..67349db687 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -687,7 +687,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { VisitRedeclarable(D); VisitDeclaratorDecl(D); Record.push_back(D->getStorageClass()); - Record.push_back(D->getTLSKind()); + Record.push_back(D->getTSCSpec()); Record.push_back(D->getInitStyle()); Record.push_back(D->isExceptionVariable()); 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 // 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->isExceptionVariable() && "PARM_VAR_DECL can't be exception var"); assert(D->getPreviousDecl() == 0 && "PARM_VAR_DECL can't be redecl"); @@ -1534,7 +1534,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo // VarDecl Abv->Add(BitCodeAbbrevOp(0)); // StorageClass - Abv->Add(BitCodeAbbrevOp(0)); // getTLSKind + Abv->Add(BitCodeAbbrevOp(0)); // getTSCSpec Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer Abv->Add(BitCodeAbbrevOp(0)); // isExceptionVariable Abv->Add(BitCodeAbbrevOp(0)); // isNRVOVariable @@ -1613,7 +1613,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo // VarDecl 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)); // isExceptionVariable Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNRVOVariable diff --git a/test/SemaCXX/cxx11-ast-print.cpp b/test/SemaCXX/cxx11-ast-print.cpp index f95eeb50fe..b239762bb0 100644 --- a/test/SemaCXX/cxx11-ast-print.cpp +++ b/test/SemaCXX/cxx11-ast-print.cpp @@ -41,3 +41,12 @@ const char *p10 = 3.300e+15_fritz; // CHECK: ; ; // 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; + -- 2.40.0