diff options
author | John McCall <rjmccall@apple.com> | 2011-01-05 12:14:39 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-01-05 12:14:39 +0000 |
commit | 711c52bb20d0c69063b52a99826fb7d2835501f1 (patch) | |
tree | 1204cedce5b080f16d43c49f872699498bace6a7 /lib/CodeGen/CGBlocks.cpp | |
parent | e6bf90aec0044342ffccd13201b8a3a31a985a4b (diff) |
Refactor the application of type attributes so that attributes from
the declaration-specifiers and on the declarator itself are moved
to the appropriate declarator chunk. This permits a greatly
simplified model for how to apply these attributes, as well as
allowing a much more efficient query for the GC attribute.
Now all qualifier queries follow the same basic strategy of
"local qualifiers, local qualifiers on the canonical type,
then look through arrays". This can be easily optimized by
changing the canonical qualified-array-type representation.
Do not process type attributes as decl attributes on declarations
with declarators.
When computing the type of a block, synthesize a prototype
function declarator chunk if the decl-spec type was not a
function. This simplifies the logic for building block signatures.
Change the logic which inserts an objc_read_weak on a block
literal to only fire if the block has a __weak __block variable,
rather than if the return type of the block is __weak qualified,
which is not actually a sensible thing to ask.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122871 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGBlocks.cpp')
-rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 510db0b1ff..36767711b4 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/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; } |