Skip to content

Commit e289865

Browse files
committed
[interop][SwiftToCxx] retain class values when a C++ class reference is copy constructed
1 parent e1d812a commit e289865

File tree

3 files changed

+20
-0
lines changed

3 files changed

+20
-0
lines changed

lib/PrintAsClang/PrintClangClassType.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ void ClangClassTypePrinter::printClassTypeDecl(
4444
os << "() { swift::" << cxx_synthesis::getCxxImplNamespaceName()
4545
<< "::swift_release(_opaquePointer); }\n";
4646

47+
os << " inline ";
48+
printer.printBaseName(typeDecl);
49+
os << "(const ";
50+
printer.printBaseName(typeDecl);
51+
os << "& other) noexcept : _opaquePointer(other._opaquePointer) { swift::"
52+
<< cxx_synthesis::getCxxImplNamespaceName()
53+
<< "::swift_retain(_opaquePointer); }\n";
54+
4755
// FIXME: move semantics should be restricted?
4856
os << " inline ";
4957
printer.printBaseName(typeDecl);

test/Interop/SwiftToCxx/class/swift-class-execution.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ int main() {
6363
// CHECK-NEXT: init ClassWithIntField
6464
// CHECK-NEXT: destroy ClassWithIntField
6565
// CHECK-NEXT: ClassWithIntField: -11;
66+
// CHECK-NEXT: destroy ClassWithIntField
67+
68+
{
69+
auto x = returnClassWithIntField();
70+
{
71+
auto x2 = x;
72+
assert(getRetainCount(x) == 2);
73+
}
74+
assert(getRetainCount(x) == 1);
75+
}
76+
// CHECK-NEXT: init ClassWithIntField
6677
// CHECK-NEXT: destroy ClassWithIntField
6778
return 0;
6879
}

test/Interop/SwiftToCxx/class/swift-class-in-cxx.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public final class ClassWithIntField {
3434
// CHECK-NEXT: class ClassWithIntField final {
3535
// CHECK-NEXT: public:
3636
// CHECK-NEXT: inline ~ClassWithIntField() { swift::_impl::swift_release(_opaquePointer); }
37+
// CHECK-NEXT: inline ClassWithIntField(const ClassWithIntField& other) noexcept : _opaquePointer(other._opaquePointer) { swift::_impl::swift_retain(_opaquePointer); }
3738
// CHECK-NEXT: inline ClassWithIntField(ClassWithIntField&&) noexcept = default;
3839
// CHECK-NEXT: private:
3940
// CHECK-NEXT: inline ClassWithIntField(void * _Nonnull ptr) noexcept : _opaquePointer(ptr) {}

0 commit comments

Comments
 (0)