// RUN: %empty-directory(%t) // RUN: split-file %s %t // RUN: %target-swift-frontend -typecheck %t/use-cxx-types.swift -typecheck -module-name UseCxx -emit-clang-header-path %t/UseCxx.h -I %t -enable-experimental-cxx-interop -clang-header-expose-decls=all-public // RUN: %target-interop-build-clangxx -std=c++20 -c %t/use-swift-cxx-types.cpp -I %t -o %t/swift-cxx-execution.o // RUN: %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 // RUN: %target-codesign %t/swift-cxx-execution // RUN: %target-run %t/swift-cxx-execution | %FileCheck %s // REQUIRES: executable_test //--- header.h #include struct Trivial { int x, y; inline Trivial(int x, int y) : x(x), y(y) {} }; template struct NonTrivialTemplate { T x; inline NonTrivialTemplate(T x) : x(x) { puts("create NonTrivialTemplate"); } inline NonTrivialTemplate(const NonTrivialTemplate &other) : x(other.x) { puts("copy NonTrivialTemplate"); } inline NonTrivialTemplate(NonTrivialTemplate &&other) : x(static_cast(other.x)) { puts("move NonTrivialTemplate"); } inline ~NonTrivialTemplate() { puts("~NonTrivialTemplate"); } inline void testPrint() const { puts("testPrint"); } }; using NonTrivialTemplateTrivial = NonTrivialTemplate; //--- module.modulemap module CxxTest { header "header.h" requires cplusplus } //--- use-cxx-types.swift import CxxTest public func consumeNonTrivial(_ x: consuming NonTrivialTemplateTrivial) -> CInt { print("x and y: \(x.x.x), \(x.x.y)") return x.x.x } public struct TakesNonTrivial { public init(_ x: NonTrivialTemplateTrivial) { self.prop = x } public var prop: NonTrivialTemplateTrivial } //--- use-swift-cxx-types.cpp #include "header.h" #include "UseCxx.h" #include int main() { { auto x = NonTrivialTemplate(Trivial(1, 2)); UseCxx::consumeNonTrivial(x); puts("DoneCall"); } // CHECK: create NonTrivialTemplate // CHECK-NEXT: copy NonTrivialTemplate // CHECK-NEXT: x and y: 1, 2 // CHECK-NEXT: ~NonTrivialTemplate // CHECK-NEXT: DoneCall // CHECK-NEXT: ~NonTrivialTemplate { auto x = NonTrivialTemplate(Trivial(-4, 0)); puts("call"); auto swiftVal = UseCxx::TakesNonTrivial::init(x); puts("DoneCall"); swiftVal.setProp(x); } puts("EndOfTest"); // CHECK-NEXT: create NonTrivialTemplate // CHECK-NEXT: call // CHECK-NEXT: copy NonTrivialTemplate // CHECK-NEXT: copy NonTrivialTemplate // CHECK-NEXT: ~NonTrivialTemplate // CHECK-NEXT: DoneCall // CHECK-NEXT: copy NonTrivialTemplate // CHECK-NEXT: ~NonTrivialTemplate // CHECK-NEXT: copy NonTrivialTemplate // CHECK-NEXT: ~NonTrivialTemplate // CHECK-NEXT: ~NonTrivialTemplate // CHECK-NEXT: ~NonTrivialTemplate // CHECK-NEXT: EndOfTest return 0; }