From bfc4e5048e495dccab7bb670a7b8773430ac189c Mon Sep 17 00:00:00 2001 From: Gabor Horvath Date: Fri, 28 Jun 2024 15:32:17 +0100 Subject: [PATCH] [cxx-interop] Add new tests for consuming shared foreign reference types Check semantics for functions creating FRTs, and wrapping FRTs. --- ...struct-parameter-back-to-cxx-execution.cpp | 57 +++++++++++++++++-- ...-not-supported-on-foreign-references.swift | 40 +++++++++++++ 2 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 test/Interop/CxxToSwiftToCxx/consuming-not-supported-on-foreign-references.swift diff --git a/test/Interop/CxxToSwiftToCxx/consuming-cxx-struct-parameter-back-to-cxx-execution.cpp b/test/Interop/CxxToSwiftToCxx/consuming-cxx-struct-parameter-back-to-cxx-execution.cpp index 88105d62db56d..ce57d07d8be71 100644 --- a/test/Interop/CxxToSwiftToCxx/consuming-cxx-struct-parameter-back-to-cxx-execution.cpp +++ b/test/Interop/CxxToSwiftToCxx/consuming-cxx-struct-parameter-back-to-cxx-execution.cpp @@ -63,6 +63,8 @@ __attribute__((swift_attr("release:releaseShared"))); inline void retainShared(SharedFRT *r) { puts("retainShared"); } inline void releaseShared(SharedFRT *r) { puts("releaseShared"); } +inline SharedFRT* createSharedFRT() { return new SharedFRT(); } + //--- module.modulemap module CxxTest { header "header.h" @@ -89,20 +91,38 @@ public func consumeImmortalFRT(_ x: consuming ImmortalFRT) { print("immortal frt x \(x.x)") } -public -func consumeSharedFRT(_ x : consuming SharedFRT) { +public func consumeSharedFRT(_ x : consuming SharedFRT) { print("consume shared frt x \(x.x)") } -public -func takeSharedFRT(_ x : SharedFRT) { print("take shared frt x \(x.x)") } +public func takeSharedFRT(_ x : SharedFRT) { + print("take shared frt x \(x.x)") +} + +public func genericConsumingFunc(_ p: consuming T) { + print("generic consuming function") +} -public -func returnSharedFRT(_ x : SharedFRT) -> SharedFRT { +public func returnSharedFRT(_ x : SharedFRT) -> SharedFRT { print("return shared frt x \(x.x)") return x } +public func returnSharedFRT2() -> SharedFRT { + return createSharedFRT() +} + +public struct ValueWrapper { + let sharedFRT: SharedFRT + public init(_ x: SharedFRT) { + self.sharedFRT = x + } +} + +public func consumeValueWrapper(_ x: consuming ValueWrapper) { + print("return shared frt x \(x.sharedFRT.x)") +} + //--- use-swift-cxx-types.cpp #include "header.h" @@ -160,6 +180,31 @@ int main() { SharedFRT *sfrtptr = UseCxx::returnSharedFRT(&sfrt); // CHECK-NEXT: retainShared // CHECK-NEXT: return shared frt x 2 + SharedFRT *sfrtptr2 = UseCxx::returnSharedFRT2(); + // No retain or release here. + } + { + SharedFRT sfrt; + sfrt.x = 4; + auto wrapper = UseCxx::ValueWrapper::init(&sfrt); + // consumeValueWrapper creates a defensive copy in the thunk. + UseCxx::consumeValueWrapper(wrapper); + // CHECK-NEXT: retainShared + // CHECK-NEXT: retainShared + // CHECK-NEXT: releaseShared + // CHECK-NEXT: return shared frt x 4 + // CHECK-NEXT: releaseShared + } + { + SharedFRT sfrt; + sfrt.x = 4; + auto wrapper = UseCxx::ValueWrapper::init(&sfrt); + UseCxx::genericConsumingFunc(wrapper); + // CHECK-NEXT: retainShared + // CHECK-NEXT: retainShared + // CHECK-DAG: releaseShared + // CHECK-DAG: generic consuming function + // CHECK-NEXT: releaseShared } puts("EndOfTest"); // CHECK-NEXT: EndOfTest diff --git a/test/Interop/CxxToSwiftToCxx/consuming-not-supported-on-foreign-references.swift b/test/Interop/CxxToSwiftToCxx/consuming-not-supported-on-foreign-references.swift new file mode 100644 index 0000000000000..01c26e6ff7f5d --- /dev/null +++ b/test/Interop/CxxToSwiftToCxx/consuming-not-supported-on-foreign-references.swift @@ -0,0 +1,40 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-interop-build-clangxx -std=c++20 -c %t/use-swift-cxx-types.cpp -I %t -o %t/swift-cxx-execution.o +// RUN: not %target-interop-build-swift %t/use-cxx-types.swift -o %t/swift-cxx-execution -Xlinker %t/swift-cxx-execution.o -module-name UseCxx -Xfrontend -entry-point-function-name -Xfrontend swiftMain -I %t -O -Xfrontend -disable-availability-checking 2> %t/out + +// RUN: cat %t/out | %FileCheck %s + +//--- header.h + +class SharedFRT { +public: + int x; +} __attribute__((swift_attr("import_reference"))) +__attribute__((swift_attr("retain:retainShared"))) +__attribute__((swift_attr("release:releaseShared"))); + +inline void retainShared(SharedFRT *r) { } +inline void releaseShared(SharedFRT *r) { } + +//--- use-swift-cxx-types.cpp +#include "header.h" + +int main() {} + +//--- module.modulemap +module CxxTest { + header "header.h" + requires cplusplus +} + +//--- use-cxx-types.swift +import CxxTest + +public func consumeSharedFRT(_ x: consuming SharedFRT) {} +public func takeSharedFRT(_ x: SharedFRT) { + consumeSharedFRT(consume x) + // CHECK: error: 'consume' applied to value that the compiler does not support. This is a compiler bug. Please file a bug with a small example of the bug + x.x = 10 +}