Author: Akira Hatanaka Date: 2021-04-29T16:04:30-07:00 New Revision: 2e1d9ebd46b826b06f0a5882e992e3d84335f268
URL: https://github.com/llvm/llvm-project/commit/2e1d9ebd46b826b06f0a5882e992e3d84335f268 DIFF: https://github.com/llvm/llvm-project/commit/2e1d9ebd46b826b06f0a5882e992e3d84335f268.diff LOG: [ObjC][ARC] Don't enter the cleanup scope if the initializer expression isn't an ExprWithCleanups This patch fixes a bug where a temporary ObjC pointer is released before the end of the full expression. This fixes PR50043. rdar://77030453 Differential Revision: https://reviews.llvm.org/D101502 Added: Modified: clang/lib/CodeGen/CGDecl.cpp clang/test/CodeGenObjCXX/arc-blocks.mm clang/test/CodeGenObjCXX/arc.mm Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 5bab185976886..7b89f5dfc9ba5 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -772,9 +772,10 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D, // If we're emitting a value with lifetime, we have to do the // initialization *before* we leave the cleanup scopes. - if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(init)) - init = EWC->getSubExpr(); - CodeGenFunction::RunCleanupsScope Scope(*this); + if (auto *EWC = dyn_cast<ExprWithCleanups>(init)) { + CodeGenFunction::RunCleanupsScope Scope(*this); + return EmitScalarInit(EWC->getSubExpr(), D, lvalue, capturedByInit); + } // We have to maintain the illusion that the variable is // zero-initialized. If the variable might be accessed in its diff --git a/clang/test/CodeGenObjCXX/arc-blocks.mm b/clang/test/CodeGenObjCXX/arc-blocks.mm index f0d3b8eefa535..2b06bf0fffebe 100644 --- a/clang/test/CodeGenObjCXX/arc-blocks.mm +++ b/clang/test/CodeGenObjCXX/arc-blocks.mm @@ -204,10 +204,10 @@ void foo1() { // Test that calls to @llvm.objc.retainBlock aren't emitted in some cases. -namespace test_block_retain { - typedef void (^BlockTy)(); +typedef void (^BlockTy)(); +void foo1(id); - void foo1(id); +namespace test_block_retain { // CHECK-LABEL: define{{.*}} void @_ZN17test_block_retain14initializationEP11objc_object( // CHECK-NOT: @llvm.objc.retainBlock( @@ -321,3 +321,24 @@ void assignmentObjCPtr(id a) { ((BlockTy)b1)(); } } + +// Check that the block capture is released after the full expression. + +// CHECK-LABEL: define void @_ZN13test_rval_ref4testEP11objc_object( +// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8 +// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK]], i32 0, i32 5 +// CHECK: %[[V1:.*]] = call i8* @llvm.objc.retain( +// CHECK: store i8* %[[V1]], i8** %[[BLOCK_CAPTURED]], align 8 +// CHECK: invoke void @_ZN13test_rval_ref17callTemplateBlockEOU15__autoreleasingU13block_pointerFvvE( + +// CHECK: call void @llvm.objc.storeStrong(i8** %[[BLOCK_CAPTURED]], i8* null) + +namespace test_rval_ref { + void callTemplateBlock(BlockTy &&func); + + void test(id str) { + return callTemplateBlock(^void() { + foo1(str); + }); + } +} diff --git a/clang/test/CodeGenObjCXX/arc.mm b/clang/test/CodeGenObjCXX/arc.mm index 5b45cae1f8cae..bb576b051161d 100644 --- a/clang/test/CodeGenObjCXX/arc.mm +++ b/clang/test/CodeGenObjCXX/arc.mm @@ -334,3 +334,17 @@ void test41(__weak id &&x) { // CHECK: [[T0:%.*]] = load i8**, i8*** [[X]] // CHECK-NEXT: call void @llvm.objc.moveWeak(i8** [[Y]], i8** [[T0]]) // CHECK-NEXT: call void @llvm.objc.destroyWeak(i8** [[Y]]) + +void test42() { + __attribute__((ns_returns_retained)) id test42_0(); + id test42_1(id); + void test42_2(id &&); + test42_2(test42_1(test42_0())); +} + +// Check that the pointer returned by test42_0 is released after the full expression. + +// CHECK-LABEL: define void @_Z6test42v() +// CHECK: %[[CALL:.*]] = call i8* @_Z8test42_0v() +// CHECK: call void @_Z8test42_2OU15__autoreleasingP11objc_object( +// CHECK: call void @llvm.objc.release(i8* %[[CALL]]) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits