[PATCH] D18618: [ObjC] Pop all cleanups created in CodeGenFunction::EmitObjCForCollectionStmt

Akira Hatanaka via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 30 12:54:28 PDT 2016


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

This patch fixes a bug where EmitObjCForCollectionStmt doesn't pop cleanups for captures.

For example, in the following for-in loop, a block which captures self is passed to foo1:

for (id x in [self foo1:^{ use(self); }]) {
  use(x);
  break;
}

The current code in EmitObjCForCollectionStmt doesn't pop the cleanup for the captured self before completing IR generation for the for-in loop. This causes code-gen to generate incorrect IR in which self gets released twice.

rdar://problem/16865751

http://reviews.llvm.org/D18618

Files:
  lib/CodeGen/CGObjC.cpp
  test/CodeGenObjC/arc-foreach.m

Index: test/CodeGenObjC/arc-foreach.m
===================================================================
--- test/CodeGenObjC/arc-foreach.m
+++ test/CodeGenObjC/arc-foreach.m
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple x86_64-apple-darwin -emit-llvm %s -o %t-64.s
 // RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
+// REQUIRES: asserts
 // rdar://9503326
 // rdar://9606600
 
@@ -170,4 +171,53 @@
   // CHECK-LP64-NEXT: br label [[L]]
 }
 
+ at interface NSObject @end
+
+ at interface I1 : NSObject
+- (NSArray *) foo1:(void (^)(void))block;
+- (void) foo2;
+ at end
+
+NSArray *array4;
+
+ at implementation I1 : NSObject
+- (NSArray *) foo1:(void (^)(void))block {
+  block();
+  return array4;
+}
+
+- (void) foo2 {
+  for (id x in [self foo1:^{ use(self); }]) {
+    use(x);
+    break;
+  }
+}
+ at end
+
+// CHECK-LP64-LABEL: define internal void @"\01-[I1 foo2]"(
+// CHECK-LP64:         [[SELF_ADDR:%.*]] = alloca [[TY:%.*]]*,
+// CHECK-LP64:         [[BLOCK:%.*]] = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>,
+// CHECK-LP64:         store [[TY]]* %self, [[TY]]** [[SELF_ADDR]]
+// CHECK-LP64:         [[T0:%.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>* [[BLOCK]], i32 0, i32 5
+// CHECK-LP64:         [[BC:%.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>* [[BLOCK]], i32 0, i32 5
+// CHECK-LP64:         [[T1:%.*]] = load [[TY]]*, [[TY]]** [[SELF_ADDR]]
+// CHECK-LP64:         [[T2:%.*]] = bitcast [[TY]]* [[T1]] to i8*
+// CHECK-LP64:         [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]])
+// CHECK-LP64:         [[T4:%.*]] = bitcast i8* [[T3]] to [[TY]]*
+// CHECK-LP64:         store [[TY]]* [[T4]], [[TY]]** [[BC]]
+
+// CHECK-LP64:         [[T5:%.*]] = bitcast [[TY]]** [[T0]] to i8**
+// CHECK-LP64:         call void @objc_storeStrong(i8** [[T5]], i8* null)
+// CHECK-LP64:         switch i32 {{%.*}}, label %unreachable [
+// CHECK-LP64-NEXT:      i32 0, label %[[CLEANUP_CONT:.*]]
+// CHECK-LP64-NEXT:      i32 2, label %[[FORCOLL_END:.*]]
+// CHECK-LP64-NEXT:    ]
+
+// CHECK-LP64:       {{^}}[[CLEANUP_CONT]]:
+// CHECK-LP64-NEXT:    br label %[[FORCOLL_END]]
+
+// CHECK-LP64:       {{^}}[[FORCOLL_END]]:
+// CHECK-LP64-NEXT:    ret void
+
+
 // CHECK-LP64: attributes [[NUW]] = { nounwind }
Index: lib/CodeGen/CGObjC.cpp
===================================================================
--- lib/CodeGen/CGObjC.cpp
+++ lib/CodeGen/CGObjC.cpp
@@ -1727,7 +1727,8 @@
 
   // Leave the cleanup we entered in ARC.
   if (getLangOpts().ObjCAutoRefCount)
-    PopCleanupBlock();
+    while (LoopEnd.getScopeDepth().strictlyEncloses(EHStack.stable_begin()))
+      PopCleanupBlock();
 
   EmitBlock(LoopEnd.getBlock());
 }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D18618.52106.patch
Type: text/x-patch
Size: 2939 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160330/9a01e474/attachment.bin>


More information about the cfe-commits mailing list