Skip to content

Commit e3a51c7

Browse files
committed
[interop][SwiftToCxx] support interop with FRT in the generated C++ bindings
1 parent 5cf1cb3 commit e3a51c7

File tree

2 files changed

+67
-4
lines changed

2 files changed

+67
-4
lines changed

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,13 @@ class CFunctionSignatureTypePrinter
268268
bool isInOutParam) {
269269
auto *cd = CT->getDecl();
270270
if (cd->hasClangNode()) {
271-
ClangSyntaxPrinter(os).printIdentifier(
272-
cast<clang::NamedDecl>(cd->getClangDecl())->getName());
271+
ClangSyntaxPrinter(os).printNominalClangTypeReference(cd->getClangDecl());
273272
os << " *"
274273
<< (!optionalKind || *optionalKind == OTK_None ? "_Nonnull"
275274
: "_Nullable");
276275
if (isInOutParam) {
277-
os << " __strong";
276+
if (isa<clang::ObjCContainerDecl>(cd->getClangDecl()))
277+
os << " __strong";
278278
printInoutTypeModifier();
279279
}
280280
// FIXME: Mark that this is only ObjC representable.
@@ -1151,7 +1151,13 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
11511151
return;
11521152
}
11531153
if (auto *classDecl = resultTy->getClassOrBoundGenericClass()) {
1154-
assert(!classDecl->hasClangNode());
1154+
if (classDecl->hasClangNode()) {
1155+
assert(!isa<clang::ObjCContainerDecl>(classDecl->getClangDecl()));
1156+
os << "return ";
1157+
printCallToCFunc(/*additionalParam=*/None);
1158+
os << ";\n";
1159+
return;
1160+
}
11551161
ClangClassTypePrinter::printClassTypeReturnScaffold(
11561162
os, classDecl, moduleContext,
11571163
[&]() { printCallToCFunc(/*additionalParam=*/None); });

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

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,29 @@ namespace ns {
4444
struct NonTrivialImplicitMove {
4545
NonTrivialTemplate<int> member;
4646
};
47+
48+
#define IMMORTAL_REF \
49+
__attribute__((swift_attr("import_as_ref"))) \
50+
__attribute__((swift_attr("retain:immortal"))) \
51+
__attribute__((swift_attr("release:immortal")))
52+
struct IMMORTAL_REF Immortal {
53+
public:
54+
};
55+
56+
inline Immortal *makeNewImmortal() {
57+
return new Immortal;
58+
}
59+
60+
template<class T>
61+
struct IMMORTAL_REF ImmortalTemplate {
62+
public:
63+
};
64+
65+
inline ImmortalTemplate<int> *makeNewImmortalInt() {
66+
return new ImmortalTemplate<int>;
67+
}
68+
69+
using ImmortalCInt = ImmortalTemplate<int>;
4770
}
4871

4972
//--- module.modulemap
@@ -55,6 +78,16 @@ module CxxTest {
5578
//--- use-cxx-types.swift
5679
import CxxTest
5780

81+
@_expose(Cxx)
82+
public func retImmortal() -> ns.Immortal {
83+
return ns.makeNewImmortal()
84+
}
85+
86+
@_expose(Cxx)
87+
public func retImmortalTemplate() -> ns.ImmortalCInt {
88+
return ns.makeNewImmortalInt()
89+
}
90+
5891
@_expose(Cxx)
5992
public func retNonTrivial() -> ns.NonTrivialTemplate<CInt> {
6093
return ns.NonTrivialTemplate<CInt>()
@@ -80,6 +113,14 @@ public func retTrivial() -> Trivial {
80113
return Trivial()
81114
}
82115

116+
@_expose(Cxx)
117+
public func takeImmortal(_ x: ns.Immortal) {
118+
}
119+
120+
@_expose(Cxx)
121+
public func takeImmortalTemplate(_ x: ns.ImmortalCInt) {
122+
}
123+
83124
@_expose(Cxx)
84125
public func takeNonTrivial2(_ x: ns.NonTrivialTemplate<ns.TrivialinNS>) {
85126
}
@@ -104,6 +145,14 @@ public func takeTrivialInout(_ x: inout Trivial) {
104145
// CHECK: SWIFT_EXTERN void $s8UseCxxTy13retNonTrivialSo2nsO02__b18TemplateInstN2ns18efH4IiEEVyF(SWIFT_INDIRECT_RESULT void * _Nonnull) SWIFT_NOEXCEPT SWIFT_CALL; // retNonTrivial()
105146
// CHECK: SWIFT_EXTERN struct swift_interop_returnStub_UseCxxTy_uint32_t_0_4 $s8UseCxxTy10retTrivialSo0E0VyF(void) SWIFT_NOEXCEPT SWIFT_CALL; // retTrivial()
106147

148+
// CHECK: ns::Immortal *_Nonnull retImmortal() noexcept SWIFT_WARN_UNUSED_RESULT {
149+
// CHECK-NEXT: return _impl::$s8UseCxxTy11retImmortalSo2nsO0E0VyF();
150+
// CHECK-NEXT: }
151+
152+
// CHECK: ns::ImmortalTemplate<int> *_Nonnull retImmortalTemplate() noexcept SWIFT_WARN_UNUSED_RESULT {
153+
// CHECK-NEXT: return _impl::$s8UseCxxTy19retImmortalTemplateSo2nsO02__bf10InstN2ns16eF4IiEEVyF();
154+
// CHECK-NEXT: }
155+
107156
// CHECK: } // end namespace
108157
// CHECK-EMPTY:
109158
// CHECK-NEXT: namespace swift {
@@ -200,6 +249,14 @@ public func takeTrivialInout(_ x: inout Trivial) {
200249
// CHECK-NEXT: return *storageObjectPtr;
201250
// CHECK-NEXT: }
202251

252+
// CHECK: void takeImmortal(ns::Immortal *_Nonnull x) noexcept {
253+
// CHECK-NEXT: return _impl::$s8UseCxxTy12takeImmortalyySo2nsO0E0VF(x);
254+
// CHECK-NEXT: }
255+
256+
// CHECK: void takeImmortalTemplate(ns::ImmortalTemplate<int> *_Nonnull x) noexcept {
257+
// CHECK-NEXT: return _impl::$s8UseCxxTy20takeImmortalTemplateyySo2nsO02__bf10InstN2ns16eF4IiEEVF(x);
258+
// CHECK-NEXT: }
259+
203260
// CHECK: inline void takeNonTrivial2(const ns::NonTrivialTemplate<ns::TrivialinNS>& x) noexcept {
204261
// CHECK-NEXT: return _impl::$s8UseCxxTy15takeNonTrivial2yySo2nsO02__b18TemplateInstN2ns18e7TrivialH20INS_11TrivialinNSEEEVF(swift::_impl::getOpaquePointer(x));
205262
// CHECK-NEXT: }

0 commit comments

Comments
 (0)