Skip to content

Commit 0db1457

Browse files
committed
[interop][SwiftToCxx] pass C++ value types into Swift correctly
1 parent b4d7a0c commit 0db1457

File tree

3 files changed

+91
-7
lines changed

3 files changed

+91
-7
lines changed

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,12 @@ class CFunctionSignatureTypePrinter
310310
ClangTypeHandler handler(decl->getClangDecl());
311311
if (!handler.isRepresentable())
312312
return ClangRepresentation::unsupported;
313+
if (typeUseKind == FunctionSignatureTypeUse::ParamType &&
314+
!isInOutParam)
315+
os << "const ";
313316
handler.printTypeName(os);
317+
if (typeUseKind == FunctionSignatureTypeUse::ParamType)
318+
os << '&';
314319
return ClangRepresentation::representable;
315320
}
316321

@@ -859,11 +864,22 @@ void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse(
859864
if (!directTypeEncoding.empty())
860865
os << cxx_synthesis::getCxxImplNamespaceName()
861866
<< "::swift_interop_passDirect_" << directTypeEncoding << '(';
862-
ClangValueTypePrinter(os, cPrologueOS, interopContext)
863-
.printParameterCxxToCUseScaffold(
864-
moduleContext,
865-
[&]() { printTypeImplTypeSpecifier(type, moduleContext); },
866-
namePrinter, isSelf);
867+
if (decl->hasClangNode()) {
868+
if (!directTypeEncoding.empty())
869+
os << "reinterpret_cast<const char *>(";
870+
os << "swift::" << cxx_synthesis::getCxxImplNamespaceName()
871+
<< "::getOpaquePointer(";
872+
namePrinter();
873+
os << ')';
874+
if (!directTypeEncoding.empty())
875+
os << ')';
876+
} else {
877+
ClangValueTypePrinter(os, cPrologueOS, interopContext)
878+
.printParameterCxxToCUseScaffold(
879+
moduleContext,
880+
[&]() { printTypeImplTypeSpecifier(type, moduleContext); },
881+
namePrinter, isSelf);
882+
}
867883
if (!directTypeEncoding.empty())
868884
os << ')';
869885
return;

test/Interop/CxxToSwiftToCxx/bridge-cxx-struct-back-to-cxx-execution.cpp

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ struct NonTrivialTemplate {
2828
inline NonTrivialTemplate(T x) : x(x) {
2929
puts("create NonTrivialTemplate");
3030
}
31-
inline NonTrivialTemplate(const NonTrivialTemplate<T> &) = default;
31+
inline NonTrivialTemplate(const NonTrivialTemplate<T> &other) : x(other.x) {
32+
puts("copy NonTrivialTemplate");
33+
}
3234
inline NonTrivialTemplate(NonTrivialTemplate<T> &&other) : x(static_cast<T &&>(other.x)) {
3335
puts("move NonTrivialTemplate");
3436
}
@@ -50,10 +52,34 @@ public func retNonTrivial(y: CInt) -> NonTrivialTemplate<Trivial> {
5052
return NonTrivialTemplate<Trivial>(Trivial(42, y))
5153
}
5254

55+
public func takeNonTrivial(_ x: NonTrivialTemplate<Trivial>) {
56+
print(x)
57+
}
58+
59+
public func passThroughNonTrivial(_ x: NonTrivialTemplate<Trivial>) -> NonTrivialTemplate<Trivial>{
60+
return x
61+
}
62+
63+
public func inoutNonTrivial(_ x: inout NonTrivialTemplate<Trivial>) {
64+
x.x.y *= 2
65+
}
66+
5367
public func retTrivial(_ x: CInt) -> Trivial {
5468
return Trivial(x, -x)
5569
}
5670

71+
public func takeTrivial(_ x: Trivial) {
72+
print(x)
73+
}
74+
75+
public func passThroughTrivial(_ x: Trivial) -> Trivial {
76+
return x
77+
}
78+
79+
public func inoutTrivial(_ x: inout Trivial) {
80+
x.x = x.y + x.x - 11
81+
}
82+
5783
//--- use-swift-cxx-types.cpp
5884

5985
#include "header.h"
@@ -65,15 +91,37 @@ int main() {
6591
auto x = UseCxx::retTrivial(423421);
6692
assert(x.x == 423421);
6793
assert(x.y == -423421);
94+
UseCxx::takeTrivial(UseCxx::passThroughTrivial(x));
95+
assert(x.x == 423421);
96+
assert(x.y == -423421);
97+
UseCxx::inoutTrivial(x);
98+
assert(x.x == -11);
99+
assert(x.y == -423421);
100+
UseCxx::takeTrivial(x);
68101
}
102+
// CHECK: Trivial(x: 423421, y: -423421)
103+
// CHECK-NEXT: Trivial(x: -11, y: -423421)
69104
{
70105
auto x = UseCxx::retNonTrivial(-942);
71106
assert(x.x.y == -942);
72107
assert(x.x.x == 42);
108+
UseCxx::takeNonTrivial(UseCxx::passThroughNonTrivial(x));
109+
puts("done non trivial");
110+
UseCxx::inoutNonTrivial(x);
111+
assert(x.x.y == -1884);
112+
assert(x.x.x == 42);
73113
}
74-
// CHECK: create NonTrivialTemplate
114+
// CHECK-NEXT: create NonTrivialTemplate
115+
// CHECK-NEXT: move NonTrivialTemplate
116+
// CHECK-NEXT: ~NonTrivialTemplate
117+
// CHECK-NEXT: copy NonTrivialTemplate
75118
// CHECK-NEXT: move NonTrivialTemplate
76119
// CHECK-NEXT: ~NonTrivialTemplate
120+
// CHECK-NEXT: copy NonTrivialTemplate
121+
// CHECK-NEXT: __CxxTemplateInst18NonTrivialTemplateI7TrivialE(x: __C.Trivial(x: 42, y: -942))
122+
// CHECK-NEXT: ~NonTrivialTemplate
123+
// CHECK-NEXT: ~NonTrivialTemplate
124+
// CHECK-NEXT: done non trivial
77125
// CHECK-NEXT: ~NonTrivialTemplate
78126
return 0;
79127
}

test/Interop/CxxToSwiftToCxx/bridge-cxx-struct-back-to-cxx.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ public func retTrivial() -> Trivial {
7171
return Trivial()
7272
}
7373

74+
public func takeNonTrivial2(_ x: ns.NonTrivialTemplate<ns.TrivialinNS>) {
75+
}
76+
77+
public func takeTrivial(_ x: Trivial) {
78+
}
79+
80+
public func takeTrivialInout(_ x: inout Trivial) {
81+
}
82+
7483
// CHECK: #if __has_feature(objc_modules)
7584
// CHECK: #if __has_feature(objc_modules)
7685
// CHECK-NEXT: #if __has_warning("-Watimport-in-framework-header")
@@ -120,3 +129,14 @@ public func retTrivial() -> Trivial {
120129
// CHECK-NEXT: return *storageObjectPtr;
121130
// CHECK-NEXT: }
122131

132+
// CHECK: inline void takeNonTrivial2(const ns::NonTrivialTemplate<ns::TrivialinNS>& x) noexcept {
133+
// CHECK-NEXT: return _impl::$s8UseCxxTy15takeNonTrivial2yySo2nsO02__b18TemplateInstN2ns18e7TrivialH20INS_11TrivialinNSEEEVF(swift::_impl::getOpaquePointer(x));
134+
// CHECK-NEXT: }
135+
136+
// CHECK: inline void takeTrivial(const Trivial& x) noexcept {
137+
// CHECK-NEXT: return _impl::$s8UseCxxTy11takeTrivialyySo0E0VF(_impl::swift_interop_passDirect_UseCxxTy_uint32_t_0_4(reinterpret_cast<const char *>(swift::_impl::getOpaquePointer(x))));
138+
// CHECK-NEXT: }
139+
140+
// CHECK: inline void takeTrivialInout(Trivial& x) noexcept {
141+
// CHECK-NEXT: return _impl::$s8UseCxxTy16takeTrivialInoutyySo0E0VzF(swift::_impl::getOpaquePointer(x));
142+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)