From: John McCall Date: Thu, 14 Dec 2017 18:21:14 +0000 (+0000) Subject: In an ARC lambda-to-block conversion thunk, reclaim the return value of X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a66f080af76f4d928571c4a61ce5ce88c0f41b49;p=clang In an ARC lambda-to-block conversion thunk, reclaim the return value of the lambda so that we don't over-release it. Patch by Dan Zimmerman! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@320721 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 9bbdc98f1f..a6915071ec 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -2777,9 +2777,12 @@ void CodeGenFunction::EmitForwardingCallToLambda( RValue RV = EmitCall(calleeFnInfo, callee, returnSlot, callArgs); // If necessary, copy the returned value into the slot. - if (!resultType->isVoidType() && returnSlot.isNull()) + if (!resultType->isVoidType() && returnSlot.isNull()) { + if (getLangOpts().ObjCAutoRefCount && resultType->isObjCRetainableType()) { + RV = RValue::get(EmitARCRetainAutoreleasedReturnValue(RV.getScalarVal())); + } EmitReturnOfRValue(RV, resultType); - else + } else EmitBranchThroughCleanup(ReturnBlock); } diff --git a/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm b/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm new file mode 100644 index 0000000000..35abe19183 --- /dev/null +++ b/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -emit-llvm -disable-llvm-passes -O3 -fblocks -fobjc-arc -fobjc-runtime-has-weak -std=c++11 -o - %s | FileCheck %s + +void test0(id x) { + extern void test0_helper(id (^)(void)); + test0_helper([=]() { return x; }); + // CHECK-LABEL: define internal i8* @___Z5test0P11objc_object_block_invoke + // CHECK: [[T0:%.*]] = call i8* @"_ZZ5test0P11objc_objectENK3$_0clEv" + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: [[T2:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T1]]) + // CHECK-NEXT: ret i8* [[T2]] +} + +id test1_rv; + +void test1() { + extern void test1_helper(id (*)(void)); + test1_helper([](){ return test1_rv; }); + // CHECK-LABEL: define internal i8* @"_ZZ5test1vEN3$_18__invokeEv" + // CHECK: [[T0:%.*]] = call i8* @"_ZZ5test1vENK3$_1clEv" + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: [[T2:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T1]]) + // CHECK-NEXT: ret i8* [[T2]] +}