summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGBlocks.cpp
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@apple.com>2016-05-04 18:40:33 +0000
committerAkira Hatanaka <ahatanaka@apple.com>2016-05-04 18:40:33 +0000
commit1cce6e15c1d4bb41d52072c85f47e70e4fb5ca92 (patch)
tree078cc434b6d918b6305b319db66ec5e0fe7607f3 /clang/lib/CodeGen/CGBlocks.cpp
parentcc9676a82111d28611e33e4f28cc0555575e863f (diff)
downloadbcm5719-llvm-1cce6e15c1d4bb41d52072c85f47e70e4fb5ca92.tar.gz
bcm5719-llvm-1cce6e15c1d4bb41d52072c85f47e70e4fb5ca92.zip
[CodeGenObjCXX] Fix handling of blocks in lambda.
This fixes a crash that occurs when a block captures a reference that is captured by its enclosing lambda. rdar://problem/18586651 Differential Revision: http://reviews.llvm.org/D19536 llvm-svn: 268532
Diffstat (limited to 'clang/lib/CodeGen/CGBlocks.cpp')
-rw-r--r--clang/lib/CodeGen/CGBlocks.cpp50
1 files changed, 24 insertions, 26 deletions
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index d603d21bbe0..1389749195c 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -780,35 +780,34 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// Compute the address of the thing we're going to move into the
// block literal.
Address src = Address::invalid();
- if (BlockInfo && CI.isNested()) {
- // We need to use the capture from the enclosing block.
- const CGBlockInfo::Capture &enclosingCapture =
- BlockInfo->getCapture(variable);
-
- // This is a [[type]]*, except that a byref entry wil just be an i8**.
- src = Builder.CreateStructGEP(LoadBlockStruct(),
- enclosingCapture.getIndex(),
- enclosingCapture.getOffset(),
- "block.capture.addr");
- } else if (blockDecl->isConversionFromLambda()) {
+
+ if (blockDecl->isConversionFromLambda()) {
// The lambda capture in a lambda's conversion-to-block-pointer is
// special; we'll simply emit it directly.
src = Address::invalid();
- } else {
- // Just look it up in the locals map, which will give us back a
- // [[type]]*. If that doesn't work, do the more elaborate DRE
- // emission.
- auto it = LocalDeclMap.find(variable);
- if (it != LocalDeclMap.end()) {
- src = it->second;
+ } else if (CI.isByRef()) {
+ if (BlockInfo && CI.isNested()) {
+ // We need to use the capture from the enclosing block.
+ const CGBlockInfo::Capture &enclosingCapture =
+ BlockInfo->getCapture(variable);
+
+ // This is a [[type]]*, except that a byref entry wil just be an i8**.
+ src = Builder.CreateStructGEP(LoadBlockStruct(),
+ enclosingCapture.getIndex(),
+ enclosingCapture.getOffset(),
+ "block.capture.addr");
} else {
- DeclRefExpr declRef(
- const_cast<VarDecl *>(variable),
- /*RefersToEnclosingVariableOrCapture*/ CI.isNested(), type,
- VK_LValue, SourceLocation());
- src = EmitDeclRefLValue(&declRef).getAddress();
+ auto I = LocalDeclMap.find(variable);
+ assert(I != LocalDeclMap.end());
+ src = I->second;
}
- }
+ } else {
+ DeclRefExpr declRef(const_cast<VarDecl *>(variable),
+ /*RefersToEnclosingVariableOrCapture*/ CI.isNested(),
+ type.getNonReferenceType(), VK_LValue,
+ SourceLocation());
+ src = EmitDeclRefLValue(&declRef).getAddress();
+ };
// For byrefs, we just write the pointer to the byref struct into
// the block field. There's no need to chase the forwarding
@@ -842,8 +841,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// If it's a reference variable, copy the reference into the block field.
} else if (type->isReferenceType()) {
- llvm::Value *ref = Builder.CreateLoad(src, "ref.val");
- Builder.CreateStore(ref, blockField);
+ Builder.CreateStore(src.getPointer(), blockField);
// If this is an ARC __strong block-pointer variable, don't do a
// block copy.
OpenPOWER on IntegriCloud