summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-03-26 22:48:22 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-03-26 22:48:22 +0000
commit0f38374f718559e3942907722db6a589769ff2de (patch)
tree7419af45ac4c4a2c8a841109d576317d60307e90
parentb220a129ca42d3327d799e975b768689445885bd (diff)
downloadbcm5719-llvm-0f38374f718559e3942907722db6a589769ff2de.tar.gz
bcm5719-llvm-0f38374f718559e3942907722db6a589769ff2de.zip
PR19254: If a thread_local data member of a class is accessed via member access
syntax, don't forget to run its initializer. llvm-svn: 204869
-rw-r--r--clang/lib/CodeGen/CGCXXABI.cpp5
-rw-r--r--clang/lib/CodeGen/CGCXXABI.h5
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp15
-rw-r--r--clang/lib/CodeGen/ItaniumCXXABI.cpp15
-rw-r--r--clang/test/CodeGenCXX/cxx11-thread-local.cpp10
5 files changed, 31 insertions, 19 deletions
diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp
index 72b84dc3e92..3d0eaa0914c 100644
--- a/clang/lib/CodeGen/CGCXXABI.cpp
+++ b/clang/lib/CodeGen/CGCXXABI.cpp
@@ -280,8 +280,9 @@ void CGCXXABI::EmitThreadLocalInitFuncs(
llvm::Function *InitFunc) {
}
-LValue CGCXXABI::EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF,
- const DeclRefExpr *DRE) {
+LValue CGCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
+ const VarDecl *VD,
+ QualType LValType) {
ErrorUnsupportedABI(CGF, "odr-use of thread_local global");
return LValue();
}
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h
index ea308f0ba4e..783cc594361 100644
--- a/clang/lib/CodeGen/CGCXXABI.h
+++ b/clang/lib/CodeGen/CGCXXABI.h
@@ -481,8 +481,9 @@ public:
/// Emit a reference to a non-local thread_local variable (including
/// triggering the initialization of all thread_local variables in its
/// translation unit).
- virtual LValue EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF,
- const DeclRefExpr *DRE);
+ virtual LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
+ const VarDecl *VD,
+ QualType LValType);
};
// Create an instance of a C++ ABI class:
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 5ba748a88d4..1bdd094873a 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1691,11 +1691,16 @@ EmitBitCastOfLValueToProperType(CodeGenFunction &CGF,
static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
const Expr *E, const VarDecl *VD) {
+ QualType T = E->getType();
+
+ // If it's thread_local, emit a call to its wrapper function instead.
+ if (VD->getTLSKind() == VarDecl::TLS_Dynamic)
+ return CGF.CGM.getCXXABI().EmitThreadLocalVarDeclLValue(CGF, VD, T);
+
llvm::Value *V = CGF.CGM.GetAddrOfGlobalVar(VD);
llvm::Type *RealVarTy = CGF.getTypes().ConvertTypeForMem(VD->getType());
V = EmitBitCastOfLValueToProperType(CGF, V, RealVarTy);
CharUnits Alignment = CGF.getContext().getDeclAlign(VD);
- QualType T = E->getType();
LValue LV;
if (VD->getType()->isReferenceType()) {
llvm::LoadInst *LI = CGF.Builder.CreateLoad(V);
@@ -1703,7 +1708,7 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
V = LI;
LV = CGF.MakeNaturalAlignAddrLValue(V, T);
} else {
- LV = CGF.MakeAddrLValue(V, E->getType(), Alignment);
+ LV = CGF.MakeAddrLValue(V, T, Alignment);
}
setObjCGCLValueClass(CGF.getContext(), E, LV);
return LV;
@@ -1770,12 +1775,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
// Check if this is a global variable.
- if (VD->hasLinkage() || VD->isStaticDataMember()) {
- // If it's thread_local, emit a call to its wrapper function instead.
- if (VD->getTLSKind() == VarDecl::TLS_Dynamic)
- return CGM.getCXXABI().EmitThreadLocalDeclRefExpr(*this, E);
+ if (VD->hasLinkage() || VD->isStaticDataMember())
return EmitGlobalVarDeclLValue(*this, E, VD);
- }
bool isBlockVariable = VD->hasAttr<BlocksAttr>();
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 7390a2113b5..9a2076d95ae 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -214,8 +214,8 @@ public:
void EmitThreadLocalInitFuncs(
llvm::ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *> > Decls,
llvm::Function *InitFunc) override;
- LValue EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF,
- const DeclRefExpr *DRE) override;
+ LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
+ QualType LValType) override;
bool NeedsVTTParameter(GlobalDecl GD) override;
};
@@ -1647,9 +1647,9 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
}
}
-LValue ItaniumCXXABI::EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF,
- const DeclRefExpr *DRE) {
- const VarDecl *VD = cast<VarDecl>(DRE->getDecl());
+LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
+ const VarDecl *VD,
+ QualType LValType) {
QualType T = VD->getType();
llvm::Type *Ty = CGF.getTypes().ConvertTypeForMem(T);
llvm::Value *Val = CGF.CGM.GetAddrOfGlobalVar(VD, Ty);
@@ -1660,10 +1660,9 @@ LValue ItaniumCXXABI::EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF,
LValue LV;
if (VD->getType()->isReferenceType())
- LV = CGF.MakeNaturalAlignAddrLValue(Val, T);
+ LV = CGF.MakeNaturalAlignAddrLValue(Val, LValType);
else
- LV = CGF.MakeAddrLValue(Val, DRE->getType(),
- CGF.getContext().getDeclAlign(VD));
+ LV = CGF.MakeAddrLValue(Val, LValType, CGF.getContext().getDeclAlign(VD));
// FIXME: need setObjCGCLValueClass?
return LV;
}
diff --git a/clang/test/CodeGenCXX/cxx11-thread-local.cpp b/clang/test/CodeGenCXX/cxx11-thread-local.cpp
index 509562dd8fc..86734cd79c8 100644
--- a/clang/test/CodeGenCXX/cxx11-thread-local.cpp
+++ b/clang/test/CodeGenCXX/cxx11-thread-local.cpp
@@ -135,6 +135,16 @@ int PR15991() {
return l();
}
+struct PR19254 {
+ static thread_local int n;
+ int f();
+};
+// CHECK: define {{.*}} @_ZN7PR192541fEv(
+int PR19254::f() {
+ // CHECK: call void @_ZTHN7PR192541nE(
+ return this->n;
+}
+
// CHECK: define {{.*}} @[[V_M_INIT:.*]]()
// CHECK: load i8* bitcast (i64* @_ZGVN1VIiE1mE to i8*)
// CHECK: %[[V_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0
OpenPOWER on IntegriCloud