diff --git a/lib/PrintAsClang/PrintClangValueType.cpp b/lib/PrintAsClang/PrintClangValueType.cpp index 2f01f75976f59..2835ab7b89c88 100644 --- a/lib/PrintAsClang/PrintClangValueType.cpp +++ b/lib/PrintAsClang/PrintClangValueType.cpp @@ -288,6 +288,7 @@ void ClangValueTypePrinter::printValueTypeDecl( os << " vwTable->destroy(_getOpaquePointer(), metadata._0);\n"; os << " }\n"; + // copy constructor. os << " "; printer.printInlineForThunk(); printer.printBaseName(typeDecl); @@ -306,6 +307,28 @@ void ClangValueTypePrinter::printValueTypeDecl( "*>(other._getOpaquePointer()), metadata._0);\n"; os << " }\n"; + // copy assignment. + os << " "; + printer.printInlineForThunk(); + printer.printBaseName(typeDecl); + os << " &operator =(const "; + printer.printBaseName(typeDecl); + os << " &other) noexcept {\n"; + ClangValueTypePrinter::printValueWitnessTableAccessAsVariable( + os, typeMetadataFuncName, typeMetadataFuncGenericParams); + os << " vwTable->assignWithCopy(_getOpaquePointer(), const_cast(other._getOpaquePointer()), metadata._0);\n"; + os << " return *this;\n"; + os << " }\n"; + + // FIXME: implement the move assignment. + os << " "; + printer.printInlineForThunk(); + printer.printBaseName(typeDecl); + os << " &operator =("; + printer.printBaseName(typeDecl); + os << " &&other) = delete;\n"; + // FIXME: implement the move constructor. os << " [[noreturn]] "; // NOTE: Do not apply attribute((used)) diff --git a/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift b/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift index a55c72bb170c5..6cac06d52f576 100644 --- a/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift +++ b/test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift @@ -72,6 +72,9 @@ // CHECK: } // CHECK-NEXT: SWIFT_INLINE_THUNK String(const String &other) noexcept { // CHECK: } +// CHECK-NEXT: SWIFT_INLINE_THUNK String &operator =(const String &other) noexcept { +// CHECK: } +// CHECK-NEXT: SWIFT_INLINE_THUNK String &operator =(String &&other) = delete; // CHECK-NEXT: SWIFT_INLINE_PRIVATE_HELPER String(String &&) noexcept { // CHECK: } // CHECK-NEXT: static SWIFT_INLINE_THUNK String init() SWIFT_SYMBOL({{.*}}); diff --git a/test/Interop/SwiftToCxx/structs/struct-move-semantics-in-cxx.cpp b/test/Interop/SwiftToCxx/structs/struct-move-semantics-in-cxx.cpp index febfc3c7cb57d..1ebdaa7d7c600 100644 --- a/test/Interop/SwiftToCxx/structs/struct-move-semantics-in-cxx.cpp +++ b/test/Interop/SwiftToCxx/structs/struct-move-semantics-in-cxx.cpp @@ -9,6 +9,10 @@ // LINK: fatalError_Cxx_move_of_Swift_value_type_not_supported_yet +// Compile should fail by default when move assignment is attempted in C++: + +// RUN: not %target-interop-build-clangxx -c %s -I %t -o %t/swift-structs-execution.o -DMOVE_ASSIGN 2>&1 | %FileCheck --check-prefix=MOVEASSIGN %s + // Fallback to abort at runtime: // RUN: %target-interop-build-clangxx -c %s -I %t -o %t/swift-structs-execution.o -DLINKS @@ -34,7 +38,13 @@ int main() { using namespace Structs; auto x = returnNewStructSeveralI64(42); +#ifdef MOVE_ASSIGN + auto y = returnNewStructSeveralI64(24); + x = std::move(y); +// MOVEASSIGN: deleted operator '=' +#else StructSeveralI64 x2 = std::move(x); +#endif return 0; } diff --git a/test/Interop/SwiftToCxx/structs/struct-with-refcounted-member-execution.cpp b/test/Interop/SwiftToCxx/structs/struct-with-refcounted-member-execution.cpp index 5b32f0e325995..b66a59465fbe0 100644 --- a/test/Interop/SwiftToCxx/structs/struct-with-refcounted-member-execution.cpp +++ b/test/Interop/SwiftToCxx/structs/struct-with-refcounted-member-execution.cpp @@ -44,5 +44,19 @@ int main() { // CHECK-NEXT: destroy RefCountedClass // CHECK-NEXT: destroy RefCountedClass // CHECK-NEXT: breakpoint 3 + + { + StructWithRefcountedMember value = returnNewStructWithRefcountedMember(); + StructWithRefcountedMember value2 = returnNewStructWithRefcountedMember(); + value = value2; + printBreak(4); + } + printBreak(5); +// CHECK-NEXT: create RefCountedClass +// CHECK-NEXT: create RefCountedClass +// CHECK-NEXT: destroy RefCountedClass +// CHECK-NEXT: breakpoint 4 +// CHECK-NEXT: destroy RefCountedClass +// CHECK-NEXT: breakpoint 5 return 0; } diff --git a/test/Interop/SwiftToCxx/structs/struct-with-refcounted-member.swift b/test/Interop/SwiftToCxx/structs/struct-with-refcounted-member.swift index c2564d24f6892..9a75b17b73e33 100644 --- a/test/Interop/SwiftToCxx/structs/struct-with-refcounted-member.swift +++ b/test/Interop/SwiftToCxx/structs/struct-with-refcounted-member.swift @@ -47,6 +47,18 @@ public func printBreak(_ x: Int) { // CHECK-NEXT: #endif // CHECK-NEXT: vwTable->initializeWithCopy(_getOpaquePointer(), const_cast(other._getOpaquePointer()), metadata._0); // CHECK-NEXT: } +// CHECK-NEXT: SWIFT_INLINE_THUNK StructWithRefcountedMember &operator =(const StructWithRefcountedMember &other) noexcept { +// CHECK-NEXT: auto metadata = _impl::$s7Structs26StructWithRefcountedMemberVMa(0); +// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; +// CHECK-NEXT: #ifdef __arm64e__ +// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); +// CHECK-NEXT: #else +// CHECK-NEXT: auto *vwTable = *vwTableAddr; +// CHECK-NEXT: #endif +// CHECK-NEXT: vwTable->assignWithCopy(_getOpaquePointer(), const_cast(other._getOpaquePointer()), metadata._0); +// CHECK-NEXT: return *this; +// CHECK-NEXT: } +// CHECK-NEXT: SWIFT_INLINE_THUNK StructWithRefcountedMember &operator =(StructWithRefcountedMember &&other) = delete; // CHECK-NEXT: SWIFT_INLINE_PRIVATE_HELPER StructWithRefcountedMember(StructWithRefcountedMember &&) noexcept { // CHECK-NEXT: swift::_impl::_fatalError_Cxx_move_of_Swift_value_type_not_supported_yet(); // CHECK-NEXT: swift::_impl::_swift_stdlib_reportFatalError("swift", 5, "C++ does not support moving a Swift value yet", 45, 0); diff --git a/test/Interop/SwiftToCxx/structs/swift-struct-in-cxx.swift b/test/Interop/SwiftToCxx/structs/swift-struct-in-cxx.swift index b23a67a8d78a2..5bb67a1b4e06e 100644 --- a/test/Interop/SwiftToCxx/structs/swift-struct-in-cxx.swift +++ b/test/Interop/SwiftToCxx/structs/swift-struct-in-cxx.swift @@ -38,6 +38,18 @@ // CHECK: } // CHECK-NEXT: SWIFT_INLINE_THUNK StructWithIntField(const StructWithIntField &other) noexcept { // CHECK: } +// CHECK: SWIFT_INLINE_THUNK StructWithIntField &operator =(const StructWithIntField &other) noexcept { +// CHECK-NEXT: auto metadata = _impl::$s7Structs18StructWithIntFieldVMa(0); +// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast(metadata._0) - 1; +// CHECK-NEXT: #ifdef __arm64e__ +// CHECK-NEXT: auto *vwTable = reinterpret_cast(ptrauth_auth_data(reinterpret_cast(*vwTableAddr), ptrauth_key_process_independent_data, ptrauth_blend_discriminator(vwTableAddr, 11839))); +// CHECK-NEXT: #else +// CHECK-NEXT: auto *vwTable = *vwTableAddr; +// CHECK-NEXT: #endif +// CHECK-NEXT: vwTable->assignWithCopy(_getOpaquePointer(), const_cast(other._getOpaquePointer()), metadata._0); +// CHECK-NEXT: return *this; +// CHECK-NEXT: } +// CHECK-NEXT: SWIFT_INLINE_THUNK StructWithIntField &operator =(StructWithIntField &&other) = delete; // CHECK-NEXT: noreturn]] SWIFT_INLINE_PRIVATE_HELPER StructWithIntField(StructWithIntField &&) noexcept { // CHECK-NEXT: swift::_impl::_fatalError_Cxx_move_of_Swift_value_type_not_supported_yet(); // CHECK-NEXT: swift::_impl::_swift_stdlib_reportFatalError("swift", 5, "C++ does not support moving a Swift value yet", 45, 0);