From 6a9ac22cd280b426f6c1e1454f2e3b5c2769086f Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Sat, 4 Oct 2025 00:40:00 -0700 Subject: [PATCH 1/3] Merge pull request #84507 from hnrklssn/swiftify-import-as-method [Swiftify] Add support for free functions imported as instance methods (cherry picked from commit ed4f058c01734dcc596d8589825e4d365803cd13) --- .../swift/AST/DiagnosticsClangImporter.def | 6 + lib/ClangImporter/ImportDecl.cpp | 64 +++- .../SwiftMacros/SwiftifyImportMacro.swift | 9 +- .../public/Cxx/libstdcxx/libstdcxx.modulemap | 1 + .../import-as-instance-method.swift | 212 ++++++++++++ .../access/swiftify-private-fileid.swift | 3 - .../Cxx/stdlib/std-span-interface.swift | 3 - .../std-span-transformed-execution.swift | 3 - .../Cxx/stdlib/use-std-span-typechecker.swift | 3 - test/Interop/Cxx/stdlib/use-std-span.swift | 3 - .../import-as-instance-method.swift | 310 ++++++++++++++++++ .../Cxx/swiftify-import/span-in-ctor.swift | 3 - .../CxxToSwiftToCxx/span/span-execution.cpp | 3 - test/Interop/lit.local.cfg | 2 + 14 files changed, 593 insertions(+), 32 deletions(-) create mode 100644 test/Interop/C/swiftify-import/import-as-instance-method.swift create mode 100644 test/Interop/Cxx/swiftify-import/import-as-instance-method.swift diff --git a/include/swift/AST/DiagnosticsClangImporter.def b/include/swift/AST/DiagnosticsClangImporter.def index 0bfb808c03dd0..3b21273951b26 100644 --- a/include/swift/AST/DiagnosticsClangImporter.def +++ b/include/swift/AST/DiagnosticsClangImporter.def @@ -100,6 +100,12 @@ GROUPED_WARNING(clang_ignored_sendable_attr, ClangDeclarationImport, none, "cannot be added to it", (Type)) +GROUPED_WARNING(warn_clang_ignored_bounds_on_self, ClangDeclarationImport, none, + "bounds attribute '%0' ignored on parameter mapped to 'self'", + (StringRef)) +NOTE(note_swift_name_instance_method, none, + "swift_name maps free function to instance method here", ()) + WARNING(implicit_bridging_header_imported_from_module,none, "implicit import of bridging header '%0' via module %1 " "is deprecated and will be removed in a later version of Swift", diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index b648c1fafccd4..b4d54cb3e7af6 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -9403,6 +9403,22 @@ void ClangImporter::Implementation::addOptionSetTypealiases( selfType); } +// until CountAttributedType::getAttributeName lands in our LLVM branch +static StringRef getAttributeName(const clang::CountAttributedType *CAT) { + switch (CAT->getKind()) { + case clang::CountAttributedType::CountedBy: + return "__counted_by"; + case clang::CountAttributedType::CountedByOrNull: + return "__counted_by_or_null"; + case clang::CountAttributedType::SizedBy: + return "__sized_by"; + case clang::CountAttributedType::SizedByOrNull: + return "__sized_by_or_null"; + case clang::CountAttributedType::EndedBy: + llvm_unreachable("CountAttributedType cannot be ended_by"); + } +} + void ClangImporter::Implementation::swiftify(AbstractFunctionDecl *MappedDecl) { if (!SwiftContext.LangOpts.hasFeature(Feature::SafeInteropWrappers)) return; @@ -9419,9 +9435,6 @@ void ClangImporter::Implementation::swiftify(AbstractFunctionDecl *MappedDecl) { ClangDecl->getAccess() == clang::AS_private) return; - if (ClangDecl->getNumParams() != MappedDecl->getParameters()->size()) - return; - MacroDecl *SwiftifyImportDecl = dyn_cast_or_null(getKnownSingleDecl(SwiftContext, "_SwiftifyImport")); if (!SwiftifyImportDecl) return; @@ -9478,14 +9491,44 @@ void ClangImporter::Implementation::swiftify(AbstractFunctionDecl *MappedDecl) { true); returnHasLifetimeInfo = true; } + + bool isClangInstanceMethod = + isa(ClangDecl) && + !isa(ClangDecl) && + cast(ClangDecl)->isInstance(); + size_t swiftNumParams = MappedDecl->getParameters()->size() - + (ClangDecl->isVariadic() ? 1 : 0); + ASSERT((MappedDecl->isImportAsInstanceMember() == isClangInstanceMethod) == + (ClangDecl->getNumParams() == swiftNumParams)); + + size_t selfParamIndex = MappedDecl->isImportAsInstanceMember() + ? MappedDecl->getSelfIndex() + : ClangDecl->getNumParams(); for (auto [index, clangParam] : llvm::enumerate(ClangDecl->parameters())) { auto clangParamTy = clangParam->getType(); - auto swiftParam = MappedDecl->getParameters()->get(index); + int mappedIndex = index < selfParamIndex ? index : + index > selfParamIndex ? index - 1 : + SwiftifyInfoPrinter::SELF_PARAM_INDEX; + ParamDecl *swiftParam = nullptr; + if (mappedIndex == SwiftifyInfoPrinter::SELF_PARAM_INDEX) { + swiftParam = MappedDecl->getImplicitSelfDecl(/*createIfNeeded*/true); + } else { + swiftParam = MappedDecl->getParameters()->get(mappedIndex); + } + ASSERT(swiftParam); Type swiftParamTy = swiftParam->getInterfaceType(); bool paramHasBoundsInfo = false; auto *CAT = clangParamTy->getAs(); - if (SwiftifiableCAT(getClangASTContext(), CAT, swiftParamTy)) { - printer.printCountedBy(CAT, index); + if (CAT && mappedIndex == SwiftifyInfoPrinter::SELF_PARAM_INDEX) { + diagnose(HeaderLoc(clangParam->getLocation()), + diag::warn_clang_ignored_bounds_on_self, getAttributeName(CAT)); + auto swiftName = ClangDecl->getAttr(); + ASSERT(swiftName && + "free function mapped to instance method without swift_name??"); + diagnose(HeaderLoc(swiftName->getLocation()), + diag::note_swift_name_instance_method); + } else if (SwiftifiableCAT(getClangASTContext(), CAT, swiftParamTy)) { + printer.printCountedBy(CAT, mappedIndex); attachMacro = paramHasBoundsInfo = true; } bool paramIsStdSpan = registerStdSpanTypeMapping( @@ -9494,14 +9537,16 @@ void ClangImporter::Implementation::swiftify(AbstractFunctionDecl *MappedDecl) { bool paramHasLifetimeInfo = false; if (clangParam->hasAttr()) { - printer.printNonEscaping(index); + printer.printNonEscaping(mappedIndex); paramHasLifetimeInfo = true; } if (clangParam->hasAttr()) { // If this parameter has bounds info we will tranform it into a Span, // so then it will no longer be Escapable. - bool willBeEscapable = swiftParamTy->isEscapable() && !paramHasBoundsInfo; - printer.printLifetimeboundReturn(index, willBeEscapable); + bool willBeEscapable = swiftParamTy->isEscapable() && + (!paramHasBoundsInfo || + mappedIndex == SwiftifyInfoPrinter::SELF_PARAM_INDEX); + printer.printLifetimeboundReturn(mappedIndex, willBeEscapable); paramHasLifetimeInfo = true; returnHasLifetimeInfo = true; } @@ -9512,7 +9557,6 @@ void ClangImporter::Implementation::swiftify(AbstractFunctionDecl *MappedDecl) { attachMacro = true; printer.printAvailability(); printer.printTypeMapping(typeMapping); - } if (attachMacro) { diff --git a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift index 0b83bb130e3c6..3f2a99749f998 100644 --- a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift +++ b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift @@ -468,7 +468,14 @@ struct FunctionCallBuilder: BoundsCheckedThunkBuilder { let functionRef = DeclReferenceExprSyntax(baseName: base.name) let args: [ExprSyntax] = base.signature.parameterClause.parameters.enumerated() .map { (i: Int, param: FunctionParameterSyntax) in - return pointerArgs[i] ?? ExprSyntax("\(param.name)") + if let overrideArg = pointerArgs[i] { + return overrideArg + } + if isInout(getParam(base.signature, i).type) { + return ExprSyntax("&\(param.name)") + } else { + return ExprSyntax("\(param.name)") + } } let labels: [TokenSyntax?] = base.signature.parameterClause.parameters.map { param in let firstName = param.firstName.trimmed diff --git a/stdlib/public/Cxx/libstdcxx/libstdcxx.modulemap b/stdlib/public/Cxx/libstdcxx/libstdcxx.modulemap index 4627ffd22307b..aec95fcd5523c 100644 --- a/stdlib/public/Cxx/libstdcxx/libstdcxx.modulemap +++ b/stdlib/public/Cxx/libstdcxx/libstdcxx.modulemap @@ -42,6 +42,7 @@ module std { header "ostream" header "queue" header "set" + header "span" header "sstream" header "stack" header "stdexcept" diff --git a/test/Interop/C/swiftify-import/import-as-instance-method.swift b/test/Interop/C/swiftify-import/import-as-instance-method.swift new file mode 100644 index 0000000000000..577cf7f122fbe --- /dev/null +++ b/test/Interop/C/swiftify-import/import-as-instance-method.swift @@ -0,0 +1,212 @@ +// REQUIRES: swift_feature_SafeInteropWrappers + +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-swift-frontend -emit-module -plugin-path %swift-plugin-dir -o %t/Test.swiftmodule -I %t%{fs-sep}Inputs -enable-experimental-feature SafeInteropWrappers -strict-memory-safety -verify -verify-additional-file %t%{fs-sep}Inputs%{fs-sep}instance.h %t/test.swift -I %bridging-path -DVERIFY +// RUN: env SWIFT_BACKTRACE="" %target-swift-frontend -emit-module -plugin-path %swift-plugin-dir -o %t/Test.swiftmodule -I %t/Inputs -enable-experimental-feature SafeInteropWrappers -strict-memory-safety -warnings-as-errors -Xcc -Werror %t/test.swift -dump-macro-expansions -I %bridging-path 2> %t/out.txt +// RUN: diff --strip-trailing-cr %t/out.txt %t/out.expected + +//--- test.swift +import Instance + +@available(macOS 13.3.0, *) +func foo(_ p: inout MutableSpan, a: A, aa: inout A, c: C, b: B, bb: inout B) { + aa.basic(&p) + aa.bar(&p) + a.constSelf(&p) + a.valSelf(&p) + let _: MutableSpan = a.lifetimeBoundSelf(3) + c.refSelf(&p) + b.nonescaping(&p) + let _: MutableSpan = bb.nonescapingLifetimebound(73) + +#if VERIFY + aa.countedSelf(&p) + a.basic(&p) // expected-error{{cannot use mutating member on immutable value: 'a' is a 'let' constant}} +#endif +} + +//--- Inputs/instance.h +#include +#include +#include + +struct A {}; +struct SWIFT_NONESCAPABLE B {}; +struct SWIFT_IMMORTAL_REFERENCE C {}; + +void basic(struct A *a, int * __counted_by(len) p __noescape, int len) __attribute__((swift_name("A.basic(self:_:_:)"))); + +void renamed(struct A *a, int * __counted_by(len) p __noescape, int len) __attribute__((swift_name("A.bar(self:_:_:)"))); + +void countedSelf(struct A * __counted_by(len) + a, // expected-warning{{bounds attribute '__counted_by' ignored on parameter mapped to 'self'}} + int * __counted_by(len) p __noescape, int len) + __attribute__(( + swift_name // expected-note{{swift_name maps free function to instance method here}} + ("A.countedSelf(self:_:_:)"))); + +void constSelf(const struct A *a, int * __counted_by(len) p __noescape, int len) __attribute__((swift_name("A.constSelf(self:_:_:)"))); + +void valSelf(struct A a, int * __counted_by(len) p __noescape, int len) __attribute__((swift_name("A.valSelf(self:_:_:)"))); + +void refSelf(struct C *c, int * __counted_by(len) p __noescape, int len) __attribute__((swift_name("C.refSelf(self:_:_:)"))); + +int * __counted_by(len) lifetimeBoundSelf(struct A a __lifetimebound, int len) __attribute__((swift_name("A.lifetimeBoundSelf(self:_:)"))); + +void nonescaping(const struct B *d, int * __counted_by(len) p __noescape, int len) __attribute__((swift_name("B.nonescaping(self:_:_:)"))); + +int * __counted_by(len) nonescapingLifetimebound(struct B *d __lifetimebound, int len) __attribute__((swift_name("B.nonescapingLifetimebound(self:_:)"))); + +//--- Inputs/module.modulemap +module Instance { + header "instance.h" +} + +//--- out.expected +@__swiftmacro_So1AV5basic15_SwiftifyImportfMp_.swift +------------------------------ +/// This is an auto-generated wrapper for safer interop +@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +public mutating func basic(_ p: inout MutableSpan) { + let len = Int32(exactly: p.count)! + return unsafe p.withUnsafeMutableBufferPointer { _pPtr in + return unsafe basic(_pPtr.baseAddress!, len) + } +} +------------------------------ +@__swiftmacro_So5basic15_SwiftifyImportfMp_.swift +------------------------------ +/// This is an auto-generated wrapper for safer interop +@available(swift, obsoleted: 3, renamed: "A.basic(self:_:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +public func basic(_ a: UnsafeMutablePointer!, _ p: inout MutableSpan) { + let len = Int32(exactly: p.count)! + return unsafe p.withUnsafeMutableBufferPointer { _pPtr in + return unsafe basic(a, _pPtr.baseAddress!, len) + } +} +------------------------------ +@__swiftmacro_So1AV3bar15_SwiftifyImportfMp_.swift +------------------------------ +/// This is an auto-generated wrapper for safer interop +@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +public mutating func bar(_ p: inout MutableSpan) { + let len = Int32(exactly: p.count)! + return unsafe p.withUnsafeMutableBufferPointer { _pPtr in + return unsafe bar(_pPtr.baseAddress!, len) + } +} +------------------------------ +@__swiftmacro_So7renamed15_SwiftifyImportfMp_.swift +------------------------------ +/// This is an auto-generated wrapper for safer interop +@available(swift, obsoleted: 3, renamed: "A.bar(self:_:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +public func renamed(_ a: UnsafeMutablePointer!, _ p: inout MutableSpan) { + let len = Int32(exactly: p.count)! + return unsafe p.withUnsafeMutableBufferPointer { _pPtr in + return unsafe renamed(a, _pPtr.baseAddress!, len) + } +} +------------------------------ +@__swiftmacro_So1AV9constSelf15_SwiftifyImportfMp_.swift +------------------------------ +/// This is an auto-generated wrapper for safer interop +@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +public func constSelf(_ p: inout MutableSpan) { + let len = Int32(exactly: p.count)! + return unsafe p.withUnsafeMutableBufferPointer { _pPtr in + return unsafe constSelf(_pPtr.baseAddress!, len) + } +} +------------------------------ +@__swiftmacro_So9constSelf15_SwiftifyImportfMp_.swift +------------------------------ +/// This is an auto-generated wrapper for safer interop +@available(swift, obsoleted: 3, renamed: "A.constSelf(self:_:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +public func constSelf(_ a: UnsafePointer!, _ p: inout MutableSpan) { + let len = Int32(exactly: p.count)! + return unsafe p.withUnsafeMutableBufferPointer { _pPtr in + return unsafe constSelf(a, _pPtr.baseAddress!, len) + } +} +------------------------------ +@__swiftmacro_So1AV7valSelf15_SwiftifyImportfMp_.swift +------------------------------ +/// This is an auto-generated wrapper for safer interop +@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +public func valSelf(_ p: inout MutableSpan) { + let len = Int32(exactly: p.count)! + return unsafe p.withUnsafeMutableBufferPointer { _pPtr in + return unsafe valSelf(_pPtr.baseAddress!, len) + } +} +------------------------------ +@__swiftmacro_So7valSelf15_SwiftifyImportfMp_.swift +------------------------------ +/// This is an auto-generated wrapper for safer interop +@available(swift, obsoleted: 3, renamed: "A.valSelf(self:_:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +public func valSelf(_ a: A, _ p: inout MutableSpan) { + let len = Int32(exactly: p.count)! + return unsafe p.withUnsafeMutableBufferPointer { _pPtr in + return unsafe valSelf(a, _pPtr.baseAddress!, len) + } +} +------------------------------ +@__swiftmacro_So1AV17lifetimeBoundSelf15_SwiftifyImportfMp_.swift +------------------------------ +/// This is an auto-generated wrapper for safer interop +@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(borrow self) @_disfavoredOverload +public func lifetimeBoundSelf(_ len: Int32) -> MutableSpan { + return unsafe _swiftifyOverrideLifetime(MutableSpan(_unsafeStart: unsafe lifetimeBoundSelf(len), count: Int(len)), copying: ()) +} +------------------------------ +@__swiftmacro_So17lifetimeBoundSelf15_SwiftifyImportfMp_.swift +------------------------------ +/// This is an auto-generated wrapper for safer interop +@available(swift, obsoleted: 3, renamed: "A.lifetimeBoundSelf(self:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(borrow a) @_disfavoredOverload +public func lifetimeBoundSelf(_ a: A, _ len: Int32) -> MutableSpan { + return unsafe _swiftifyOverrideLifetime(MutableSpan(_unsafeStart: unsafe lifetimeBoundSelf(a, len), count: Int(len)), copying: ()) +} +------------------------------ +@__swiftmacro_So1CV7refSelf15_SwiftifyImportfMp_.swift +------------------------------ +/// This is an auto-generated wrapper for safer interop +@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +public func refSelf(_ p: inout MutableSpan) { + let len = Int32(exactly: p.count)! + return unsafe p.withUnsafeMutableBufferPointer { _pPtr in + return unsafe refSelf(_pPtr.baseAddress!, len) + } +} +------------------------------ +@__swiftmacro_So7refSelf15_SwiftifyImportfMp_.swift +------------------------------ +/// This is an auto-generated wrapper for safer interop +@available(swift, obsoleted: 3, renamed: "C.refSelf(self:_:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +public func refSelf(_ c: C!, _ p: inout MutableSpan) { + let len = Int32(exactly: p.count)! + return unsafe p.withUnsafeMutableBufferPointer { _pPtr in + return unsafe refSelf(c, _pPtr.baseAddress!, len) + } +} +------------------------------ +@__swiftmacro_So1BV11nonescaping15_SwiftifyImportfMp_.swift +------------------------------ +/// This is an auto-generated wrapper for safer interop +@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +public func nonescaping(_ p: inout MutableSpan) { + let len = Int32(exactly: p.count)! + return unsafe p.withUnsafeMutableBufferPointer { _pPtr in + return unsafe nonescaping(_pPtr.baseAddress!, len) + } +} +------------------------------ +@__swiftmacro_So1BV24nonescapingLifetimebound15_SwiftifyImportfMp_.swift +------------------------------ +/// This is an auto-generated wrapper for safer interop +@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(copy self) @_disfavoredOverload +public mutating func nonescapingLifetimebound(_ len: Int32) -> MutableSpan { + return unsafe _swiftifyOverrideLifetime(MutableSpan(_unsafeStart: unsafe nonescapingLifetimebound(len), count: Int(len)), copying: ()) +} +------------------------------ diff --git a/test/Interop/Cxx/class/access/swiftify-private-fileid.swift b/test/Interop/Cxx/class/access/swiftify-private-fileid.swift index 020295d8f8d8b..cd12684535fd3 100644 --- a/test/Interop/Cxx/class/access/swiftify-private-fileid.swift +++ b/test/Interop/Cxx/class/access/swiftify-private-fileid.swift @@ -5,9 +5,6 @@ // REQUIRES: swift_feature_SafeInteropWrappers -// FIXME swift-ci linux tests do not support std::span -// UNSUPPORTED: OS=linux-gnu, OS=linux-android, OS=linux-androideabi - //--- Inputs/swiftify-non-public.h #pragma once diff --git a/test/Interop/Cxx/stdlib/std-span-interface.swift b/test/Interop/Cxx/stdlib/std-span-interface.swift index 0cf298f6b63f2..680cb5adb16a0 100644 --- a/test/Interop/Cxx/stdlib/std-span-interface.swift +++ b/test/Interop/Cxx/stdlib/std-span-interface.swift @@ -8,9 +8,6 @@ // REQUIRES: swift_feature_SafeInteropWrappers // REQUIRES: swift_feature_Lifetimes -// FIXME swift-ci linux tests do not support std::span -// UNSUPPORTED: OS=linux-gnu, OS=linux-android, OS=linux-androideabi - #if !BRIDGING_HEADER import StdSpan #endif diff --git a/test/Interop/Cxx/stdlib/std-span-transformed-execution.swift b/test/Interop/Cxx/stdlib/std-span-transformed-execution.swift index a1ada02cb4dff..aac46b5afa75b 100644 --- a/test/Interop/Cxx/stdlib/std-span-transformed-execution.swift +++ b/test/Interop/Cxx/stdlib/std-span-transformed-execution.swift @@ -1,8 +1,5 @@ // RUN: %target-run-simple-swift(-plugin-path %swift-plugin-dir -I %S/Inputs -Xfrontend -enable-experimental-cxx-interop -swift-version 6 -Xfrontend -disable-availability-checking -Xcc -std=c++20 -enable-experimental-feature LifetimeDependence -enable-experimental-feature SafeInteropWrappers) -// FIXME swift-ci linux tests do not support std::span -// UNSUPPORTED: OS=linux-gnu - // TODO: test failed in Windows PR testing: rdar://144384453 // UNSUPPORTED: OS=windows-msvc diff --git a/test/Interop/Cxx/stdlib/use-std-span-typechecker.swift b/test/Interop/Cxx/stdlib/use-std-span-typechecker.swift index 51b6444ea1921..bf173f868ca4c 100644 --- a/test/Interop/Cxx/stdlib/use-std-span-typechecker.swift +++ b/test/Interop/Cxx/stdlib/use-std-span-typechecker.swift @@ -1,8 +1,5 @@ // RUN: %target-typecheck-verify-swift -I %S/Inputs -enable-experimental-cxx-interop -Xcc -std=c++20 2>&1 -// FIXME swift-ci linux tests do not support std::span -// UNSUPPORTED: OS=linux-gnu - import StdSpan let arr: [Int32] = [1, 2, 3] diff --git a/test/Interop/Cxx/stdlib/use-std-span.swift b/test/Interop/Cxx/stdlib/use-std-span.swift index 89644de5a9d90..478be72399651 100644 --- a/test/Interop/Cxx/stdlib/use-std-span.swift +++ b/test/Interop/Cxx/stdlib/use-std-span.swift @@ -1,9 +1,6 @@ // RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-experimental-cxx-interop -Xcc -std=c++20) // RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-experimental-cxx-interop -Xcc -std=c++20 -Xcc -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG) -// FIXME swift-ci linux tests do not support std::span -// UNSUPPORTED: OS=linux-gnu - // TODO: test failed in Windows PR testing: rdar://144384453 // UNSUPPORTED: OS=windows-msvc diff --git a/test/Interop/Cxx/swiftify-import/import-as-instance-method.swift b/test/Interop/Cxx/swiftify-import/import-as-instance-method.swift new file mode 100644 index 0000000000000..b9406f0d3e0d8 --- /dev/null +++ b/test/Interop/Cxx/swiftify-import/import-as-instance-method.swift @@ -0,0 +1,310 @@ +// REQUIRES: swift_feature_SafeInteropWrappers + +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-swift-frontend -emit-module -plugin-path %swift-plugin-dir -o %t/Test.swiftmodule -I %t/Inputs -enable-experimental-feature SafeInteropWrappers -strict-memory-safety -warnings-as-errors -Xcc -Werror %t/test.swift -cxx-interoperability-mode=default -Xcc -std=c++20 -verify -verify-additional-file %t/Inputs/instance.h -DVERIFY +// RUN: env SWIFT_BACKTRACE="" %target-swift-frontend -emit-module -plugin-path %swift-plugin-dir -o %t/Test.swiftmodule -I %t/Inputs -enable-experimental-feature SafeInteropWrappers -strict-memory-safety -warnings-as-errors -Xcc -Werror %t/test.swift -cxx-interoperability-mode=default -Xcc -std=c++20 -dump-macro-expansions 2>&1 | %FileCheck %s --match-full-lines --strict-whitespace --implicit-check-not __swiftmacro + +//--- test.swift +import Instance + +func foo(_ p: inout MutableSpan, a: A, aa: inout A, s: IntSpan, cs: ConstIntSpan, asp: AliasingSpan, b: inout baz.B) { + aa.basic(&p) + aa.bar(&p) + a.constSelf(&p) + a.valSelf(&p) + aa.refSelf(&p) + aa.namespaced(&p) + b.decapseman(&p) + baz.bar(&aa, &p) + baz.this(&aa, &p) + + let _: IntSpan = unsafe s.spanSelf() + let _: MutableSpan = unsafe s.spanSelf() + let _: IntSpan = unsafe s.spanConstSelf() + let _: MutableSpan = unsafe s.spanConstSelf() + let _: ConstIntSpan = unsafe cs.constSpanSelf() + let _: Span = unsafe cs.constSpanSelf() + let _: IntSpan = unsafe asp.spanSelf() + let _: MutableSpan = unsafe asp.spanSelf() +#if VERIFY + p.spanSelf() // expected-error{{value of type 'MutableSpan' (aka 'MutableSpan') has no member 'spanSelf'}} +#endif +} + +//--- Inputs/instance.h +#include +#include +#include + +struct A {}; + +using IntSpan = std::span; +using ConstIntSpan = std::span; +using AliasingSpan = std::span; + +void basic(A *a, IntSpan p __noescape) __attribute__((swift_name("A.basic(self:_:)"))); + +void renamed(A *a, IntSpan p __noescape) __attribute__((swift_name("A.bar(self:_:)"))); + +void constSelf(const A *a, IntSpan p __noescape) __attribute__((swift_name("A.constSelf(self:_:)"))); + +void valSelf(A a, IntSpan p __noescape) __attribute__((swift_name("A.valSelf(self:_:)"))); + +void refSelf(A &a, IntSpan p __noescape) __attribute__((swift_name("A.refSelf(self:_:)"))); + +IntSpan spanSelf(IntSpan p __lifetimebound) __attribute__((swift_name("IntSpan.spanSelf(self:)"))); + +const IntSpan spanConstSelf(const IntSpan p __lifetimebound) __attribute__((swift_name("IntSpan.spanConstSelf(self:)"))); + +ConstIntSpan constSpanSelf(ConstIntSpan p __lifetimebound) __attribute__((swift_name("ConstIntSpan.constSpanSelf(self:)"))); + +namespace baz { + void namespaced(A *a, IntSpan p __noescape) __attribute__((swift_name("A.namespaced(self:_:)"))); + struct B {}; + void renamed(A &a, IntSpan p __noescape) __attribute__((swift_name("baz.bar(_:_:)"))); + void that(A &a, IntSpan p __noescape) __attribute__((swift_name("this(_:_:)"))); +} + +void decapseman(baz::B *b, IntSpan p __noescape) __attribute__((swift_name("baz.B.decapseman(self:_:)"))); + +//--- Inputs/module.modulemap +module Instance { + header "instance.h" + export * +} + +//--- out.expected +// CHECK:@__swiftmacro_{{.*}}basic{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public mutating func basic(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe basic(IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}basic{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@available(swift, obsoleted: 3, renamed: "A.basic(self:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public func basic(_ a: UnsafeMutablePointer!, _ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe basic(a, IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}bar{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public mutating func bar(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe bar(IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}renamed{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@available(swift, obsoleted: 3, renamed: "A.bar(self:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public func renamed(_ a: UnsafeMutablePointer!, _ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe renamed(a, IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}constSelf{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public func constSelf(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe constSelf(IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}constSelf{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@available(swift, obsoleted: 3, renamed: "A.constSelf(self:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public func constSelf(_ a: UnsafePointer!, _ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe constSelf(a, IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}valSelf{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public func valSelf(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe valSelf(IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}valSelf{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@available(swift, obsoleted: 3, renamed: "A.valSelf(self:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public func valSelf(_ a: A, _ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe valSelf(a, IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}refSelf{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public mutating func refSelf(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe refSelf(IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}refSelf{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@available(swift, obsoleted: 3, renamed: "A.refSelf(self:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public func refSelf(_ a: inout A, _ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe refSelf(&a, IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}namespaced{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public mutating func namespaced(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe namespaced(IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}baz{{.*}}namespaced{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@available(swift, obsoleted: 3, renamed: "A.namespaced(self:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT: public static func namespaced(_ a: UnsafeMutablePointer!, _ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe namespaced(a, IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}baz{{.*}}Instance{{.*}}decapseman{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public mutating func decapseman(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe decapseman(IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}decapseman{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@available(swift, obsoleted: 3, renamed: "baz.B.decapseman(self:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public func decapseman(_ b: UnsafeMutablePointer!, _ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe decapseman(b, IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}baz{{.*}}Instance{{.*}}bar{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public static func bar(_ a: inout A, _ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe bar(&a, IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}baz{{.*}}renamed{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@available(swift, obsoleted: 3, renamed: "baz.bar(_:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT: public static func renamed(_ a: inout A, _ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe renamed(&a, IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}baz{{.*}}this{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public static func this(_ a: inout A, _ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe this(&a, IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}baz{{.*}}that{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@available(swift, obsoleted: 3, renamed: "this(_:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT: public static func that(_ a: inout A, _ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe that(&a, IntSpan(_pPtr)) +// CHECK-NEXT: } +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}Instance{{.*}}spanSelf{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(borrow self) @_disfavoredOverload +// CHECK-NEXT:public func spanSelf() -> MutableSpan { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(MutableSpan(_unsafeCxxSpan: unsafe spanSelf()), copying: ()) +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_So8spanSelf{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@available(swift, obsoleted: 3, renamed: "IntSpan.spanSelf(self:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(copy p) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public func spanSelf(_ p: inout MutableSpan) -> MutableSpan { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(MutableSpan(_unsafeCxxSpan: unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe spanSelf(IntSpan(_pPtr)) +// CHECK-NEXT: }), copying: ()) +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}Instance{{.*}}spanConstSelf{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(borrow self) @_disfavoredOverload +// CHECK-NEXT:public func spanConstSelf() -> MutableSpan { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(MutableSpan(_unsafeCxxSpan: unsafe spanConstSelf()), copying: ()) +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}spanConstSelf{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@available(swift, obsoleted: 3, renamed: "IntSpan.spanConstSelf(self:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(copy p) @_lifetime(p: copy p) @_disfavoredOverload +// CHECK-NEXT:public func spanConstSelf(_ p: inout MutableSpan) -> MutableSpan { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(MutableSpan(_unsafeCxxSpan: unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe spanConstSelf(IntSpan(_pPtr)) +// CHECK-NEXT: }), copying: ()) +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}Instance{{.*}}constSpanSelf{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(borrow self) @_disfavoredOverload +// CHECK-NEXT:public func constSpanSelf() -> Span { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(Span(_unsafeCxxSpan: unsafe constSpanSelf()), copying: ()) +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:@__swiftmacro_{{.*}}constSpanSelf{{.*}}_SwiftifyImportfMp_.swift +// CHECK-NEXT:------------------------------ +// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop +// CHECK-NEXT:@available(swift, obsoleted: 3, renamed: "ConstIntSpan.constSpanSelf(self:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(copy p) @_disfavoredOverload +// CHECK-NEXT:public func constSpanSelf(_ p: Span) -> Span { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(Span(_unsafeCxxSpan: unsafe constSpanSelf(ConstIntSpan(p))), copying: ()) +// CHECK-NEXT:} +// CHECK-NEXT:------------------------------ diff --git a/test/Interop/Cxx/swiftify-import/span-in-ctor.swift b/test/Interop/Cxx/swiftify-import/span-in-ctor.swift index 7e824cd0ea9ec..d138152bb06b1 100644 --- a/test/Interop/Cxx/swiftify-import/span-in-ctor.swift +++ b/test/Interop/Cxx/swiftify-import/span-in-ctor.swift @@ -1,8 +1,5 @@ // REQUIRES: swift_feature_SafeInteropWrappers -// FIXME swift-ci linux tests do not support std::span -// UNSUPPORTED: OS=linux-gnu, OS=linux-android, OS=linux-androideabi - // RUN: rm -rf %t // RUN: split-file %s %t // RUN: %target-swift-frontend -c -plugin-path %swift-plugin-dir -I %t/Inputs -Xcc -std=c++20 -cxx-interoperability-mode=default -enable-experimental-feature SafeInteropWrappers %t/method.swift -dump-macro-expansions -verify 2>&1 | %FileCheck %s diff --git a/test/Interop/CxxToSwiftToCxx/span/span-execution.cpp b/test/Interop/CxxToSwiftToCxx/span/span-execution.cpp index 06864db50f3c3..d087c08d4a463 100644 --- a/test/Interop/CxxToSwiftToCxx/span/span-execution.cpp +++ b/test/Interop/CxxToSwiftToCxx/span/span-execution.cpp @@ -9,9 +9,6 @@ // RUN: %target-codesign %t/swift-cxx-execution // RUN: %target-run %t/swift-cxx-execution | %FileCheck %s -// FIXME swift-ci linux tests do not support std::span -// UNSUPPORTED: OS=linux-gnu - // REQUIRES: executable_test //--- header.h diff --git a/test/Interop/lit.local.cfg b/test/Interop/lit.local.cfg index 26efb7ec1ea2a..19f28f614bc46 100644 --- a/test/Interop/lit.local.cfg +++ b/test/Interop/lit.local.cfg @@ -68,3 +68,5 @@ config.substitutions.insert(0, (r'%check-interop-cxx-header-in-clang\(([^)]+)\)' config.substitutions.insert(0, (r'%check-interop-c-header-in-clang\(([^)]+)\)', SubstituteCaptures(r'%check-c-header-in-clang -std=c99 -Wno-padded -Wno-c11-extensions -Wno-pre-c11-compat \1 && ' r'%check-c-header-in-clang -std=c11 -Wno-padded -Wno-pre-c11-compat \1'))) + +config.substitutions.insert(0, ('%bridging-path', '%swift_src_root%{fs-sep}lib%{fs-sep}ClangImporter%{fs-sep}SwiftBridging')) From d983f30cd38bf7080f3b75d5910adc9b50a2007a Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Wed, 8 Oct 2025 00:30:28 -0700 Subject: [PATCH 2/3] comment test cases unsupported in Swift 6.2 --- .../import-as-instance-method.swift | 31 ++---- .../import-as-instance-method.swift | 94 ++----------------- 2 files changed, 16 insertions(+), 109 deletions(-) diff --git a/test/Interop/C/swiftify-import/import-as-instance-method.swift b/test/Interop/C/swiftify-import/import-as-instance-method.swift index 577cf7f122fbe..a79906469b27b 100644 --- a/test/Interop/C/swiftify-import/import-as-instance-method.swift +++ b/test/Interop/C/swiftify-import/import-as-instance-method.swift @@ -11,15 +11,15 @@ import Instance @available(macOS 13.3.0, *) -func foo(_ p: inout MutableSpan, a: A, aa: inout A, c: C, b: B, bb: inout B) { +func foo(_ p: inout MutableSpan, a: A, aa: inout A, c: C/*, b: B, bb: inout B*/) { aa.basic(&p) aa.bar(&p) a.constSelf(&p) a.valSelf(&p) let _: MutableSpan = a.lifetimeBoundSelf(3) c.refSelf(&p) - b.nonescaping(&p) - let _: MutableSpan = bb.nonescapingLifetimebound(73) + //b.nonescaping(&p) + //let _: MutableSpan = bb.nonescapingLifetimebound(73) #if VERIFY aa.countedSelf(&p) @@ -55,9 +55,11 @@ void refSelf(struct C *c, int * __counted_by(len) p __noescape, int len) __attri int * __counted_by(len) lifetimeBoundSelf(struct A a __lifetimebound, int len) __attribute__((swift_name("A.lifetimeBoundSelf(self:_:)"))); -void nonescaping(const struct B *d, int * __counted_by(len) p __noescape, int len) __attribute__((swift_name("B.nonescaping(self:_:_:)"))); +//void nonescaping(const struct B *d, int * __counted_by(len) p __noescape, int len) __attribute__((swift_name("B.nonescaping(self:_:_:)"))); -int * __counted_by(len) nonescapingLifetimebound(struct B *d __lifetimebound, int len) __attribute__((swift_name("B.nonescapingLifetimebound(self:_:)"))); +// Swift 6.2 error: a mutating method cannot have a ~Escapable 'self' +// requires https://github.com/swiftlang/swift/pull/84010 +//int * __counted_by(len) nonescapingLifetimebound(struct B *d __lifetimebound, int len) __attribute__((swift_name("B.nonescapingLifetimebound(self:_:)"))); //--- Inputs/module.modulemap module Instance { @@ -191,22 +193,3 @@ public func refSelf(_ c: C!, _ p: inout MutableSpan) { } } ------------------------------ -@__swiftmacro_So1BV11nonescaping15_SwiftifyImportfMp_.swift ------------------------------- -/// This is an auto-generated wrapper for safer interop -@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload -public func nonescaping(_ p: inout MutableSpan) { - let len = Int32(exactly: p.count)! - return unsafe p.withUnsafeMutableBufferPointer { _pPtr in - return unsafe nonescaping(_pPtr.baseAddress!, len) - } -} ------------------------------- -@__swiftmacro_So1BV24nonescapingLifetimebound15_SwiftifyImportfMp_.swift ------------------------------- -/// This is an auto-generated wrapper for safer interop -@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(copy self) @_disfavoredOverload -public mutating func nonescapingLifetimebound(_ len: Int32) -> MutableSpan { - return unsafe _swiftifyOverrideLifetime(MutableSpan(_unsafeStart: unsafe nonescapingLifetimebound(len), count: Int(len)), copying: ()) -} ------------------------------- diff --git a/test/Interop/Cxx/swiftify-import/import-as-instance-method.swift b/test/Interop/Cxx/swiftify-import/import-as-instance-method.swift index b9406f0d3e0d8..ae0e76d6f46a3 100644 --- a/test/Interop/Cxx/swiftify-import/import-as-instance-method.swift +++ b/test/Interop/Cxx/swiftify-import/import-as-instance-method.swift @@ -9,16 +9,16 @@ //--- test.swift import Instance -func foo(_ p: inout MutableSpan, a: A, aa: inout A, s: IntSpan, cs: ConstIntSpan, asp: AliasingSpan, b: inout baz.B) { +func foo(_ p: inout MutableSpan, a: A, aa: inout A, s: IntSpan, cs: ConstIntSpan, asp: AliasingSpan/*, b: inout baz.B*/) { aa.basic(&p) aa.bar(&p) a.constSelf(&p) a.valSelf(&p) aa.refSelf(&p) - aa.namespaced(&p) - b.decapseman(&p) - baz.bar(&aa, &p) - baz.this(&aa, &p) + //aa.namespaced(&p) + //b.decapseman(&p) + //baz.bar(&aa, &p) + //baz.this(&aa, &p) let _: IntSpan = unsafe s.spanSelf() let _: MutableSpan = unsafe s.spanSelf() @@ -60,6 +60,9 @@ const IntSpan spanConstSelf(const IntSpan p __lifetimebound) __attribute__((swif ConstIntSpan constSpanSelf(ConstIntSpan p __lifetimebound) __attribute__((swift_name("ConstIntSpan.constSpanSelf(self:)"))); +/* + * Swift 6.2 error: 'swift_name' attribute has invalid identifier for the base name. + * Requires https://github.com/llvm/llvm-project/pull/145947 namespace baz { void namespaced(A *a, IntSpan p __noescape) __attribute__((swift_name("A.namespaced(self:_:)"))); struct B {}; @@ -68,6 +71,7 @@ namespace baz { } void decapseman(baz::B *b, IntSpan p __noescape) __attribute__((swift_name("baz.B.decapseman(self:_:)"))); +*/ //--- Inputs/module.modulemap module Instance { @@ -176,86 +180,6 @@ module Instance { // CHECK-NEXT: } // CHECK-NEXT:} // CHECK-NEXT:------------------------------ -// CHECK-NEXT:@__swiftmacro_{{.*}}namespaced{{.*}}_SwiftifyImportfMp_.swift -// CHECK-NEXT:------------------------------ -// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop -// CHECK-NEXT:@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload -// CHECK-NEXT:public mutating func namespaced(_ p: inout MutableSpan) { -// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in -// CHECK-NEXT: return unsafe namespaced(IntSpan(_pPtr)) -// CHECK-NEXT: } -// CHECK-NEXT:} -// CHECK-NEXT:------------------------------ -// CHECK-NEXT:@__swiftmacro_{{.*}}baz{{.*}}namespaced{{.*}}_SwiftifyImportfMp_.swift -// CHECK-NEXT:------------------------------ -// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop -// CHECK-NEXT:@available(swift, obsoleted: 3, renamed: "A.namespaced(self:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload -// CHECK-NEXT: public static func namespaced(_ a: UnsafeMutablePointer!, _ p: inout MutableSpan) { -// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in -// CHECK-NEXT: return unsafe namespaced(a, IntSpan(_pPtr)) -// CHECK-NEXT: } -// CHECK-NEXT:} -// CHECK-NEXT:------------------------------ -// CHECK-NEXT:@__swiftmacro_{{.*}}baz{{.*}}Instance{{.*}}decapseman{{.*}}_SwiftifyImportfMp_.swift -// CHECK-NEXT:------------------------------ -// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop -// CHECK-NEXT:@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload -// CHECK-NEXT:public mutating func decapseman(_ p: inout MutableSpan) { -// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in -// CHECK-NEXT: return unsafe decapseman(IntSpan(_pPtr)) -// CHECK-NEXT: } -// CHECK-NEXT:} -// CHECK-NEXT:------------------------------ -// CHECK-NEXT:@__swiftmacro_{{.*}}decapseman{{.*}}_SwiftifyImportfMp_.swift -// CHECK-NEXT:------------------------------ -// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop -// CHECK-NEXT:@available(swift, obsoleted: 3, renamed: "baz.B.decapseman(self:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload -// CHECK-NEXT:public func decapseman(_ b: UnsafeMutablePointer!, _ p: inout MutableSpan) { -// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in -// CHECK-NEXT: return unsafe decapseman(b, IntSpan(_pPtr)) -// CHECK-NEXT: } -// CHECK-NEXT:} -// CHECK-NEXT:------------------------------ -// CHECK-NEXT:@__swiftmacro_{{.*}}baz{{.*}}Instance{{.*}}bar{{.*}}_SwiftifyImportfMp_.swift -// CHECK-NEXT:------------------------------ -// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop -// CHECK-NEXT:@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload -// CHECK-NEXT:public static func bar(_ a: inout A, _ p: inout MutableSpan) { -// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in -// CHECK-NEXT: return unsafe bar(&a, IntSpan(_pPtr)) -// CHECK-NEXT: } -// CHECK-NEXT:} -// CHECK-NEXT:------------------------------ -// CHECK-NEXT:@__swiftmacro_{{.*}}baz{{.*}}renamed{{.*}}_SwiftifyImportfMp_.swift -// CHECK-NEXT:------------------------------ -// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop -// CHECK-NEXT:@available(swift, obsoleted: 3, renamed: "baz.bar(_:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload -// CHECK-NEXT: public static func renamed(_ a: inout A, _ p: inout MutableSpan) { -// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in -// CHECK-NEXT: return unsafe renamed(&a, IntSpan(_pPtr)) -// CHECK-NEXT: } -// CHECK-NEXT:} -// CHECK-NEXT:------------------------------ -// CHECK-NEXT:@__swiftmacro_{{.*}}baz{{.*}}this{{.*}}_SwiftifyImportfMp_.swift -// CHECK-NEXT:------------------------------ -// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop -// CHECK-NEXT:@_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload -// CHECK-NEXT:public static func this(_ a: inout A, _ p: inout MutableSpan) { -// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in -// CHECK-NEXT: return unsafe this(&a, IntSpan(_pPtr)) -// CHECK-NEXT: } -// CHECK-NEXT:} -// CHECK-NEXT:------------------------------ -// CHECK-NEXT:@__swiftmacro_{{.*}}baz{{.*}}that{{.*}}_SwiftifyImportfMp_.swift -// CHECK-NEXT:------------------------------ -// CHECK-NEXT:/// This is an auto-generated wrapper for safer interop -// CHECK-NEXT:@available(swift, obsoleted: 3, renamed: "this(_:_:)") @_alwaysEmitIntoClient @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @_lifetime(p: copy p) @_disfavoredOverload -// CHECK-NEXT: public static func that(_ a: inout A, _ p: inout MutableSpan) { -// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in -// CHECK-NEXT: return unsafe that(&a, IntSpan(_pPtr)) -// CHECK-NEXT: } -// CHECK-NEXT:} -// CHECK-NEXT:------------------------------ // CHECK-NEXT:@__swiftmacro_{{.*}}Instance{{.*}}spanSelf{{.*}}_SwiftifyImportfMp_.swift // CHECK-NEXT:------------------------------ // CHECK-NEXT:/// This is an auto-generated wrapper for safer interop From d1dbf8e3bb4d682757d359ab6893ab31b95757b0 Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Wed, 8 Oct 2025 09:26:01 -0700 Subject: [PATCH 3/3] complete availability --- test/Interop/C/swiftify-import/import-as-instance-method.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Interop/C/swiftify-import/import-as-instance-method.swift b/test/Interop/C/swiftify-import/import-as-instance-method.swift index a79906469b27b..6f51ce9c4349a 100644 --- a/test/Interop/C/swiftify-import/import-as-instance-method.swift +++ b/test/Interop/C/swiftify-import/import-as-instance-method.swift @@ -10,7 +10,7 @@ //--- test.swift import Instance -@available(macOS 13.3.0, *) +@available(macOS 13.3, iOS 16.4, watchOS 9.4, tvOS 16.4, *) func foo(_ p: inout MutableSpan, a: A, aa: inout A, c: C/*, b: B, bb: inout B*/) { aa.basic(&p) aa.bar(&p)