summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGBlocks.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGBlocks.cpp')
-rw-r--r--clang/lib/CodeGen/CGBlocks.cpp20
1 files changed, 14 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index 510db0b1ffc..36767711b48 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -198,6 +198,8 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
llvm::Constant *C;
llvm::Value *V;
+ bool hasWeakBlockVariable = false;
+
{
llvm::Constant *BlockVarLayout;
// C = BuildBlockStructInitlist();
@@ -268,6 +270,8 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
QualType Ty = E->getType();
if (BDRE && BDRE->isByRef()) {
+ if (BDRE->getDecl()->getType().isObjCGCWeak())
+ hasWeakBlockVariable = true;
Types[i+BlockFields] =
llvm::PointerType::get(BuildByRefType(BDRE->getDecl()), 0);
} else if (BDRE && BDRE->getDecl()->getType()->isReferenceType()) {
@@ -404,18 +408,22 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
QualType BPT = BE->getType();
V = Builder.CreateBitCast(V, ConvertType(BPT));
- // See if this is a __weak block variable and the must call objc_read_weak
- // on it.
- const FunctionType *ftype = BPT->getPointeeType()->getAs<FunctionType>();
- QualType RES = ftype->getResultType();
- if (RES.isObjCGCWeak()) {
+
+ // We must call objc_read_weak on the block literal itself if it closes
+ // on any __weak __block variables. For some reason.
+ if (hasWeakBlockVariable) {
+ const llvm::Type *OrigTy = V->getType();
+
// Must cast argument to id*
const llvm::Type *ObjectPtrTy =
ConvertType(CGM.getContext().getObjCIdType());
const llvm::Type *PtrObjectPtrTy =
llvm::PointerType::getUnqual(ObjectPtrTy);
V = Builder.CreateBitCast(V, PtrObjectPtrTy);
- V = CGM.getObjCRuntime().EmitObjCWeakRead(*this, V);
+ V = CGM.getObjCRuntime().EmitObjCWeakRead(*this, V);
+
+ // Cast back to the original type.
+ V = Builder.CreateBitCast(V, OrigTy);
}
return V;
}
OpenPOWER on IntegriCloud