Skip to content

Commit f577330

Browse files
committed
[interop][SwiftToCxx] fix copy constructor for resilient structs
1 parent 5474d7e commit f577330

File tree

5 files changed

+51
-2
lines changed

5 files changed

+51
-2
lines changed

lib/PrintAsClang/PrintClangValueType.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@ void ClangValueTypePrinter::printValueTypeDecl(
140140
os << " auto *vwTable = ";
141141
printer.printValueWitnessTableAccessFromTypeMetadata("metadata");
142142
os << ";\n";
143+
if (isOpaqueLayout) {
144+
os << " _storage = ";
145+
printer.printSwiftImplQualifier();
146+
os << cxx_synthesis::getCxxOpaqueStorageClassName() << "(vwTable);\n";
147+
}
143148
os << " vwTable->initializeWithCopy(_getOpaquePointer(), const_cast<char "
144149
"*>(other._getOpaquePointer()), metadata._0);\n";
145150
os << " }\n";

lib/PrintAsClang/PrintSwiftToClangCoreScaffold.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ static void printSwiftResilientStorageClass(raw_ostream &os) {
132132
<< "&& other) : storage(other.storage) { other.storage = nullptr; }\n";
133133
os << " inline " << name << "(const " << name << "&) = delete;\n";
134134
os << " inline ~" << name << "() { if (storage) { delete[] storage; } }\n";
135+
os << " void operator =(" << name
136+
<< "&& other) { auto temp = storage; storage = other.storage; "
137+
"other.storage = temp; }\n";
138+
os << " void operator =(const " << name << "&) = delete;\n";
135139
os << " inline char * _Nonnull getOpaquePointer() { return static_cast<char "
136140
"* _Nonnull>(storage); }\n";
137141
os << " inline const char * _Nonnull getOpaquePointer() const { return "

test/Interop/SwiftToCxx/core/swift-impl-defs-in-cxx.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@
5959
// CHECK-NEXT: inline OpaqueStorage(OpaqueStorage&& other) : storage(other.storage) { other.storage = nullptr; }
6060
// CHECK-NEXT: inline OpaqueStorage(const OpaqueStorage&) = delete;
6161
// CHECK-NEXT: inline ~OpaqueStorage() { if (storage) { delete[] storage; } }
62+
// CHECK-NEXT: void operator =(OpaqueStorage&& other) { auto temp = storage; storage = other.storage; other.storage = temp; }
63+
// CHECK-NEXT: void operator =(const OpaqueStorage&) = delete;
6264
// CHECK-NEXT: inline char * _Nonnull getOpaquePointer() { return static_cast<char * _Nonnull>(storage); }
6365
// CHECK-NEXT: inline const char * _Nonnull getOpaquePointer() const { return static_cast<char * _Nonnull>(storage); }
6466
// CHECK-NEXT: private:

test/Interop/SwiftToCxx/structs/resilient-struct-in-cxx-execution.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ int main() {
3434
// CURRENT-NEXT: x = 65
3535
// CHANGE-NEXT: x&y = 65&0
3636

37+
auto copySmallStruct = smallStruct;
38+
mutateSmall(copySmallStruct);
39+
copySmallStruct.dump();
40+
// CHECK: find - small dump
41+
// CURRENT-NEXT: x = 66
42+
// CHANGE-NEXT: x&y = 0&65
43+
3744
printSmallAndLarge(smallStruct, largeStruct);
3845
// CHECK: find - small dump
3946
// CURRENT-NEXT: x = 65
@@ -44,9 +51,14 @@ int main() {
4451
auto structWithRefCountStoredProp =
4552
createStructWithRefCountStoredProp();
4653
structWithRefCountStoredProp.dump();
54+
{
55+
StructWithRefCountStoredProp copy(structWithRefCountStoredProp);
56+
}
57+
structWithRefCountStoredProp.dump();
4758
}
4859
// CHECK-NEXT: create RefCountedClass 0
4960
// CHECK-NEXT: storedRef = 0
61+
// CHECK-NEXT: storedRef = 0
5062
// CHECK-NEXT: destroy RefCountedClass 0
5163
return 0;
5264
}

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

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
// RUN: %check-interop-cxx-header-in-clang(%t/structs.h)
66

77
public struct FirstSmallStruct {
8-
public let x: UInt32
8+
public var x: UInt32
99
#if CHANGE_LAYOUT
10-
public let y: UInt32 = 0
10+
public var y: UInt32 = 0
1111
#endif
1212

1313
public func dump() {
@@ -22,6 +22,12 @@ public struct FirstSmallStruct {
2222

2323
// CHECK: class FirstSmallStruct final {
2424
// CHECK-NEXT: public:
25+
// CHECK: inline FirstSmallStruct(const FirstSmallStruct &other) {
26+
// CHECK-NEXT: auto metadata = _impl::$s7Structs16FirstSmallStructVMa(0);
27+
// CHECK-NEXT: auto *vwTable = *(reinterpret_cast<swift::_impl::ValueWitnessTable **>(metadata._0) - 1);
28+
// CHECK-NEXT: _storage = swift::_impl::OpaqueStorage(vwTable);
29+
// CHECK-NEXT: vwTable->initializeWithCopy(_getOpaquePointer(), const_cast<char *>(other._getOpaquePointer()), metadata._0);
30+
// CHECK-NEXT: }
2531
// CHECK: private:
2632
// CHECK-NEXT: inline FirstSmallStruct(swift::_impl::ValueWitnessTable *vwTable) : _storage(vwTable) {}
2733
// CHECK-NEXT: static inline FirstSmallStruct _make() {
@@ -57,6 +63,12 @@ public struct LargeStruct {
5763

5864
// CHECK: class LargeStruct final {
5965
// CHECK-NEXT: public:
66+
// CHECK: inline LargeStruct(const LargeStruct &other) {
67+
// CHECK-NEXT: auto metadata = _impl::$s7Structs11LargeStructVMa(0);
68+
// CHECK-NEXT: auto *vwTable = *(reinterpret_cast<swift::_impl::ValueWitnessTable **>(metadata._0) - 1);
69+
// CHECK-NEXT: _storage = swift::_impl::OpaqueStorage(vwTable);
70+
// CHECK-NEXT: vwTable->initializeWithCopy(_getOpaquePointer(), const_cast<char *>(other._getOpaquePointer()), metadata._0);
71+
// CHECK-NEXT: }
6072
// CHECK: private:
6173
// CHECK-NEXT: inline LargeStruct(swift::_impl::ValueWitnessTable *vwTable) : _storage(vwTable) {}
6274
// CHECK-NEXT: static inline LargeStruct _make() {
@@ -124,6 +136,16 @@ public func createStructWithRefCountStoredProp() -> StructWithRefCountStoredProp
124136
return StructWithRefCountStoredProp(x: 0)
125137
}
126138

139+
public func mutateSmall(_ x: inout FirstSmallStruct) {
140+
#if CHANGE_LAYOUT
141+
let y = x.y
142+
x.y = x.x
143+
x.x = y
144+
#else
145+
x.x += 1
146+
#endif
147+
}
148+
127149
// CHECK: inline LargeStruct createLargeStruct(swift::Int x) noexcept SWIFT_WARN_UNUSED_RESULT {
128150
// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) {
129151
// CHECK-NEXT: _impl::$s7Structs17createLargeStructyAA0cD0VSiF(result, x);
@@ -136,6 +158,10 @@ public func createStructWithRefCountStoredProp() -> StructWithRefCountStoredProp
136158
// CHECK-NEXT: });
137159
// CHECK-NEXT: }
138160

161+
// CHECK: inline void mutateSmall(FirstSmallStruct& x) noexcept {
162+
// CHECK-NEXT: return _impl::$s7Structs11mutateSmallyyAA05FirstC6StructVzF(_impl::_impl_FirstSmallStruct::getOpaquePointer(x));
163+
// CHECK-NEXT: }
164+
139165
// CHECK: inline void printSmallAndLarge(const FirstSmallStruct& x, const LargeStruct& y) noexcept {
140166
// CHECK-NEXT: return _impl::$s7Structs18printSmallAndLargeyyAA05FirstC6StructV_AA0eG0VtF(_impl::_impl_FirstSmallStruct::getOpaquePointer(x), _impl::_impl_LargeStruct::getOpaquePointer(y));
141167
// CHECK-NEXT: }

0 commit comments

Comments
 (0)