[PATCH] D19536: [CodeGenObjCXX] Fix handling of blocks in lambda

Akira Hatanaka via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 26 09:48:11 PDT 2016


ahatanak created this revision.
ahatanak added a reviewer: rjmccall.
ahatanak added a subscriber: cfe-commits.

This fixes a crash that occurs when a block nested in a c++ lambda captures a reference that is captured by the enclosing lambda.

rdar://problem/18586651

http://reviews.llvm.org/D19536

Files:
  lib/CodeGen/CGBlocks.cpp
  test/CodeGenObjCXX/block-nested-in-lambda.cpp

Index: test/CodeGenObjCXX/block-nested-in-lambda.cpp
===================================================================
--- /dev/null
+++ test/CodeGenObjCXX/block-nested-in-lambda.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple=x86_64-apple-darwin10 -emit-llvm -std=c++11 -fblocks -o - %s | FileCheck %s
+
+// CHECK: %[[BLOCK_CAPTURED0:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32*, i32* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32*, i32* }>* %[[BLOCK:.*]], i32 0, i32 5
+// CHECK: %[[V0:.*]] = getelementptr inbounds %[[LAMBDA_CLASS:.*]], %[[LAMBDA_CLASS]]* %[[THIS:.*]], i32 0, i32 0
+// CHECK: %[[V1:.*]] = load i32*, i32** %[[V0]], align 8
+// CHECK: store i32* %[[V1]], i32** %[[BLOCK_CAPTURED0]], align 8
+// CHECK: %[[BLOCK_CAPTURED1:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32*, i32* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32*, i32* }>* %[[BLOCK]], i32 0, i32 6
+// CHECK: %[[V2:.*]] = getelementptr inbounds %[[LAMBDA_CLASS]], %[[LAMBDA_CLASS]]* %[[THIS]], i32 0, i32 1
+// CHECK: %[[V3:.*]] = load i32*, i32** %[[V2]], align 8
+// CHECK: store i32* %[[V3]], i32** %[[BLOCK_CAPTURED1]], align 8
+
+void foo1(int &, int &);
+
+void block_in_lambda(int &s1, int &s2) {
+  auto lambda = [&s1, &s2]() {
+    auto block = ^{
+      foo1(s1, s2);
+    };
+    block();
+  };
+
+  lambda();
+}
Index: lib/CodeGen/CGBlocks.cpp
===================================================================
--- lib/CodeGen/CGBlocks.cpp
+++ lib/CodeGen/CGBlocks.cpp
@@ -14,6 +14,7 @@
 #include "CGBlocks.h"
 #include "CGDebugInfo.h"
 #include "CGObjCRuntime.h"
+#include "CGRecordLayout.h"
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
 #include "clang/AST/DeclObjC.h"
@@ -789,6 +790,20 @@
       // The lambda capture in a lambda's conversion-to-block-pointer is
       // special; we'll simply emit it directly.
       src = Address::invalid();
+    } else if (FieldDecl *FD = LambdaCaptureFields.lookup(variable)) {
+      const RecordDecl *Rec = FD->getParent();
+      QualType TagType = getContext().getTagDeclType(Rec);
+      LValue LV = MakeNaturalAlignAddrLValue(CXXABIThisValue, TagType);
+      Address Addr = LV.getAddress();
+      unsigned Idx =
+          CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(FD);
+      CharUnits Offset;
+      if (Idx != 0) {
+        auto &RecLayout = getContext().getASTRecordLayout(Rec);
+        auto OffsetInBits = RecLayout.getFieldOffset(FD->getFieldIndex());
+        Offset = getContext().toCharUnitsFromBits(OffsetInBits);
+      }
+      src = Builder.CreateStructGEP(Addr, Idx, Offset, FD->getName());
     } 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


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D19536.55022.patch
Type: text/x-patch
Size: 2840 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160426/938931dc/attachment.bin>


More information about the cfe-commits mailing list