r266147 - [ObjC] Pop all cleanups created in EmitObjCForCollectionStmt before

Akira Hatanaka via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 12 16:10:58 PDT 2016


Author: ahatanak
Date: Tue Apr 12 18:10:58 2016
New Revision: 266147

URL: http://llvm.org/viewvc/llvm-project?rev=266147&view=rev
Log:
[ObjC] Pop all cleanups created in EmitObjCForCollectionStmt before
exiting the for-in loop.

This commit fixes a bug where EmitObjCForCollectionStmt didn'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;
}

Previously, the code in EmitObjCForCollectionStmt wouldn't pop the
cleanup for the captured self before exiting the loop, which caused
code-gen to generate an IR in which objc_release was called twice on
the captured self.

This commit fixes the bug by entering a RunCleanupsScope before the
loop condition is evaluated and forcing its cleanup before exiting the
loop.

rdar://problem/16865751

Differential Revision: http://reviews.llvm.org/D18618

Modified:
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/test/CodeGenObjC/arc-foreach.m

Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=266147&r1=266146&r2=266147&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Tue Apr 12 18:10:58 2016
@@ -1485,6 +1485,8 @@ void CodeGenFunction::EmitObjCForCollect
                                       ArrayType::Normal, 0);
   Address ItemsPtr = CreateMemTemp(ItemsTy, "items.ptr");
 
+  RunCleanupsScope ForScope(*this);
+
   // Emit the collection pointer.  In ARC, we do a retain.
   llvm::Value *Collection;
   if (getLangOpts().ObjCAutoRefCount) {
@@ -1725,10 +1727,7 @@ void CodeGenFunction::EmitObjCForCollect
   if (DI)
     DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd());
 
-  // Leave the cleanup we entered in ARC.
-  if (getLangOpts().ObjCAutoRefCount)
-    PopCleanupBlock();
-
+  ForScope.ForceCleanup();
   EmitBlock(LoopEnd.getBlock());
 }
 

Modified: cfe/trunk/test/CodeGenObjC/arc-foreach.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-foreach.m?rev=266147&r1=266146&r2=266147&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/arc-foreach.m (original)
+++ cfe/trunk/test/CodeGenObjC/arc-foreach.m Tue Apr 12 18:10:58 2016
@@ -170,4 +170,55 @@ void test3(NSArray *array) {
   // 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:       {{^|:}}[[UNREACHABLE]]
+// CHECK-LP64-NEXT:    unreachable
+
 // CHECK-LP64: attributes [[NUW]] = { nounwind }




More information about the cfe-commits mailing list