forked from OSchip/llvm-project
[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 llvm-svn: 266147
This commit is contained in:
parent
16a7d637dd
commit
2d3690bc98
|
@ -1485,6 +1485,8 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
|
|||
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::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
|
|||
if (DI)
|
||||
DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd());
|
||||
|
||||
// Leave the cleanup we entered in ARC.
|
||||
if (getLangOpts().ObjCAutoRefCount)
|
||||
PopCleanupBlock();
|
||||
|
||||
ForScope.ForceCleanup();
|
||||
EmitBlock(LoopEnd.getBlock());
|
||||
}
|
||||
|
||||
|
|
|
@ -170,4 +170,55 @@ void test3(NSArray *array) {
|
|||
// CHECK-LP64-NEXT: br label [[L]]
|
||||
}
|
||||
|
||||
@interface NSObject @end
|
||||
|
||||
@interface I1 : NSObject
|
||||
- (NSArray *) foo1:(void (^)(void))block;
|
||||
- (void) foo2;
|
||||
@end
|
||||
|
||||
NSArray *array4;
|
||||
|
||||
@implementation I1 : NSObject
|
||||
- (NSArray *) foo1:(void (^)(void))block {
|
||||
block();
|
||||
return array4;
|
||||
}
|
||||
|
||||
- (void) foo2 {
|
||||
for (id x in [self foo1:^{ use(self); }]) {
|
||||
use(x);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@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 }
|
||||
|
|
Loading…
Reference in New Issue