Skip to content

Commit 84a69c4

Browse files
committed
[C++-Interop] Import const &T function parameters as @in_guaranteed
When passing value types as a const-ref to a C++ API, ensure that the caller is tasked with handling the lifetime of the instance passed in.
1 parent 9ab055a commit 84a69c4

File tree

8 files changed

+65
-29
lines changed

8 files changed

+65
-29
lines changed

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2702,6 +2702,8 @@ static bool isCFTypedef(const TypeLowering &tl, clang::QualType type) {
27022702
static ParameterConvention getIndirectCParameterConvention(clang::QualType type) {
27032703
// Non-trivial C++ types would be Indirect_Inout (at least in Itanium).
27042704
// A trivial const * parameter in C should be considered @in.
2705+
if (type->isReferenceType() && type->getPointeeType().isConstQualified())
2706+
return ParameterConvention::Indirect_In_Guaranteed;
27052707
return ParameterConvention::Indirect_In;
27062708
}
27072709

lib/SILGen/SILGenBridging.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2224,8 +2224,8 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) {
22242224
auto bridged = emitNativeToBridgedValue(fd, param, nativeFormalType,
22252225
foreignFormalType,
22262226
foreignLoweredTy);
2227-
// Handle C pointer arguments imported as indirect `self` arguments.
2228-
if (foreignParam.getConvention() == ParameterConvention::Indirect_In) {
2227+
if (foreignParam.getConvention() == ParameterConvention::Indirect_In ||
2228+
foreignParam.getConvention() == ParameterConvention::Indirect_In_Guaranteed) {
22292229
auto temp = emitTemporaryAllocation(fd, bridged.getType());
22302230
bridged.forwardInto(*this, fd, temp);
22312231
bridged = emitManagedBufferWithCleanup(temp);

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,9 @@ module ConstRefParameter {
1313
requires objc
1414
requires cplusplus
1515
}
16+
17+
module ConstRefCxxObjCCtorInitParameter {
18+
header "reference-silgen-cxx-objc-ctors+init.h"
19+
requires objc
20+
requires cplusplus
21+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
3+
@interface NSObject
4+
@end
5+
6+
struct IntWrapper {
7+
int value;
8+
IntWrapper() = delete;
9+
IntWrapper(const int &value): value(value) {};
10+
};
11+
12+
@interface ObjCSwiftBridge : NSObject
13+
- (instancetype)init __attribute__((unavailable));
14+
- (instancetype)initWithEmbedded:(const IntWrapper &)embedded __attribute__((objc_designated_initializer));
15+
@end

test/Interop/Cxx/reference/const-ref-parameter.swift

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,42 +36,34 @@ func testFunction() {
3636

3737
// RUN: %target-swift-frontend -c -enable-experimental-cxx-interop -enable-objc-interop -I %S/Inputs %s -emit-silgen -o - | %FileCheck %s
3838

39-
// COM: FIXME: should it be @in_guaranteed OptionsStruct? https://github.com/apple/swift/issues/60601
4039
// CHECK: [[FN1:%[0-9]+]] = function_ref @$sSo19OptionsConsumerObjCC7optionsABSo0A6StructV_tcfC : $@convention(method) (OptionsStruct, @thick OptionsConsumerObjC.Type) -> @owned OptionsConsumerObjC
4140
// CHECK-NEXT: apply [[FN1]]
4241
// CHECK-SAME: : $@convention(method) (OptionsStruct, @thick OptionsConsumerObjC.Type) -> @owned OptionsConsumerObjC
4342

44-
// COM: FIXME: should it be @in_guaranteed OptionStruct? https://github.com/apple/swift/issues/60601
45-
// CHECK: [[FN2:%[0-9]+]] = objc_method {{%[0-9]+}} : $OptionsConsumerObjC, #OptionsConsumerObjC.doOtherThing!foreign : (OptionsConsumerObjC) -> (OptionsStruct) -> Float, $@convention(objc_method) (@in OptionsStruct, OptionsConsumerObjC) -> Float
43+
// CHECK: [[FN2:%[0-9]+]] = objc_method {{%[0-9]+}} : $OptionsConsumerObjC, #OptionsConsumerObjC.doOtherThing!foreign : (OptionsConsumerObjC) -> (OptionsStruct) -> Float, $@convention(objc_method) (@in_guaranteed OptionsStruct, OptionsConsumerObjC) -> Float
4644
// CHECK-NEXT: apply [[FN2]]
47-
// CHECK-SAME: : $@convention(objc_method) (@in OptionsStruct, OptionsConsumerObjC) -> Float
45+
// CHECK-SAME: : $@convention(objc_method) (@in_guaranteed OptionsStruct, OptionsConsumerObjC) -> Float
4846

49-
// COM: FIXME: should it be @in_guaranteed OptionStruct? https://github.com/apple/swift/issues/60601
50-
// CHECK: [[FN3:%[0-9]+]] = objc_method {{%[0-9]+}} : $@objc_metatype OptionsConsumerObjC.Type, #OptionsConsumerObjC.consumer!foreign : (OptionsConsumerObjC.Type) -> (OptionsStruct) -> @dynamic_self OptionsConsumerObjC, $@convention(objc_method) (@in OptionsStruct, @objc_metatype OptionsConsumerObjC.Type) -> @autoreleased OptionsConsumerObjC
47+
// CHECK: [[FN3:%[0-9]+]] = objc_method {{%[0-9]+}} : $@objc_metatype OptionsConsumerObjC.Type, #OptionsConsumerObjC.consumer!foreign : (OptionsConsumerObjC.Type) -> (OptionsStruct) -> @dynamic_self OptionsConsumerObjC, $@convention(objc_method) (@in_guaranteed OptionsStruct, @objc_metatype OptionsConsumerObjC.Type) -> @autoreleased OptionsConsumerObjC
5148
// CHECK-NEXT: apply [[FN3]]
52-
// CHECK-SAME: : $@convention(objc_method) (@in OptionsStruct, @objc_metatype OptionsConsumerObjC.Type) -> @autoreleased OptionsConsumerObjC
49+
// CHECK-SAME: : $@convention(objc_method) (@in_guaranteed OptionsStruct, @objc_metatype OptionsConsumerObjC.Type) -> @autoreleased OptionsConsumerObjC
5350

54-
// COM: FIXME: should it be @in_guaranteed OptionStruct? https://github.com/apple/swift/issues/60601
55-
// CHECK: [[FN4:%[0-9]+]] = objc_method {{%[0-9]+}} : $@objc_metatype OptionsConsumerObjC.Type, #OptionsConsumerObjC.doThing!foreign : (OptionsConsumerObjC.Type) -> (OptionsStruct) -> Int32, $@convention(objc_method) (@in OptionsStruct, @objc_metatype OptionsConsumerObjC.Type) -> Int32
51+
// CHECK: [[FN4:%[0-9]+]] = objc_method {{%[0-9]+}} : $@objc_metatype OptionsConsumerObjC.Type, #OptionsConsumerObjC.doThing!foreign : (OptionsConsumerObjC.Type) -> (OptionsStruct) -> Int32, $@convention(objc_method) (@in_guaranteed OptionsStruct, @objc_metatype OptionsConsumerObjC.Type) -> Int32
5652
// CHECK-NEXT: apply [[FN4]]
57-
// CHECK-SAME: : $@convention(objc_method) (@in OptionsStruct, @objc_metatype OptionsConsumerObjC.Type) -> Int32
53+
// CHECK-SAME: : $@convention(objc_method) (@in_guaranteed OptionsStruct, @objc_metatype OptionsConsumerObjC.Type) -> Int32
5854

59-
// COM: FIXME: should it be @in_guaranteed OptionStruct? https://github.com/apple/swift/issues/60601
6055
// CHECK: [[FN5:%[0-9]+]] = function_ref @_ZN18OptionsConsumerCxxC1ERK13OptionsStruct : $@convention(c) (OptionsStruct) -> @out OptionsConsumerCxx
6156
// CHECK-NEXT: apply [[FN5]]
6257
// CHECK-SAME: : $@convention(c) (OptionsStruct) -> @out OptionsConsumerCxx
6358

64-
// COM: FIXME: should it be @in_guaranteed OptionStruct? https://github.com/apple/swift/issues/60601
65-
// CHECK: [[FN6:%[0-9]+]] = function_ref @_ZN18OptionsConsumerCxx12doOtherThingERK13OptionsStruct : $@convention(cxx_method) (@in OptionsStruct, @inout OptionsConsumerCxx) -> Float
59+
// CHECK: [[FN6:%[0-9]+]] = function_ref @_ZN18OptionsConsumerCxx12doOtherThingERK13OptionsStruct : $@convention(cxx_method) (@in_guaranteed OptionsStruct, @inout OptionsConsumerCxx) -> Float
6660
// CHECK-NEXT: apply [[FN6]]
67-
// CHECK-SAME: : $@convention(cxx_method) (@in OptionsStruct, @inout OptionsConsumerCxx) -> Float
61+
// CHECK-SAME: : $@convention(cxx_method) (@in_guaranteed OptionsStruct, @inout OptionsConsumerCxx) -> Float
6862

69-
// COM: FIXME: should it be @in_guaranteed OptionStruct? https://github.com/apple/swift/issues/60601
70-
// CHECK: [[FN6:%[0-9]+]] = function_ref @_ZN18OptionsConsumerCxx5buildERK13OptionsStruct : $@convention(c) (@in OptionsStruct) -> OptionsConsumerCxx
63+
// CHECK: [[FN6:%[0-9]+]] = function_ref @_ZN18OptionsConsumerCxx5buildERK13OptionsStruct : $@convention(c) (@in_guaranteed OptionsStruct) -> OptionsConsumerCxx
7164
// CHECK-NEXT: apply [[FN6]]
72-
// CHECK-SAME: : $@convention(c) (@in OptionsStruct) -> OptionsConsumerCxx
65+
// CHECK-SAME: : $@convention(c) (@in_guaranteed OptionsStruct) -> OptionsConsumerCxx
7366

74-
// COM: FIXME: should it be @in_guaranteed OptionStruct? https://github.com/apple/swift/issues/60601
75-
// CHECK: [[FN7:%[0-9]+]] = function_ref @_ZN18OptionsConsumerCxx7doThingERK13OptionsStruct : $@convention(c) (@in OptionsStruct) -> Int32
67+
// CHECK: [[FN7:%[0-9]+]] = function_ref @_ZN18OptionsConsumerCxx7doThingERK13OptionsStruct : $@convention(c) (@in_guaranteed OptionsStruct) -> Int32
7668
// CHECK-NEXT: apply [[FN7]]
77-
// CHECK-SAME: : $@convention(c) (@in OptionsStruct) -> Int32
69+
// CHECK-SAME: : $@convention(c) (@in_guaranteed OptionsStruct) -> Int32
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// REQUIRES: objc_interop
2+
// RUN: %target-swift-emit-sil -I %S/Inputs -enable-experimental-cxx-interop -Xcc -std=c++17 -Ounchecked %s | %FileCheck %s
3+
4+
import ConstRefCxxObjCCtorInitParameter
5+
6+
var a: Int32 = 32
7+
var b = IntWrapper(a)
8+
var c = ObjCSwiftBridge(embedded: b)
9+
10+
// FIXME: the const-ref C++ Consructor here is not getting an @in_guaranteed or even an @in convention here.
11+
// CHECK: {{%[0-9]+}} = function_ref @_ZN10IntWrapperC1ERKi : $@convention(c) (Int32) -> @out IntWrapper
12+
// CHECK: {{%[0-9]+}} = apply {{%[0-9]+}}({{%[0-9]+}}, {{%[0-9]+}}) : $@convention(c) (Int32) -> @out IntWrapper
13+
// CHECK: alloc_global @$s4main1cSo15ObjCSwiftBridgeCSgvp
14+
// CHECK: {{%[0-9]+}} = global_addr @$s4main1cSo15ObjCSwiftBridgeCSgvp : $*Optional<ObjCSwiftBridge>
15+
// CHECK: {{%[0-9]+}} = load {{%[0-9]+}} : $*IntWrapper
16+
// CHECK: {{%[0-9]+}} = alloc_ref [objc] $ObjCSwiftBridge
17+
// CHECK: {{%[0-9]+}} = alloc_stack $IntWrapper
18+
// CHECK: store {{%[0-9]+}} to {{%[0-9]+}} : $*IntWrapper
19+
// CHECK: {{%[0-9]+}} = objc_method {{%[0-9]+}} : $ObjCSwiftBridge, #ObjCSwiftBridge.init!initializer.foreign : (ObjCSwiftBridge.Type) -> (IntWrapper) -> ObjCSwiftBridge?, $@convention(objc_method) (@in_guaranteed IntWrapper, @owned ObjCSwiftBridge) -> @owned Optional<ObjCSwiftBridge>
20+
// CHECK: {{%[0-9]+}} = apply {{%[0-9]+}}({{%[0-9]+}}, {{%[0-9]+}}) : $@convention(objc_method) (@in_guaranteed IntWrapper, @owned ObjCSwiftBridge) -> @owned Optional<ObjCSwiftBridge>
21+
// CHECK: dealloc_stack {{%[0-9]+}} : $*IntWrapper

test/Interop/Cxx/reference/reference-silgen.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ func setCxxConstRef() {
4949
}
5050

5151
// CHECK: sil hidden @$s4main14setCxxConstRefyyF : $@convention(thin) () -> ()
52-
// CHECK: [[REF:%.*]] = function_ref @{{_Z20setConstStaticIntRefRKi|\?setConstStaticIntRef@@YAXAEBH@Z}} : $@convention(c) (@in Int32) -> ()
53-
// CHECK: apply [[REF]](%{{[0-9]+}}) : $@convention(c) (@in Int32) -> ()
52+
// CHECK: [[REF:%.*]] = function_ref @{{_Z20setConstStaticIntRefRKi|\?setConstStaticIntRef@@YAXAEBH@Z}} : $@convention(c) (@in_guaranteed Int32) -> ()
53+
// CHECK: apply [[REF]](%{{[0-9]+}}) : $@convention(c) (@in_guaranteed Int32) -> ()
5454

5555
func setCxxRvalueRef() {
5656
var val: CInt = 21
@@ -67,5 +67,5 @@ func setCxxConstRvalueRef() {
6767
}
6868

6969
// CHECK: sil hidden @$s4main20setCxxConstRvalueRefyyF : $@convention(thin) () -> ()
70-
// CHECK: [[REF:%.*]] = function_ref @{{_Z26setConstStaticIntRvalueRefOKi|\?setConstStaticIntRvalueRef@@YAX\$\$QEBH@Z}} : $@convention(c) (@in Int32) -> ()
71-
// CHECK: apply [[REF]](%{{[0-9]+}}) : $@convention(c) (@in Int32) -> ()
70+
// CHECK: [[REF:%.*]] = function_ref @{{_Z26setConstStaticIntRvalueRefOKi|\?setConstStaticIntRvalueRef@@YAX\$\$QEBH@Z}} : $@convention(c) (@in_guaranteed Int32) -> ()
71+
// CHECK: apply [[REF]](%{{[0-9]+}}) : $@convention(c) (@in_guaranteed Int32) -> ()

test/Interop/Cxx/templates/member-templates-silgen.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ import MemberTemplates
1717
// CHECK: [[ADD_ALL:%.*]] = function_ref @_ZN18HasMemberTemplates6addAllIiiEEiiT_T0_ : $@convention(cxx_method) (Int32, Int32, Int32, @inout HasMemberTemplates) -> Int32
1818
// CHECK: apply [[ADD_ALL]]({{.*}}) : $@convention(cxx_method) (Int32, Int32, Int32, @inout HasMemberTemplates) -> Int32
1919

20-
// CHECK: [[DO_NOTHING:%.*]] = function_ref @_ZN18HasMemberTemplates17doNothingConstRefIiEEvRKT_ : $@convention(cxx_method) (@in Int32, @inout HasMemberTemplates) -> ()
21-
// CHECK: apply [[DO_NOTHING]]({{.*}}) : $@convention(cxx_method) (@in Int32, @inout HasMemberTemplates) -> ()
20+
// CHECK: [[DO_NOTHING:%.*]] = function_ref @_ZN18HasMemberTemplates17doNothingConstRefIiEEvRKT_ : $@convention(cxx_method) (@in_guaranteed Int32, @inout HasMemberTemplates) -> ()
21+
// CHECK: apply [[DO_NOTHING]]({{.*}}) : $@convention(cxx_method) (@in_guaranteed Int32, @inout HasMemberTemplates) -> ()
2222

2323
// CHECK-LABEL: end sil function '$s4main9basicTestyyF'
2424
func basicTest() {
@@ -36,7 +36,7 @@ func basicTest() {
3636

3737
// CHECK-LABEL: sil [clang HasMemberTemplates.addAll] @_ZN18HasMemberTemplates6addAllIiiEEiiT_T0_ : $@convention(cxx_method) (Int32, Int32, Int32, @inout HasMemberTemplates) -> Int32
3838

39-
// CHECK-LABEL: sil [clang HasMemberTemplates.doNothingConstRef] @_ZN18HasMemberTemplates17doNothingConstRefIiEEvRKT_ : $@convention(cxx_method) (@in Int32, @inout HasMemberTemplates) -> ()
39+
// CHECK-LABEL: sil [clang HasMemberTemplates.doNothingConstRef] @_ZN18HasMemberTemplates17doNothingConstRefIiEEvRKT_ : $@convention(cxx_method) (@in_guaranteed Int32, @inout HasMemberTemplates) -> ()
4040

4141
// CHECK-LABEL: sil hidden @$s4main12testSetValueyyF : $@convention(thin) () -> ()
4242

0 commit comments

Comments
 (0)