Skip to content

Commit c332a90

Browse files
committed
[interop][SwiftToCxx] retain & release class values when a C++ class reference is copy assigned
1 parent e289865 commit c332a90

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

lib/PrintAsClang/PrintClangClassType.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,19 @@ void ClangClassTypePrinter::printClassTypeDecl(
5252
<< cxx_synthesis::getCxxImplNamespaceName()
5353
<< "::swift_retain(_opaquePointer); }\n";
5454

55+
os << " inline ";
56+
printer.printBaseName(typeDecl);
57+
os << " & operator=(const ";
58+
printer.printBaseName(typeDecl);
59+
os << "& other) noexcept {\n swift::"
60+
<< cxx_synthesis::getCxxImplNamespaceName()
61+
<< "::swift_retain(other._opaquePointer);\n";
62+
os << " swift::" << cxx_synthesis::getCxxImplNamespaceName()
63+
<< "::swift_release(_opaquePointer);\n";
64+
os << " _opaquePointer = other._opaquePointer;\n";
65+
os << " return *this;\n";
66+
os << " }\n";
67+
5568
// FIXME: move semantics should be restricted?
5669
os << " inline ";
5770
printer.printBaseName(typeDecl);

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,24 @@ int main() {
7474
assert(getRetainCount(x) == 1);
7575
}
7676
// CHECK-NEXT: init ClassWithIntField
77+
// CHECK-NEXT: destroy ClassWithIntField
78+
79+
{
80+
auto x = returnClassWithIntField();
81+
{
82+
auto x2 = returnClassWithIntField();
83+
assert(getRetainCount(x2) == 1);
84+
assert(getRetainCount(x) == 1);
85+
x = x2;
86+
assert(getRetainCount(x) == 2);
87+
}
88+
takeClassWithIntField(x);
89+
assert(getRetainCount(x) == 1);
90+
}
91+
// CHECK-NEXT: init ClassWithIntField
92+
// CHECK-NEXT: init ClassWithIntField
93+
// CHECK-NEXT: destroy ClassWithIntField
94+
// CHECK-NEXT: ClassWithIntField: 0;
7795
// CHECK-NEXT: destroy ClassWithIntField
7896
return 0;
7997
}

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,13 @@ 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); }
37+
// CHECK-NEXT: inline ClassWithIntField(const ClassWithIntField& other) noexcept : _opaquePointer(other._opaquePointer) { swift::_impl::swift_retain(_opaquePointer); }
38+
// CHECK-NEXT: inline ClassWithIntField & operator=(const ClassWithIntField& other) noexcept {
39+
// CHECK-NEXT: swift::_impl::swift_retain(other._opaquePointer);
40+
// CHECK-NEXT: swift::_impl::swift_release(_opaquePointer);
41+
// CHECK-NEXT: _opaquePointer = other._opaquePointer;
42+
// CHECK-NEXT: return *this;
43+
// CHECK-NEXT: }
3844
// CHECK-NEXT: inline ClassWithIntField(ClassWithIntField&&) noexcept = default;
3945
// CHECK-NEXT: private:
4046
// CHECK-NEXT: inline ClassWithIntField(void * _Nonnull ptr) noexcept : _opaquePointer(ptr) {}

0 commit comments

Comments
 (0)