Skip to content

Commit 3533686

Browse files
committed
[interop][SwiftToCxx] emit copy constructor that calls value witness initWithCopy function for Swift structs
1 parent b787172 commit 3533686

File tree

4 files changed

+43
-3
lines changed

4 files changed

+43
-3
lines changed

lib/PrintAsClang/PrintClangValueType.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,15 @@ void ClangValueTypePrinter::printStructDecl(const StructDecl *SD) {
126126
printer.printBaseName(SD);
127127
os << "(const ";
128128
printer.printBaseName(SD);
129-
os << " &) = default;\n";
129+
os << " &other) {\n";
130+
os << " auto metadata = " << cxx_synthesis::getCxxImplNamespaceName()
131+
<< "::" << typeMetadataFuncName << "(0);\n";
132+
os << " auto *vwTable = "
133+
"*(reinterpret_cast<swift::_impl::ValueWitnessTable **>(metadata._0) - "
134+
"1);\n";
135+
os << " vwTable->initializeWithCopy(_getOpaquePointer(), const_cast<char "
136+
"*>(other._getOpaquePointer()), metadata._0);\n";
137+
os << " }\n";
130138

131139
// FIXME: the move constructor should be hidden somehow.
132140
os << " inline ";

test/Interop/SwiftToCxx/structs/struct-with-refcounted-member-execution.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,29 @@ int main() {
2020
{
2121
StructWithRefcountedMember value = returnNewStructWithRefcountedMember();
2222
}
23+
printBreak(1);
2324
// CHECK: create RefCountedClass
2425
// CHECK-NEXT: destroy RefCountedClass
26+
// CHECK-NEXT: breakpoint 1
27+
28+
{
29+
StructWithRefcountedMember value = returnNewStructWithRefcountedMember();
30+
StructWithRefcountedMember copyValue(value);
31+
}
32+
printBreak(2);
33+
// CHECK-NEXT: create RefCountedClass
34+
// CHECK-NEXT: destroy RefCountedClass
35+
// CHECK-NEXT: breakpoint 2
36+
37+
{
38+
StructWithRefcountedMember value = returnNewStructWithRefcountedMember();
39+
StructWithRefcountedMember value2(returnNewStructWithRefcountedMember());
40+
}
41+
printBreak(3);
42+
// CHECK-NEXT: create RefCountedClass
43+
// CHECK-NEXT: create RefCountedClass
44+
// CHECK-NEXT: destroy RefCountedClass
45+
// CHECK-NEXT: destroy RefCountedClass
46+
// CHECK-NEXT: breakpoint 3
2547
return 0;
2648
}

test/Interop/SwiftToCxx/structs/struct-with-refcounted-member.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,21 @@ public func returnNewStructWithRefcountedMember() -> StructWithRefcountedMember
2121
return StructWithRefcountedMember(x: RefCountedClass())
2222
}
2323

24+
public func printBreak(_ x: Int) {
25+
print("breakpoint \(x)")
26+
}
27+
2428
// CHECK: class StructWithRefcountedMember final {
2529
// CHECK-NEXT: public:
2630
// CHECK-NEXT: inline ~StructWithRefcountedMember() {
2731
// CHECK-NEXT: auto metadata = _impl::$s7Structs26StructWithRefcountedMemberVMa(0);
2832
// CHECK-NEXT: auto *vwTable = *(reinterpret_cast<swift::_impl::ValueWitnessTable **>(metadata._0) - 1);
2933
// CHECK-NEXT: vwTable->destroy(_getOpaquePointer(), metadata._0);
3034
// CHECK-NEXT: }
31-
// CHECK-NEXT: inline StructWithRefcountedMember(const StructWithRefcountedMember &) = default;
35+
// CHECK-NEXT: inline StructWithRefcountedMember(const StructWithRefcountedMember &other) {
36+
// CHECK-NEXT: auto metadata = _impl::$s7Structs26StructWithRefcountedMemberVMa(0);
37+
// CHECK-NEXT: auto *vwTable = *(reinterpret_cast<swift::_impl::ValueWitnessTable **>(metadata._0) - 1);
38+
// CHECK-NEXT: vwTable->initializeWithCopy(_getOpaquePointer(), const_cast<char *>(other._getOpaquePointer()), metadata._0);
39+
// CHECK-NEXT: }
3240
// CHECK-NEXT: inline StructWithRefcountedMember(StructWithRefcountedMember &&) = default;
3341
// CHECK-NEXT: private:

test/Interop/SwiftToCxx/structs/swift-struct-in-cxx.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
// CHECK: class StructWithIntField final {
2323
// CHECK-NEXT: public:
2424
// CHECK-NEXT: inline ~StructWithIntField() {
25-
// CHECK: inline StructWithIntField(const StructWithIntField &) = default;
25+
// CHECK: }
26+
// CHECK-NEXT: inline StructWithIntField(const StructWithIntField &other) {
27+
// CHECK: }
2628
// CHECK-NEXT: inline StructWithIntField(StructWithIntField &&) = default;
2729
// CHECK-NEXT: private:
2830
// CHECK-NEXT: inline StructWithIntField() {}

0 commit comments

Comments
 (0)