summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-04-13 02:43:54 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-04-13 02:43:54 +0000
commitfd3834f7a1cc06f3843a83080c65eadb613927f4 (patch)
tree8b34c1ec3249c0d7d89aad10e848997a321e94c3 /clang/lib
parent98c0eaecf51606fb1b83cdec6e6ddeaf091a61cc (diff)
downloadbcm5719-llvm-fd3834f7a1cc06f3843a83080c65eadb613927f4.tar.gz
bcm5719-llvm-fd3834f7a1cc06f3843a83080c65eadb613927f4.zip
Annotate flavor of TLS variable (statically or dynamically initialized) onto the AST.
llvm-svn: 179447
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTDumper.cpp7
-rw-r--r--clang/lib/AST/DeclPrinter.cpp25
-rw-r--r--clang/lib/AST/ExprConstant.cpp2
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp2
-rw-r--r--clang/lib/CodeGen/CGDeclCXX.cpp8
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp2
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp6
-rw-r--r--clang/lib/Sema/SemaDecl.cpp30
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp4
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp4
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp3
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp2
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp2
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp8
14 files changed, 67 insertions, 38 deletions
diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp
index b1d174b855e..340cc41f7e8 100644
--- a/clang/lib/AST/ASTDumper.cpp
+++ b/clang/lib/AST/ASTDumper.cpp
@@ -853,8 +853,11 @@ void ASTDumper::VisitVarDecl(const VarDecl *D) {
StorageClass SC = D->getStorageClass();
if (SC != SC_None)
OS << ' ' << VarDecl::getStorageClassSpecifierString(SC);
- if (D->isThreadSpecified())
- OS << " __thread";
+ switch (D->getTLSKind()) {
+ case VarDecl::TLS_None: break;
+ case VarDecl::TLS_Static: OS << " tls"; break;
+ case VarDecl::TLS_Dynamic: OS << " tls_dynamic"; break;
+ }
if (D->isModulePrivate())
OS << " __module_private__";
if (D->isNRVOVariable())
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index c3bf8f89b29..995925350c3 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -641,14 +641,25 @@ void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
void DeclPrinter::VisitVarDecl(VarDecl *D) {
- StorageClass SC = D->getStorageClass();
- if (!Policy.SuppressSpecifiers && SC != SC_None)
- Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
+ if (!Policy.SuppressSpecifiers) {
+ StorageClass SC = D->getStorageClass();
+ if (SC != SC_None)
+ Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
- if (!Policy.SuppressSpecifiers && D->isThreadSpecified())
- Out << "__thread ";
- if (!Policy.SuppressSpecifiers && D->isModulePrivate())
- Out << "__module_private__ ";
+ switch (D->getTLSKind()) {
+ case VarDecl::TLS_None:
+ break;
+ case VarDecl::TLS_Static:
+ Out << "_Thread_local ";
+ break;
+ case VarDecl::TLS_Dynamic:
+ Out << "thread_local ";
+ break;
+ }
+
+ if (D->isModulePrivate())
+ Out << "__module_private__ ";
+ }
QualType T = D->getType();
if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D))
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index d7abe3082e5..d499228af32 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -999,7 +999,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
// Check if this is a thread-local variable.
if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) {
if (const VarDecl *Var = dyn_cast<const VarDecl>(VD)) {
- if (Var->isThreadSpecified())
+ if (Var->getTLSKind())
return false;
}
}
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 5375c5e18f2..8865399b70e 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -198,7 +198,7 @@ CodeGenFunction::CreateStaticVarDecl(const VarDecl &D,
if (Linkage != llvm::GlobalValue::InternalLinkage)
GV->setVisibility(CurFn->getVisibility());
- if (D.isThreadSpecified())
+ if (D.getTLSKind())
CGM.setTLSMode(GV, D);
return GV;
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index 0448d31f407..609f6aa7c6e 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -39,7 +39,7 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
CodeGenModule &CGM = CGF.CGM;
if (lv.isObjCStrong())
CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, CGF.EmitScalarExpr(Init),
- DeclPtr, D.isThreadSpecified());
+ DeclPtr, D.getTLSKind());
else if (lv.isObjCWeak())
CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, CGF.EmitScalarExpr(Init),
DeclPtr);
@@ -218,6 +218,9 @@ void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
"this initialization requires a guard variable, which "
"the kernel does not support");
+ if (D.getTLSKind())
+ CGM.ErrorUnsupported(D.getInit(), "dynamic TLS initialization");
+
CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr, PerformInit);
}
@@ -254,6 +257,9 @@ void
CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
llvm::GlobalVariable *Addr,
bool PerformInit) {
+ if (D->getTLSKind())
+ ErrorUnsupported(D->getInit(), "dynamic TLS initialization");
+
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
// Create a variable initialization function.
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 4d72dc1c884..c5155088758 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1667,7 +1667,7 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
if (const VarDecl *VD = dyn_cast<VarDecl>(Exp->getDecl())) {
if (VD->hasGlobalStorage()) {
LV.setGlobalObjCRef(true);
- LV.setThreadLocalRef(VD->isThreadSpecified());
+ LV.setThreadLocalRef(VD->getTLSKind() != VarDecl::TLS_None);
}
}
LV.setObjCArray(E->getType()->isArrayType());
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index aacabc78679..20532d68c9e 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -333,7 +333,7 @@ static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel(
void CodeGenModule::setTLSMode(llvm::GlobalVariable *GV,
const VarDecl &D) const {
- assert(D.isThreadSpecified() && "setting TLS mode on non-TLS var!");
+ assert(D.getTLSKind() && "setting TLS mode on non-TLS var!");
llvm::GlobalVariable::ThreadLocalMode TLM;
TLM = GetLLVMTLSModel(CodeGenOpts.getDefaultTLSModel());
@@ -1485,7 +1485,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
GV->setVisibility(GetLLVMVisibility(LV.getVisibility()));
}
- if (D->isThreadSpecified())
+ if (D->getTLSKind())
setTLSMode(GV, *D);
}
@@ -1915,7 +1915,7 @@ CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D,
((!CodeGenOpts.NoCommon && !D->getAttr<NoCommonAttr>()) ||
D->getAttr<CommonAttr>()) &&
!D->hasExternalStorage() && !D->getInit() &&
- !D->getAttr<SectionAttr>() && !D->isThreadSpecified() &&
+ !D->getAttr<SectionAttr>() && !D->getTLSKind() &&
!D->getAttr<WeakImportAttr>()) {
// Thread local vars aren't considered common linkage.
return llvm::GlobalVariable::CommonLinkage;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index a2c3c2e1472..b3cbbf203e2 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2953,12 +2953,22 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous,
return New->setInvalidDecl();
}
- if (New->isThreadSpecified() && !Old->isThreadSpecified()) {
- Diag(New->getLocation(), diag::err_thread_non_thread) << New->getDeclName();
- Diag(Old->getLocation(), diag::note_previous_definition);
- } else if (!New->isThreadSpecified() && Old->isThreadSpecified()) {
- Diag(New->getLocation(), diag::err_non_thread_thread) << New->getDeclName();
- Diag(Old->getLocation(), diag::note_previous_definition);
+ if (New->getTLSKind() != Old->getTLSKind()) {
+ if (!Old->getTLSKind()) {
+ Diag(New->getLocation(), diag::err_thread_non_thread) << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ } else if (!New->getTLSKind()) {
+ Diag(New->getLocation(), diag::err_non_thread_thread) << New->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ } else {
+ // Do not allow redeclaration to change the variable between requiring
+ // static and dynamic initialization.
+ // FIXME: GCC allows this, but uses the TLS keyword on the first
+ // declaration to determine the kind. Do we need to be compatible here?
+ Diag(New->getLocation(), diag::err_thread_thread_different_kind)
+ << New->getDeclName() << (New->getTLSKind() == VarDecl::TLS_Dynamic);
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ }
}
// C++ doesn't have tentative definitions, so go right ahead and check here.
@@ -4577,7 +4587,7 @@ bool Sema::inferObjCARCLifetime(ValueDecl *decl) {
if (VarDecl *var = dyn_cast<VarDecl>(decl)) {
// Thread-local variables cannot have lifetime.
if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone &&
- var->isThreadSpecified()) {
+ var->getTLSKind()) {
Diag(var->getLocation(), diag::err_arc_thread_ownership)
<< var->getType();
return true;
@@ -4851,9 +4861,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_thread_unsupported);
else
- // FIXME: Track which thread specifier was used; they have different
- // semantics.
- NewVD->setThreadSpecified(true);
+ NewVD->setTLSKind(TSCS == DeclSpec::TSCS_thread_local
+ ? VarDecl::TLS_Dynamic
+ : VarDecl::TLS_Static);
}
// C99 6.7.4p3
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index f832809b2df..1fc1a7cc488 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -284,7 +284,7 @@ static bool mayBeSharedVariable(const Decl *D) {
if (isa<FieldDecl>(D))
return true;
if (const VarDecl *vd = dyn_cast<VarDecl>(D))
- return (vd->hasGlobalStorage() && !(vd->isThreadSpecified()));
+ return vd->hasGlobalStorage() && !vd->getTLSKind();
return false;
}
@@ -1656,7 +1656,7 @@ static void handleTLSModelAttr(Sema &S, Decl *D,
return;
}
- if (!isa<VarDecl>(D) || !cast<VarDecl>(D)->isThreadSpecified()) {
+ if (!isa<VarDecl>(D) || !cast<VarDecl>(D)->getTLSKind()) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedTLSVar;
return;
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index b8acb2d7310..c815d4f9abc 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -165,8 +165,8 @@ OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
continue;
}
- // Check if threadspecified is set.
- if (VD->isThreadSpecified()) {
+ // Check if this is a TLS variable.
+ if (VD->getTLSKind()) {
Diag(ILoc, diag::err_omp_var_thread_local) << VD;
Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
continue;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 990626189e1..ae091e3da34 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3842,8 +3842,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
}
// A template argument must have static storage duration.
- // FIXME: Ensure this works for thread_local as well as __thread.
- if (Var->isThreadSpecified()) {
+ if (Var->getTLSKind()) {
S.Diag(Arg->getLocStart(), diag::err_template_arg_thread_local)
<< Arg->getSourceRange();
S.Diag(Var->getLocation(), diag::note_template_arg_refers_here);
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 17e3218bffc..868369e87cd 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -339,7 +339,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
D->getLocation(), D->getIdentifier(),
DI->getType(), DI,
D->getStorageClass());
- Var->setThreadSpecified(D->isThreadSpecified());
+ Var->setTLSKind(D->getTLSKind());
Var->setInitStyle(D->getInitStyle());
Var->setCXXForRangeDecl(D->isCXXForRangeDecl());
Var->setConstexpr(D->isConstexpr());
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 0fbdd7e5dae..cad6ea77b67 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -895,7 +895,7 @@ void ASTDeclReader::VisitVarDecl(VarDecl *VD) {
VisitDeclaratorDecl(VD);
VD->VarDeclBits.SClass = (StorageClass)Record[Idx++];
- VD->VarDeclBits.ThreadSpecified = Record[Idx++];
+ VD->VarDeclBits.TLSKind = Record[Idx++];
VD->VarDeclBits.InitStyle = Record[Idx++];
VD->VarDeclBits.ExceptionVar = Record[Idx++];
VD->VarDeclBits.NRVOVariable = Record[Idx++];
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 023599d0db8..ef9e60f32e8 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -677,7 +677,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
VisitRedeclarable(D);
VisitDeclaratorDecl(D);
Record.push_back(D->getStorageClass());
- Record.push_back(D->isThreadSpecified());
+ Record.push_back(D->getTLSKind());
Record.push_back(D->getInitStyle());
Record.push_back(D->isExceptionVariable());
Record.push_back(D->isNRVOVariable());
@@ -766,7 +766,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->isThreadSpecified() && "PARM_VAR_DECL can't be __thread");
+ assert(!D->getTLSKind() && "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");
@@ -1515,7 +1515,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
// VarDecl
Abv->Add(BitCodeAbbrevOp(0)); // StorageClass
- Abv->Add(BitCodeAbbrevOp(0)); // isThreadSpecified
+ Abv->Add(BitCodeAbbrevOp(0)); // getTLSKind
Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer
Abv->Add(BitCodeAbbrevOp(0)); // isExceptionVariable
Abv->Add(BitCodeAbbrevOp(0)); // isNRVOVariable
@@ -1594,7 +1594,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
// VarDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // StorageClass
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isThreadSpecified
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // getTLSKind
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // CXXDirectInitializer
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isExceptionVariable
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNRVOVariable
OpenPOWER on IntegriCloud