Skip to content

Commit 834fe9a

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 38a528c commit 834fe9a

File tree

8 files changed

+68
-28
lines changed

8 files changed

+68
-28
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 & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2225,7 +2225,8 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) {
22252225
foreignFormalType,
22262226
foreignLoweredTy);
22272227
// Handle C pointer arguments imported as indirect `self` arguments.
2228-
if (foreignParam.getConvention() == ParameterConvention::Indirect_In) {
2228+
if (foreignParam.getConvention() == ParameterConvention::Indirect_In ||
2229+
foreignParam.getConvention() == ParameterConvention::Indirect_In_Guaranteed) {
22292230
auto temp = emitTemporaryAllocation(fd, bridged.getType());
22302231
bridged.forwardInto(*this, fd, temp);
22312232
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: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
3+
@interface NSObject
4+
@end
5+
6+
struct PrimitiveWrapperT { int value; };
7+
8+
struct CxxEmbeddedT {
9+
PrimitiveWrapperT V;
10+
CxxEmbeddedT() = delete;
11+
CxxEmbeddedT(const PrimitiveWrapperT &V) noexcept : V(V) {}
12+
};
13+
14+
15+
@interface ObjCSwiftBridgeT : NSObject
16+
- (instancetype)init __attribute__((unavailable));
17+
- (instancetype)initWithEmbedded:(const CxxEmbeddedT &)embedded __attribute__((objc_designated_initializer));
18+
@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 primativeWrapperInst = PrimitiveWrapperT(value: 42)
7+
var cxxEmeddedInst = CxxEmbeddedT(primativeWrapperInst)
8+
var objcSwiftBridgeInst = ObjCSwiftBridgeT(embedded: cxxEmeddedInst)
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 @_ZN12CxxEmbeddedTC1ERK17PrimitiveWrapperT : $@convention(c) (PrimitiveWrapperT) -> @out CxxEmbeddedT
12+
// CHECK: {{%[0-9]+}} = apply {{%[0-9]+}}({{%[0-9]+}}, {{%[0-9]+}}) : $@convention(c) (PrimitiveWrapperT) -> @out CxxEmbeddedT
13+
// CHECK: alloc_global @$s4main19objcSwiftBridgeInstSo09ObjCSwiftD1TCSgvp
14+
// CHECK: {{%[0-9]+}} = global_addr @$s4main19objcSwiftBridgeInstSo09ObjCSwiftD1TCSgvp : $*Optional<ObjCSwiftBridgeT>
15+
// CHECK: {{%[0-9]+}} = load {{%[0-9]+}} : $*CxxEmbeddedT
16+
// CHECK: {{%[0-9]+}} = alloc_ref [objc] $ObjCSwiftBridgeT
17+
// CHECK: {{%[0-9]+}} = alloc_stack $CxxEmbeddedT
18+
// CHECK: store {{%[0-9]+}} to {{%[0-9]+}} : $*CxxEmbeddedT
19+
// CHECK: {{%[0-9]+}} = objc_method {{%[0-9]+}} : $ObjCSwiftBridgeT, #ObjCSwiftBridgeT.init!initializer.foreign : (ObjCSwiftBridgeT.Type) -> (CxxEmbeddedT) -> ObjCSwiftBridgeT?, $@convention(objc_method) (@in_guaranteed CxxEmbeddedT, @owned ObjCSwiftBridgeT) -> @owned Optional<ObjCSwiftBridgeT>
20+
// CHECK: {{%[0-9]+}} = apply {{%[0-9]+}}({{%[0-9]+}}, {{%[0-9]+}}) : $@convention(objc_method) (@in_guaranteed CxxEmbeddedT, @owned ObjCSwiftBridgeT) -> @owned Optional<ObjCSwiftBridgeT>
21+
// CHECK: dealloc_stack {{%[0-9]+}} : $*CxxEmbeddedT

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)