Merge pull request #84755 from hnrklssn/cherry-pick-swiftify-import-as-method-6.2

Cherry-pick [6.2] [Swiftify] Add support for free functions imported as instance methods
This commit is contained in:
Henrik G. Olsson
2025-10-10 11:00:06 -07:00
committed by GitHub
14 changed files with 500 additions and 32 deletions

View File

@@ -100,6 +100,12 @@ GROUPED_WARNING(clang_ignored_sendable_attr, ClangDeclarationImport, none,
"cannot be added to it", "cannot be added to it",
(Type)) (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, WARNING(implicit_bridging_header_imported_from_module,none,
"implicit import of bridging header '%0' via module %1 " "implicit import of bridging header '%0' via module %1 "
"is deprecated and will be removed in a later version of Swift", "is deprecated and will be removed in a later version of Swift",

View File

@@ -9403,6 +9403,22 @@ void ClangImporter::Implementation::addOptionSetTypealiases(
selfType); 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) { void ClangImporter::Implementation::swiftify(AbstractFunctionDecl *MappedDecl) {
if (!SwiftContext.LangOpts.hasFeature(Feature::SafeInteropWrappers)) if (!SwiftContext.LangOpts.hasFeature(Feature::SafeInteropWrappers))
return; return;
@@ -9419,9 +9435,6 @@ void ClangImporter::Implementation::swiftify(AbstractFunctionDecl *MappedDecl) {
ClangDecl->getAccess() == clang::AS_private) ClangDecl->getAccess() == clang::AS_private)
return; return;
if (ClangDecl->getNumParams() != MappedDecl->getParameters()->size())
return;
MacroDecl *SwiftifyImportDecl = dyn_cast_or_null<MacroDecl>(getKnownSingleDecl(SwiftContext, "_SwiftifyImport")); MacroDecl *SwiftifyImportDecl = dyn_cast_or_null<MacroDecl>(getKnownSingleDecl(SwiftContext, "_SwiftifyImport"));
if (!SwiftifyImportDecl) if (!SwiftifyImportDecl)
return; return;
@@ -9478,14 +9491,44 @@ void ClangImporter::Implementation::swiftify(AbstractFunctionDecl *MappedDecl) {
true); true);
returnHasLifetimeInfo = true; returnHasLifetimeInfo = true;
} }
bool isClangInstanceMethod =
isa<clang::CXXMethodDecl>(ClangDecl) &&
!isa<clang::CXXConstructorDecl>(ClangDecl) &&
cast<clang::CXXMethodDecl>(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())) { for (auto [index, clangParam] : llvm::enumerate(ClangDecl->parameters())) {
auto clangParamTy = clangParam->getType(); 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(); Type swiftParamTy = swiftParam->getInterfaceType();
bool paramHasBoundsInfo = false; bool paramHasBoundsInfo = false;
auto *CAT = clangParamTy->getAs<clang::CountAttributedType>(); auto *CAT = clangParamTy->getAs<clang::CountAttributedType>();
if (SwiftifiableCAT(getClangASTContext(), CAT, swiftParamTy)) { if (CAT && mappedIndex == SwiftifyInfoPrinter::SELF_PARAM_INDEX) {
printer.printCountedBy(CAT, index); diagnose(HeaderLoc(clangParam->getLocation()),
diag::warn_clang_ignored_bounds_on_self, getAttributeName(CAT));
auto swiftName = ClangDecl->getAttr<clang::SwiftNameAttr>();
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; attachMacro = paramHasBoundsInfo = true;
} }
bool paramIsStdSpan = registerStdSpanTypeMapping( bool paramIsStdSpan = registerStdSpanTypeMapping(
@@ -9494,14 +9537,16 @@ void ClangImporter::Implementation::swiftify(AbstractFunctionDecl *MappedDecl) {
bool paramHasLifetimeInfo = false; bool paramHasLifetimeInfo = false;
if (clangParam->hasAttr<clang::NoEscapeAttr>()) { if (clangParam->hasAttr<clang::NoEscapeAttr>()) {
printer.printNonEscaping(index); printer.printNonEscaping(mappedIndex);
paramHasLifetimeInfo = true; paramHasLifetimeInfo = true;
} }
if (clangParam->hasAttr<clang::LifetimeBoundAttr>()) { if (clangParam->hasAttr<clang::LifetimeBoundAttr>()) {
// If this parameter has bounds info we will tranform it into a Span, // If this parameter has bounds info we will tranform it into a Span,
// so then it will no longer be Escapable. // so then it will no longer be Escapable.
bool willBeEscapable = swiftParamTy->isEscapable() && !paramHasBoundsInfo; bool willBeEscapable = swiftParamTy->isEscapable() &&
printer.printLifetimeboundReturn(index, willBeEscapable); (!paramHasBoundsInfo ||
mappedIndex == SwiftifyInfoPrinter::SELF_PARAM_INDEX);
printer.printLifetimeboundReturn(mappedIndex, willBeEscapable);
paramHasLifetimeInfo = true; paramHasLifetimeInfo = true;
returnHasLifetimeInfo = true; returnHasLifetimeInfo = true;
} }
@@ -9512,7 +9557,6 @@ void ClangImporter::Implementation::swiftify(AbstractFunctionDecl *MappedDecl) {
attachMacro = true; attachMacro = true;
printer.printAvailability(); printer.printAvailability();
printer.printTypeMapping(typeMapping); printer.printTypeMapping(typeMapping);
} }
if (attachMacro) { if (attachMacro) {

View File

@@ -468,7 +468,14 @@ struct FunctionCallBuilder: BoundsCheckedThunkBuilder {
let functionRef = DeclReferenceExprSyntax(baseName: base.name) let functionRef = DeclReferenceExprSyntax(baseName: base.name)
let args: [ExprSyntax] = base.signature.parameterClause.parameters.enumerated() let args: [ExprSyntax] = base.signature.parameterClause.parameters.enumerated()
.map { (i: Int, param: FunctionParameterSyntax) in .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 labels: [TokenSyntax?] = base.signature.parameterClause.parameters.map { param in
let firstName = param.firstName.trimmed let firstName = param.firstName.trimmed

View File

@@ -42,6 +42,7 @@ module std {
header "ostream" header "ostream"
header "queue" header "queue"
header "set" header "set"
header "span"
header "sstream" header "sstream"
header "stack" header "stack"
header "stdexcept" header "stdexcept"

View File

@@ -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<CInt>, 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<CInt> = a.lifetimeBoundSelf(3)
c.refSelf(&p)
//b.nonescaping(&p)
//let _: MutableSpan<CInt> = 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 <ptrcheck.h>
#include <lifetimebound.h>
#include <swift/bridging>
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<Int32>) {
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<A>!, _ p: inout MutableSpan<Int32>) {
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<Int32>) {
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<A>!, _ p: inout MutableSpan<Int32>) {
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<Int32>) {
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<A>!, _ p: inout MutableSpan<Int32>) {
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<Int32>) {
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<Int32>) {
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<Int32> {
return unsafe _swiftifyOverrideLifetime(MutableSpan<Int32>(_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<Int32> {
return unsafe _swiftifyOverrideLifetime(MutableSpan<Int32>(_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<Int32>) {
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<Int32>) {
let len = Int32(exactly: p.count)!
return unsafe p.withUnsafeMutableBufferPointer { _pPtr in
return unsafe refSelf(c, _pPtr.baseAddress!, len)
}
}
------------------------------

View File

@@ -5,9 +5,6 @@
// REQUIRES: swift_feature_SafeInteropWrappers // 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 //--- Inputs/swiftify-non-public.h
#pragma once #pragma once

View File

@@ -8,9 +8,6 @@
// REQUIRES: swift_feature_SafeInteropWrappers // REQUIRES: swift_feature_SafeInteropWrappers
// REQUIRES: swift_feature_Lifetimes // 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 #if !BRIDGING_HEADER
import StdSpan import StdSpan
#endif #endif

View File

@@ -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) // 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 // TODO: test failed in Windows PR testing: rdar://144384453
// UNSUPPORTED: OS=windows-msvc // UNSUPPORTED: OS=windows-msvc

View File

@@ -1,8 +1,5 @@
// RUN: %target-typecheck-verify-swift -I %S/Inputs -enable-experimental-cxx-interop -Xcc -std=c++20 2>&1 // 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 import StdSpan
let arr: [Int32] = [1, 2, 3] let arr: [Int32] = [1, 2, 3]

View File

@@ -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)
// 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) // 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 // TODO: test failed in Windows PR testing: rdar://144384453
// UNSUPPORTED: OS=windows-msvc // UNSUPPORTED: OS=windows-msvc

View File

@@ -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<CInt>, 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<CInt> = unsafe s.spanSelf()
let _: IntSpan = unsafe s.spanConstSelf()
let _: MutableSpan<CInt> = unsafe s.spanConstSelf()
let _: ConstIntSpan = unsafe cs.constSpanSelf()
let _: Span<CInt> = unsafe cs.constSpanSelf()
let _: IntSpan = unsafe asp.spanSelf()
let _: MutableSpan<CInt> = unsafe asp.spanSelf()
#if VERIFY
p.spanSelf() // expected-error{{value of type 'MutableSpan<CInt>' (aka 'MutableSpan<Int32>') has no member 'spanSelf'}}
#endif
}
//--- Inputs/instance.h
#include <ptrcheck.h>
#include <lifetimebound.h>
#include <span>
struct A {};
using IntSpan = std::span<int>;
using ConstIntSpan = std::span<const int>;
using AliasingSpan = std::span<int>;
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<CInt>) {
// 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<A>!, _ p: inout MutableSpan<CInt>) {
// 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<CInt>) {
// 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<A>!, _ p: inout MutableSpan<CInt>) {
// 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<CInt>) {
// 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<A>!, _ p: inout MutableSpan<CInt>) {
// 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<CInt>) {
// 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<CInt>) {
// 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<CInt>) {
// 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<CInt>) {
// 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<CInt> {
// 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<CInt>) -> MutableSpan<CInt> {
// 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<CInt> {
// 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<CInt>) -> MutableSpan<CInt> {
// 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<CInt> {
// 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<CInt>) -> Span<CInt> {
// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(Span(_unsafeCxxSpan: unsafe constSpanSelf(ConstIntSpan(p))), copying: ())
// CHECK-NEXT:}
// CHECK-NEXT:------------------------------

View File

@@ -1,8 +1,5 @@
// REQUIRES: swift_feature_SafeInteropWrappers // 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: rm -rf %t
// RUN: split-file %s %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 // 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

View File

@@ -9,9 +9,6 @@
// RUN: %target-codesign %t/swift-cxx-execution // RUN: %target-codesign %t/swift-cxx-execution
// RUN: %target-run %t/swift-cxx-execution | %FileCheck %s // 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 // REQUIRES: executable_test
//--- header.h //--- header.h

View File

@@ -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\(([^)]+)\)', 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 && ' 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'))) 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'))