Skip to content

Commit 335cec0

Browse files
authored
[cxx-interop][IRGen] Do not pass a foreign reference type to objc_retainAutoreleasedReturnValue (#73630)
If a foreign reference type has a custom retain function, emit a call to it instead of emitting a call to objc_retainAutoreleasedReturnValue. rdar://117353222
1 parent a30b014 commit 335cec0

File tree

4 files changed

+59
-3
lines changed

4 files changed

+59
-3
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <optional>
3939

4040
#include "CallEmission.h"
41+
#include "ClassTypeInfo.h"
4142
#include "EntryPointArgumentEmission.h"
4243
#include "Explosion.h"
4344
#include "GenCall.h"
@@ -2612,9 +2613,16 @@ class SyncCallEmission final : public CallEmission {
26122613
if (fnConv.getNumDirectSILResults() == 1
26132614
&& (fnConv.getDirectSILResults().begin()->getConvention()
26142615
== ResultConvention::Autoreleased)) {
2615-
if (IGF.IGM.Context.LangOpts.EnableObjCInterop)
2616-
result = emitObjCRetainAutoreleasedReturnValue(IGF, result);
2617-
else
2616+
if (IGF.IGM.Context.LangOpts.EnableObjCInterop) {
2617+
auto ty = fnConv.getSILResultType(IGF.IGM.getMaximalTypeExpansionContext());
2618+
auto *classTypeInfo = dyn_cast<ClassTypeInfo>(&IGF.IGM.getTypeInfo(ty));
2619+
if (classTypeInfo && classTypeInfo->getReferenceCounting() == ReferenceCounting::Custom) {
2620+
Explosion e(result);
2621+
classTypeInfo->strongCustomRetain(IGF, e, true);
2622+
} else {
2623+
result = emitObjCRetainAutoreleasedReturnValue(IGF, result);
2624+
}
2625+
} else
26182626
IGF.emitNativeStrongRetain(result, IGF.getDefaultAtomicity());
26192627
}
26202628

test/Interop/Cxx/foreign-reference/Inputs/module.modulemap

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ module ReferenceCounted {
2828
requires cplusplus
2929
}
3030

31+
module ReferenceCountedObjCProperty {
32+
header "reference-counted-objc-property.h"
33+
requires cplusplus
34+
export *
35+
}
36+
3137
module MemberLayout {
3238
header "member-layout.h"
3339
requires cplusplus
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#ifndef REFERENCE_COUNTED_OBJC_PROPERTY_H
2+
#define REFERENCE_COUNTED_OBJC_PROPERTY_H
3+
4+
#include "reference-counted.h"
5+
6+
SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
7+
8+
@interface C0
9+
@property (nonnull, readonly) NS::LocalCount *lc;
10+
- (instancetype)init;
11+
@end
12+
13+
SWIFT_END_NULLABILITY_ANNOTATIONS
14+
15+
#endif // REFERENCE_COUNTED_OBJC_PROPERTY_H
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %target-swift-emit-irgen %s -I %S/Inputs -cxx-interoperability-mode=default -Xcc -fno-exceptions -Xcc -fno-objc-exceptions | %FileCheck %s
2+
3+
// REQUIRES: objc_interop
4+
5+
import ReferenceCountedObjCProperty
6+
7+
// CHECK: define swiftcc void @"$s4main10testGetteryyF"()
8+
// CHECK: alloca ptr, align 8
9+
// CHECK: %[[LC:.*]] = alloca ptr, align 8
10+
// CHECK: %[[V4:.*]] = load ptr, ptr @"\01L_selector(lc)", align 8
11+
// CHECK: %[[V5:.*]] = call ptr @objc_msgSend(ptr %{{.*}}, ptr %[[V4]])
12+
// CHECK: %[[V6:.*]] = icmp ne ptr %[[V5]], null
13+
// CHECK: br i1 %[[V6]], label %[[LIFETIME_NONNULL_VALUE:.*]], label %[[LIFETIME_CONT:.*]]
14+
15+
// CHECK: [[LIFETIME_NONNULL_VALUE]]:
16+
// CHECK-NEXT: call void @_Z8LCRetainPN2NS10LocalCountE(ptr %[[V5]])
17+
// CHECK-NEXT: br label %[[LIFETIME_CONT]]
18+
19+
// CHECK: [[LIFETIME_CONT]]:
20+
// CHECK: store ptr %[[V5]], ptr %[[LC]], align 8
21+
// CHECK: %[[TODESTROY:.*]] = load ptr, ptr %[[LC]], align 8
22+
// CHECK: call void @_Z9LCReleasePN2NS10LocalCountE(ptr %[[TODESTROY]])
23+
24+
public func testGetter() {
25+
var c0 = C0()
26+
var lc = c0.lc
27+
}

0 commit comments

Comments
 (0)