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..6f51ce9c4349a --- /dev/null +++ b/test/Interop/C/swiftify-import/import-as-instance-method.swift @@ -0,0 +1,195 @@ +// 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, 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) + 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:_:_:)"))); + +// 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 { + 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) + } +} +------------------------------ 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..ae0e76d6f46a3 --- /dev/null +++ b/test/Interop/Cxx/swiftify-import/import-as-instance-method.swift @@ -0,0 +1,234 @@ +// 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:)"))); + +/* + * 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 {}; + 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_{{.*}}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'))