Skip to content

Commit d0c35cf

Browse files
committed
[IRGen] Don't call objc_retainAutoreleasedReturnValue() without interop.
When ObjC interop is not enabled, we shouldn't be emitting calls to `objc_retainAutoreleasedReturnValue()` as that function might not exist. Call `swift_retain()` instead, to balance the `swift_release()` of the returned value. Fixes #47846, #45359. rdar://23335318
1 parent f1adf99 commit d0c35cf

File tree

5 files changed

+41
-4
lines changed

5 files changed

+41
-4
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2605,7 +2605,10 @@ class SyncCallEmission final : public CallEmission {
26052605
if (fnConv.getNumDirectSILResults() == 1
26062606
&& (fnConv.getDirectSILResults().begin()->getConvention()
26072607
== ResultConvention::Autoreleased)) {
2608-
result = emitObjCRetainAutoreleasedReturnValue(IGF, result);
2608+
if (IGF.IGM.Context.LangOpts.EnableObjCInterop)
2609+
result = emitObjCRetainAutoreleasedReturnValue(IGF, result);
2610+
else
2611+
IGF.emitNativeStrongRetain(result, IGF.getDefaultAtomicity());
26092612
}
26102613

26112614
auto origFnType = getCallee().getOrigFunctionType();

test/IRGen/Inputs/CFBridgedType.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#define CF_BRIDGED_TYPE(T) __attribute__((objc_bridge(T)))
2+
3+
typedef struct CF_BRIDGED_TYPE(id) __CFBridgedType *CFBridgedTypeRef;
4+
5+
__attribute__((cf_audited_transfer))
6+
CFBridgedTypeRef returnsACFBridgedType(void);

test/IRGen/Inputs/module.modulemap

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,9 @@ module SynthesizedProtocol {
3333
}
3434

3535
module PointerAuth {
36-
header "ptrauth_field_fptr_import.h"
37-
}
36+
header "ptrauth_field_fptr_import.h"
37+
}
38+
39+
module CFBridgedType {
40+
header "CFBridgedType.h"
41+
}

test/IRGen/autorelease.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) %s -emit-ir | %FileCheck -check-prefix CHECK -check-prefix CHECK-%target-ptrsize -check-prefix %target-cpu -DINT=i%target-ptrsize %s
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) %s -enable-objc-interop -emit-ir | %FileCheck -check-prefix CHECK -check-prefix CHECK-%target-ptrsize -check-prefix %target-cpu -DINT=i%target-ptrsize %s
22

33
// rdar://16565958
44

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %target-swift-frontend -module-name cf_objc_retainAutoreleasedReturnValue -I %S/Inputs %s -enable-objc-interop -emit-ir | %FileCheck %s
2+
// RUN: %target-swift-frontend -module-name cf_objc_retainAutoreleasedReturnValue -I %S/Inputs %s -emit-ir | %FileCheck %s --check-prefix=NO_INTEROP
3+
4+
import CFBridgedType
5+
6+
@inline(never)
7+
public func foo() {
8+
let _ = returnsACFBridgedType()
9+
}
10+
11+
// With interop enabled, this should use objc_retainAutoreleasedReturnValue()
12+
13+
// CHECK-LABEL: define protected swiftcc void @"$s37cf_objc_retainAutoreleasedReturnValue3fooyyF"()
14+
// CHECK: entry:
15+
// CHECK: %0 = call {{.*}}@returnsACFBridgedType()
16+
// CHECK: %1 = notail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %0)
17+
18+
// Without interop, it should call swift_retain() instead.
19+
20+
// NO_INTEROP-LABEL: define protected swiftcc void @"$s37cf_objc_retainAutoreleasedReturnValue3fooyyF"()
21+
// NO_INTEROP: entry:
22+
// NO_INTEROP: %0 = call {{.*}}@returnsACFBridgedType()
23+
// NO_INTEROP: %1 = call ptr @swift_retain(ptr returned %0)
24+

0 commit comments

Comments
 (0)