Skip to content

Commit 0ca6106

Browse files
committed
[interop][SwiftToCxx] Add a base ref counted Swift class type to _SwiftCxxInteroperability.h header
1 parent c332a90 commit 0ca6106

File tree

3 files changed

+36
-50
lines changed

3 files changed

+36
-50
lines changed

lib/PrintAsClang/PrintClangClassType.cpp

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -31,53 +31,24 @@ void ClangClassTypePrinter::printClassTypeDecl(
3131
os << ";\n";
3232
});
3333

34+
StringRef baseClassName = "RefCountedClass";
35+
StringRef baseClassQualifiedName = "swift::_impl::RefCountedClass";
36+
3437
os << "class ";
3538
printer.printBaseName(typeDecl);
3639
// FIXME: Add support for inherintance.
37-
os << " final";
40+
os << " final : " << baseClassQualifiedName;
3841
os << " {\n";
3942
os << "public:\n";
4043

41-
// Destructor releases the object.
42-
os << " inline ~";
43-
printer.printBaseName(typeDecl);
44-
os << "() { swift::" << cxx_synthesis::getCxxImplNamespaceName()
45-
<< "::swift_release(_opaquePointer); }\n";
46-
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-
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-
68-
// FIXME: move semantics should be restricted?
69-
os << " inline ";
70-
printer.printBaseName(typeDecl);
71-
os << "(";
72-
printer.printBaseName(typeDecl);
73-
os << "&&) noexcept = default;\n";
44+
os << " using " << baseClassName << "::" << baseClassName << ";\n";
45+
os << " using " << baseClassName << "::operator=;\n";
7446

7547
os << "private:\n";
7648
os << " inline ";
7749
printer.printBaseName(typeDecl);
78-
os << "(void * _Nonnull ptr) noexcept : _opaquePointer(ptr) {}\n";
79-
os << "\n void * _Nonnull _opaquePointer;\n";
80-
os << " friend class " << cxx_synthesis::getCxxImplNamespaceName() << "::";
50+
os << "(void * _Nonnull ptr) noexcept : " << baseClassName << "(ptr) {}\n";
51+
os << "\n friend class " << cxx_synthesis::getCxxImplNamespaceName() << "::";
8152
printCxxImplClassName(os, typeDecl);
8253
os << ";\n";
8354
os << "};\n\n";

stdlib/public/SwiftShims/_SwiftCxxInteroperability.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,29 @@ inline void opaqueFree(void *_Nonnull p) noexcept {
5353
#endif
5454
}
5555

56+
/// Base class for a Swift reference counted class value.
57+
class RefCountedClass {
58+
public:
59+
inline ~RefCountedClass() { swift_release(_opaquePointer); }
60+
inline RefCountedClass(const RefCountedClass &other) noexcept
61+
: _opaquePointer(other._opaquePointer) {
62+
swift_retain(_opaquePointer);
63+
}
64+
inline RefCountedClass &operator=(const RefCountedClass &other) noexcept {
65+
swift_retain(other._opaquePointer);
66+
swift_release(_opaquePointer);
67+
_opaquePointer = other._opaquePointer;
68+
return *this;
69+
}
70+
// FIXME: What to do in 'move'?
71+
inline RefCountedClass(RefCountedClass &&) noexcept = default;
72+
73+
protected:
74+
inline RefCountedClass(void *_Nonnull ptr) noexcept : _opaquePointer(ptr) {}
75+
76+
void *_Nonnull _opaquePointer;
77+
};
78+
5679
} // namespace _impl
5780

5881
/// Swift's Int type.

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

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,13 @@ public final class ClassWithIntField {
3131
// CHECK-EMPTY:
3232
// CHECK-NEXT: } // namespace _impl
3333
// CHECK-EMPTY:
34-
// CHECK-NEXT: class ClassWithIntField final {
34+
// CHECK-NEXT: class ClassWithIntField final : swift::_impl::RefCountedClass {
3535
// CHECK-NEXT: public:
36-
// 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); }
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: }
44-
// CHECK-NEXT: inline ClassWithIntField(ClassWithIntField&&) noexcept = default;
36+
// CHECK-NEXT: using RefCountedClass::RefCountedClass;
37+
// CHECK-NEXT: using RefCountedClass::operator=;
4538
// CHECK-NEXT: private:
46-
// CHECK-NEXT: inline ClassWithIntField(void * _Nonnull ptr) noexcept : _opaquePointer(ptr) {}
39+
// CHECK-NEXT: inline ClassWithIntField(void * _Nonnull ptr) noexcept : RefCountedClass(ptr) {}
4740
// CHECK-EMPTY:
48-
// CHECK-NEXT: void * _Nonnull _opaquePointer;
4941
// CHECK-NEXT: friend class _impl::_impl_ClassWithIntField;
5042
// CHECK-NEXT: };
5143
// CHECK-EMPTY:
@@ -66,7 +58,7 @@ public final class ClassWithIntField {
6658

6759
public final class register { }
6860

69-
// CHECK: class register_ final {
61+
// CHECK: class register_ final : swift::_impl::RefCountedClass {
7062

7163
public func returnClassWithIntField() -> ClassWithIntField {
7264
return ClassWithIntField()

0 commit comments

Comments
 (0)