From 74c7720a8b2c698d664091e87442d09894983eb8 Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Sun, 30 Mar 2025 22:21:56 -0700 Subject: [PATCH 01/10] [Swiftify] Run swift-format (NFC) --- .../SwiftMacros/SwiftifyImportMacro.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift index 8ef08d222b96..705cb441b8fd 100644 --- a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift +++ b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift @@ -691,15 +691,15 @@ struct CountedOrSizedReturnPointerThunkBuilder: PointerBoundsThunkBuilder { cast = optType.wrappedType } return """ - { () in - let _resultValue = \(call) - if unsafe _resultValue == nil { - return nil - } else { - return unsafe \(raw: cast)(\(raw: startLabel): _resultValue!, count: Int(\(countExpr))) - } - }() - """ + { () in + let _resultValue = \(call) + if unsafe _resultValue == nil { + return nil + } else { + return unsafe \(raw: cast)(\(raw: startLabel): _resultValue!, count: Int(\(countExpr))) + } + }() + """ } return """ From 7e1375197af8734195e0ac9412fd72a41d540f3d Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Fri, 14 Feb 2025 14:19:42 -0800 Subject: [PATCH 02/10] [Swiftify] Add _SwiftifyImportProtocol for safe overloads for protocols The existing _SwiftifyImport macro is a peer macro, limiting it to only emitting function wrappers in the same scope as the original function. Protocols cannot contain function implementations, so these need to be placed in a separate protocol extension instead. _SwiftifyImportProtocol is an extension macro rather than a peer macro, to enable this functionality. Rather than operating on a single function, like _SwiftifyImport, _SwiftifyImportProtocol takes information about multiple methods and creates a single protocol extension with all wrappers in a one-shot operation. rdar://144335990 --- .../SwiftMacros/SwiftifyImportMacro.swift | 252 ++++++++++++------ stdlib/public/core/SwiftifyImport.swift | 23 +- .../SwiftifyImport/CountedBy/Protocol.swift | 57 ++++ 3 files changed, 247 insertions(+), 85 deletions(-) create mode 100644 test/Macros/SwiftifyImport/CountedBy/Protocol.swift diff --git a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift index 705cb441b8fd..25d28f6edddf 100644 --- a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift +++ b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift @@ -1117,11 +1117,10 @@ func parseCxxSpansInSignature( } func parseMacroParam( - _ paramAST: LabeledExprSyntax, _ signature: FunctionSignatureSyntax, + _ paramExpr: ExprSyntax, _ signature: FunctionSignatureSyntax, nonescapingPointers: inout Set, lifetimeDependencies: inout [SwiftifyExpr: [LifetimeDependence]] ) throws -> ParamInfo? { - let paramExpr = paramAST.expression guard let enumConstructorExpr = paramExpr.as(FunctionCallExprSyntax.self) else { throw DiagnosticError( "expected _SwiftifyInfo enum literal as argument, got '\(paramExpr)'", node: paramExpr) @@ -1351,6 +1350,94 @@ func paramLifetimeAttributes( return defaultLifetimes } +func constructOverloadFunction(forDecl funcDecl: FunctionDeclSyntax, + args arguments: [ExprSyntax], + typeMappings: [String: String]?) throws -> DeclSyntax { + var nonescapingPointers = Set() + var lifetimeDependencies : [SwiftifyExpr: [LifetimeDependence]] = [:] + var parsedArgs = try arguments.compactMap { + try parseMacroParam($0, funcDecl.signature, nonescapingPointers: &nonescapingPointers, + lifetimeDependencies: &lifetimeDependencies) + } + parsedArgs.append(contentsOf: try parseCxxSpansInSignature(funcDecl.signature, typeMappings)) + setNonescapingPointers(&parsedArgs, nonescapingPointers) + setLifetimeDependencies(&parsedArgs, lifetimeDependencies) + // We only transform non-escaping spans. + parsedArgs = parsedArgs.filter { + if let cxxSpanArg = $0 as? CxxSpan { + return cxxSpanArg.nonescaping || cxxSpanArg.pointerIndex == .return + } else { + return true + } + } + try checkArgs(parsedArgs, funcDecl) + parsedArgs.sort { a, b in + // make sure return value cast to Span happens last so that withUnsafeBufferPointer + // doesn't return a ~Escapable type + if a.pointerIndex != .return && b.pointerIndex == .return { + return true + } + if a.pointerIndex == .return && b.pointerIndex != .return { + return false + } + return paramOrReturnIndex(a.pointerIndex) < paramOrReturnIndex(b.pointerIndex) + } + let baseBuilder = FunctionCallBuilder(funcDecl) + + let skipTrivialCount = hasTrivialCountVariants(parsedArgs) + + let builder: BoundsCheckedThunkBuilder = parsedArgs.reduce( + baseBuilder, + { (prev, parsedArg) in + parsedArg.getBoundsCheckedThunkBuilder(prev, funcDecl, skipTrivialCount) + }) + let (newSignature, onlyReturnTypeChanged) = try builder.buildFunctionSignature([:], nil) + let checks = + skipTrivialCount + ? [] as [CodeBlockItemSyntax] + : try builder.buildBoundsChecks().map { e in + CodeBlockItemSyntax(leadingTrivia: "\n", item: e) + } + let call = CodeBlockItemSyntax( + item: CodeBlockItemSyntax.Item( + ReturnStmtSyntax( + returnKeyword: .keyword(.return, trailingTrivia: " "), + expression: try builder.buildFunctionCall([:])))) + let body = CodeBlockSyntax(statements: CodeBlockItemListSyntax(checks + [call])) + let returnLifetimeAttribute = getReturnLifetimeAttribute(funcDecl, lifetimeDependencies) + let lifetimeAttrs = + returnLifetimeAttribute + paramLifetimeAttributes(newSignature, funcDecl.attributes) + let disfavoredOverload: [AttributeListSyntax.Element] = (onlyReturnTypeChanged ? [ + .attribute( + AttributeSyntax( + atSign: .atSignToken(), + attributeName: IdentifierTypeSyntax(name: "_disfavoredOverload"))) + ] : []) + let newFunc = + funcDecl + .with(\.signature, newSignature) + .with(\.body, body) + .with( + \.attributes, + funcDecl.attributes.filter { e in + switch e { + case .attribute(let attr): + // don't apply this macro recursively, and avoid dupe _alwaysEmitIntoClient + let name = attr.attributeName.as(IdentifierTypeSyntax.self)?.name.text + return name == nil || (name != "_SwiftifyImport" && name != "_alwaysEmitIntoClient") + default: return true + } + } + [ + .attribute( + AttributeSyntax( + atSign: .atSignToken(), + attributeName: IdentifierTypeSyntax(name: "_alwaysEmitIntoClient"))) + ] + + lifetimeAttrs + + disfavoredOverload) + return DeclSyntax(newFunc) +} + /// A macro that adds safe(r) wrappers for functions with unsafe pointer types. /// Depends on bounds, escapability and lifetime information for each pointer. /// Intended to map to C attributes like __counted_by, __ended_by and __no_escape, @@ -1374,92 +1461,89 @@ public struct SwiftifyImportMacro: PeerMacro { if typeMappings != nil { arguments = arguments.dropLast() } - var nonescapingPointers = Set() - var lifetimeDependencies: [SwiftifyExpr: [LifetimeDependence]] = [:] - var parsedArgs = try arguments.compactMap { - try parseMacroParam( - $0, funcDecl.signature, nonescapingPointers: &nonescapingPointers, - lifetimeDependencies: &lifetimeDependencies) + let args = arguments.map { $0.expression } + return [try constructOverloadFunction(forDecl: funcDecl, args: args, typeMappings: typeMappings)] + } catch let error as DiagnosticError { + context.diagnose( + Diagnostic( + node: error.node, message: MacroExpansionErrorMessage(error.description), + notes: error.notes)) + return [] + } + } +} + +func parseProtocolMacroParam( + _ paramAST: LabeledExprSyntax, + methods: [String: FunctionDeclSyntax] +) throws -> (FunctionDeclSyntax, [ExprSyntax]) { + let paramExpr = paramAST.expression + guard let enumConstructorExpr = paramExpr.as(FunctionCallExprSyntax.self) else { + throw DiagnosticError( + "expected _SwiftifyProtocolMethodInfo enum literal as argument, got '\(paramExpr)'", node: paramExpr) + } + let enumName = try parseEnumName(paramExpr) + if enumName != "method" { + throw DiagnosticError( + "expected 'method', got '\(enumName)'", + node: enumConstructorExpr) + } + let argumentList = enumConstructorExpr.arguments + let methodNameArg = try getArgumentByName(argumentList, "name") + guard let methodNameStringLit = methodNameArg.as(StringLiteralExprSyntax.self) else { + throw DiagnosticError( + "expected string literal for 'name' parameter, got \(methodNameArg)", node: methodNameArg) + } + let methodName = methodNameStringLit.representedLiteralValue! + guard let methodSyntax = methods[methodName] else { + throw DiagnosticError("method with name \(methodName) not found in protocol", node: methodNameArg) + } + let paramInfoArg = try getArgumentByName(argumentList, "paramInfo") + guard let paramInfoArgList = paramInfoArg.as(ArrayExprSyntax.self) else { + throw DiagnosticError("expected array literal for 'paramInfo' parameter, got \(paramInfoArg)", node: paramInfoArg) + } + return (methodSyntax, paramInfoArgList.elements.map { ExprSyntax($0.expression) }) +} + +/// Similar to SwiftifyImportMacro, but for providing overloads to methods in +/// protocols using an extension, rather than in the same scope as the original. +public struct SwiftifyImportProtocolMacro: ExtensionMacro { + public static func expansion( + of node: AttributeSyntax, + attachedTo declaration: some DeclGroupSyntax, + providingExtensionsOf type: some TypeSyntaxProtocol, + conformingTo protocols: [TypeSyntax], + in context: some MacroExpansionContext + ) throws -> [ExtensionDeclSyntax] { + do { + guard let protocolDecl = declaration.as(ProtocolDeclSyntax.self) else { + throw DiagnosticError("@_SwiftifyImportProtocol only works on protocols", node: declaration) + } + let argumentList = node.arguments!.as(LabeledExprListSyntax.self)! + var arguments = [LabeledExprSyntax](argumentList) + let typeMappings = try parseTypeMappingParam(arguments.last) + if typeMappings != nil { + arguments = arguments.dropLast() } - parsedArgs.append(contentsOf: try parseCxxSpansInSignature(funcDecl.signature, typeMappings)) - setNonescapingPointers(&parsedArgs, nonescapingPointers) - setLifetimeDependencies(&parsedArgs, lifetimeDependencies) - // We only transform non-escaping spans. - parsedArgs = parsedArgs.filter { - if let cxxSpanArg = $0 as? CxxSpan { - return cxxSpanArg.nonescaping || cxxSpanArg.pointerIndex == .return - } else { - return true + + var methods: [String: FunctionDeclSyntax] = [:] + for member in protocolDecl.memberBlock.members { + guard let methodDecl = member.decl.as(FunctionDeclSyntax.self) else { + continue } + methods[methodDecl.name.trimmed.text] = methodDecl } - try checkArgs(parsedArgs, funcDecl) - parsedArgs.sort { a, b in - // make sure return value cast to Span happens last so that withUnsafeBufferPointer - // doesn't return a ~Escapable type - if a.pointerIndex != .return && b.pointerIndex == .return { - return true - } - if a.pointerIndex == .return && b.pointerIndex != .return { - return false - } - return paramOrReturnIndex(a.pointerIndex) < paramOrReturnIndex(b.pointerIndex) + let overloads = try arguments.map { + let (method, args) = try parseProtocolMacroParam($0, methods: methods) + let function = try constructOverloadFunction(forDecl: method, args: args, typeMappings: typeMappings) + return MemberBlockItemSyntax(decl: function) } - let baseBuilder = FunctionCallBuilder(funcDecl) - - let skipTrivialCount = hasTrivialCountVariants(parsedArgs) - - let builder: BoundsCheckedThunkBuilder = parsedArgs.reduce( - baseBuilder, - { (prev, parsedArg) in - parsedArg.getBoundsCheckedThunkBuilder(prev, funcDecl, skipTrivialCount) - }) - let (newSignature, onlyReturnTypeChanged) = try builder.buildFunctionSignature([:], nil) - let checks = - skipTrivialCount - ? [] as [CodeBlockItemSyntax] - : try builder.buildBoundsChecks().map { e in - CodeBlockItemSyntax(leadingTrivia: "\n", item: e) - } - let call = CodeBlockItemSyntax( - item: CodeBlockItemSyntax.Item( - ReturnStmtSyntax( - returnKeyword: .keyword(.return, trailingTrivia: " "), - expression: try builder.buildFunctionCall([:])))) - let body = CodeBlockSyntax(statements: CodeBlockItemListSyntax(checks + [call])) - let returnLifetimeAttribute = getReturnLifetimeAttribute(funcDecl, lifetimeDependencies) - let lifetimeAttrs = - returnLifetimeAttribute + paramLifetimeAttributes(newSignature, funcDecl.attributes) - let disfavoredOverload: [AttributeListSyntax.Element] = - (onlyReturnTypeChanged - ? [ - .attribute( - AttributeSyntax( - atSign: .atSignToken(), - attributeName: IdentifierTypeSyntax(name: "_disfavoredOverload"))) - ] : []) - let newFunc = - funcDecl - .with(\.signature, newSignature) - .with(\.body, body) - .with( - \.attributes, - funcDecl.attributes.filter { e in - switch e { - case .attribute(let attr): - // don't apply this macro recursively, and avoid dupe _alwaysEmitIntoClient - let name = attr.attributeName.as(IdentifierTypeSyntax.self)?.name.text - return name == nil || (name != "_SwiftifyImport" && name != "_alwaysEmitIntoClient") - default: return true - } - } + [ - .attribute( - AttributeSyntax( - atSign: .atSignToken(), - attributeName: IdentifierTypeSyntax(name: "_alwaysEmitIntoClient"))) - ] - + lifetimeAttrs - + disfavoredOverload) - return [DeclSyntax(newFunc)] + + return [ExtensionDeclSyntax(extensionKeyword: .identifier("extension"), extendedType: type, + memberBlock: MemberBlockSyntax(leftBrace: .leftBraceToken(), + members: MemberBlockItemListSyntax(overloads), + rightBrace: .rightBraceToken()) + )] } catch let error as DiagnosticError { context.diagnose( Diagnostic( diff --git a/stdlib/public/core/SwiftifyImport.swift b/stdlib/public/core/SwiftifyImport.swift index 3efd0a645098..8ddddf6af98f 100644 --- a/stdlib/public/core/SwiftifyImport.swift +++ b/stdlib/public/core/SwiftifyImport.swift @@ -54,7 +54,7 @@ public enum _SwiftifyInfo { /// It will replace some std::span arguments with Swift's Span type when sufficient information is /// available. /// -/// Currently not supported: return pointers, nested pointers, pointee "count" parameters, endedBy. +/// Currently not supported: nested pointers, pointee "count" parameters, endedBy. /// /// Parameter paramInfo: information about how the function uses the pointer passed to it. The /// safety of the generated wrapper function depends on this info being extensive and accurate. @@ -63,3 +63,24 @@ public enum _SwiftifyInfo { public macro _SwiftifyImport(_ paramInfo: _SwiftifyInfo..., typeMappings: [String: String] = [:]) = #externalMacro(module: "SwiftMacros", type: "SwiftifyImportMacro") #endif + +/// Allows annotating pointer parameters in a protocol method using the `@_SwiftifyImportProtocol` macro. +/// +/// This is not marked @available, because _SwiftifyImportProtocolMethod is available for any target. +/// Instances of _SwiftifyProtocolMethodInfo should ONLY be passed as arguments directly to +/// _SwiftifyImportProtocolMethod, so they should not affect linkage since there are never any instances +/// at runtime. +public enum _SwiftifyProtocolMethodInfo { + case method(name: String, paramInfo: [_SwiftifyInfo]) +} + +/// Like _SwiftifyImport, but since protocols cannot contain function implementations they need to +/// be placed in a separate extension instead. Unlike _SwiftifyImport, which applies to a single +/// function, this macro supports feeding info about multiple methods and generating safe overloads +/// for all of them at once. +#if hasFeature(Macros) +@attached(extension, names: arbitrary) +public macro _SwiftifyImportProtocol(_ methodInfo: _SwiftifyProtocolMethodInfo..., + typeMappings: [String: String] = [:]) = + #externalMacro(module: "SwiftMacros", type: "SwiftifyImportProtocolMacro") +#endif diff --git a/test/Macros/SwiftifyImport/CountedBy/Protocol.swift b/test/Macros/SwiftifyImport/CountedBy/Protocol.swift new file mode 100644 index 000000000000..853adffa130b --- /dev/null +++ b/test/Macros/SwiftifyImport/CountedBy/Protocol.swift @@ -0,0 +1,57 @@ +// REQUIRES: swift_swift_parser + +// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -dump-macro-expansions -enable-experimental-feature Span -enable-experimental-feature LifetimeDependence 2>&1 | %FileCheck --match-full-lines %s + +@_SwiftifyImportProtocol(.method(name: "myFunc", paramInfo: [.countedBy(pointer: .param(1), count: "len")])) +protocol SimpleProtocol { + func myFunc(_ ptr: UnsafePointer, _ len: CInt) +} + +// CHECK: extension SimpleProtocol { +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer) { +// CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) +// CHECK-NEXT: } +// CHECK-NEXT: } + +@_SwiftifyImportProtocol(.method(name: "foo", paramInfo: [.countedBy(pointer: .param(1), count: "len"), .nonescaping(pointer: .param(1))]), + .method(name: "bar", paramInfo: [.countedBy(pointer: .return, count: "len"), .nonescaping(pointer: .return), .lifetimeDependence(dependsOn: .self, pointer: .return, type: .borrow)])) +protocol SpanProtocol { + func foo(_ ptr: UnsafePointer, _ len: CInt) + func bar(_ len: CInt) -> UnsafePointer +} + +// CHECK: extension SpanProtocol { +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: func foo(_ ptr: Span) { +// CHECK-NEXT: return unsafe ptr.withUnsafeBufferPointer { _ptrPtr in +// CHECK-NEXT: return unsafe foo(_ptrPtr.baseAddress!, CInt(exactly: ptr.count)!) +// CHECK-NEXT: } +// CHECK-NEXT: } + +// CHECK-NEXT: @_alwaysEmitIntoClient @lifetime(borrow self) @_disfavoredOverload +// CHECK-NEXT: func bar(_ len: CInt) -> Span { +// CHECK-NEXT: return unsafe Span(_unsafeStart: unsafe bar(len), count: Int(len)) +// CHECK-NEXT: } +// CHECK-NEXT: } + +@_SwiftifyImportProtocol(.method(name: "foo", paramInfo: [.countedBy(pointer: .param(1), count: "len"), .nonescaping(pointer: .param(1))]), + .method(name: "bar", paramInfo: [.countedBy(pointer: .param(1), count: "len")])) +protocol MixedProtocol { + func foo(_ ptr: UnsafePointer, _ len: CInt) + func bar(_ ptr: UnsafePointer, _ len: CInt) +} + +// CHECK: extension MixedProtocol { +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: func foo(_ ptr: Span) { +// CHECK-NEXT: return unsafe ptr.withUnsafeBufferPointer { _ptrPtr in +// CHECK-NEXT: return unsafe foo(_ptrPtr.baseAddress!, CInt(exactly: ptr.count)!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: func bar(_ ptr: UnsafeBufferPointer) { +// CHECK-NEXT: return unsafe bar(ptr.baseAddress!, CInt(exactly: ptr.count)!) +// CHECK-NEXT: } +// CHECK-NEXT: } + From 83d4cc59c744cd44fbd48cde67a6121bf2646a92 Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Mon, 31 Mar 2025 11:37:27 -0700 Subject: [PATCH 03/10] Move registerStdSpanTypeMapping to SwiftifyInfoPrinter (NFC) `registerStdSpanTypeMapping` used to be a lambda inside `swiftify`. By moving it, along with the `typeMapping` state, inside `SwiftifyInfoPrinter` we will simplify changes necessary to support `_SwiftifyImportProtocol` in ClangImporter. --- lib/ClangImporter/ImportDecl.cpp | 38 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 2b33b7885259..93dc9c20abfe 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -9046,6 +9046,8 @@ class SwiftifyInfoPrinter { clang::ASTContext &ctx; llvm::raw_ostream &out; bool firstParam = true; + llvm::StringMap typeMapping; + SwiftifyInfoPrinter(clang::ASTContext &ctx, llvm::raw_ostream &out) : ctx(ctx), out(out) { out << "@_SwiftifyImport("; @@ -9091,14 +9093,24 @@ class SwiftifyInfoPrinter { out << ")"; } - void printTypeMapping(const llvm::StringMap &mapping) { + bool registerStdSpanTypeMapping(Type swiftType, const clang::QualType clangType) { + const auto *decl = clangType->getAsTagDecl(); + if (decl && decl->isInStdNamespace() && decl->getName() == "span") { + typeMapping.insert(std::make_pair( + swiftType->getString(), swiftType->getDesugaredType()->getString())); + return true; + } + return false; + } + + void printTypeMapping() { printSeparator(); out << "typeMappings: ["; - if (mapping.empty()) { + if (typeMapping.empty()) { out << ":]"; return; } - llvm::interleaveComma(mapping, out, [&](const auto &entry) { + llvm::interleaveComma(typeMapping, out, [&](const auto &entry) { out << '"' << entry.getKey() << "\" : \"" << entry.getValue() << '"'; }); out << "]"; @@ -9140,21 +9152,9 @@ void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) { bool attachMacro = false; { llvm::raw_svector_ostream out(MacroString); - llvm::StringMap typeMapping; - - auto registerStdSpanTypeMapping = - [&typeMapping](Type swiftType, const clang::QualType clangType) { - const auto *decl = clangType->getAsTagDecl(); - if (decl && decl->isInStdNamespace() && decl->getName() == "span") { - typeMapping.insert( - std::make_pair(swiftType->getString(), - swiftType->getDesugaredType()->getString())); - return true; - } - return false; - }; + SwiftifyInfoPrinter printer(getClangASTContext(), out); - bool returnIsStdSpan = registerStdSpanTypeMapping( + bool returnIsStdSpan = printer.registerStdSpanTypeMapping( MappedDecl->getResultInterfaceType(), ClangDecl->getReturnType()); if (auto CAT = ClangDecl->getReturnType()->getAs()) { @@ -9176,7 +9176,7 @@ void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) { printer.printCountedBy(CAT, index); attachMacro = paramHasBoundsInfo = true; } - bool paramIsStdSpan = registerStdSpanTypeMapping( + bool paramIsStdSpan = printer.registerStdSpanTypeMapping( swiftParam->getInterfaceType(), clangParamTy); paramHasBoundsInfo |= paramIsStdSpan; @@ -9197,7 +9197,7 @@ void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) { } if (returnIsStdSpan && returnHasLifetimeInfo) attachMacro = true; - printer.printTypeMapping(typeMapping); + printer.printTypeMapping(); } if (attachMacro) From e3009d5c399fded4253049bd71cf62d08037bd93 Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Wed, 19 Feb 2025 21:44:52 -0800 Subject: [PATCH 04/10] [Swiftify] Make safe wrappers explicitly public --- .../SwiftMacros/SwiftifyImportMacro.swift | 5 +++++ .../SwiftifyImport/CountedBy/CountExpr.swift | 2 +- .../CountedBy/MultipleParams.swift | 2 +- .../SwiftifyImport/CountedBy/Mutable.swift | 2 +- .../SwiftifyImport/CountedBy/MutableSpan.swift | 2 +- .../SwiftifyImport/CountedBy/NamedParams.swift | 12 ++++++------ .../SwiftifyImport/CountedBy/Nullable.swift | 8 ++++---- .../CountedBy/PointerReturn.swift | 8 ++++---- .../SwiftifyImport/CountedBy/Protocol.swift | 11 +++++------ .../CountedBy/QualifiedTypes.swift | 4 ++-- .../SwiftifyImport/CountedBy/Return.swift | 2 +- .../SwiftifyImport/CountedBy/SharedCount.swift | 2 +- .../SwiftifyImport/CountedBy/SimpleCount.swift | 2 +- .../SwiftifyImport/CountedBy/SimpleSpan.swift | 2 +- .../CountedBy/SimpleSpanWithReturn.swift | 2 +- .../CountedBy/SpanAndUnsafeBuffer.swift | 2 +- .../SwiftifyImport/CountedBy/Unwrapped.swift | 2 +- .../CxxSpan/LifetimeboundSpan.swift | 18 +++++++++--------- .../SwiftifyImport/CxxSpan/NoEscapeSpan.swift | 8 ++++---- .../MacroErrors/UnexpectedCountType.swift | 2 +- .../SizedBy/MultipleParams.swift | 2 +- .../SwiftifyImport/SizedBy/Mutable.swift | 2 +- .../SizedBy/MutableRawSpan.swift | 2 +- .../SwiftifyImport/SizedBy/Nullable.swift | 2 +- .../Macros/SwiftifyImport/SizedBy/Opaque.swift | 12 ++++++------ .../Macros/SwiftifyImport/SizedBy/Return.swift | 2 +- .../SwiftifyImport/SizedBy/SharedCount.swift | 2 +- .../SwiftifyImport/SizedBy/SimpleRawSpan.swift | 2 +- .../SizedBy/SimpleRawSpanWithReturn.swift | 2 +- .../SwiftifyImport/SizedBy/SimpleSize.swift | 2 +- .../SwiftifyImport/SizedBy/SizeExpr.swift | 2 +- .../SwiftifyImport/SizedBy/Unwrapped.swift | 2 +- 32 files changed, 68 insertions(+), 64 deletions(-) diff --git a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift index 25d28f6edddf..fd062295994a 100644 --- a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift +++ b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift @@ -1413,6 +1413,10 @@ func constructOverloadFunction(forDecl funcDecl: FunctionDeclSyntax, atSign: .atSignToken(), attributeName: IdentifierTypeSyntax(name: "_disfavoredOverload"))) ] : []) + let hasVisibilityModifier = funcDecl.modifiers.contains { modifier in + let modName = modifier.name.trimmed.text + return modName == "public" || modName == "internal" || modName == "open" || modName == "private" || modName == "filePrivate" + } let newFunc = funcDecl .with(\.signature, newSignature) @@ -1435,6 +1439,7 @@ func constructOverloadFunction(forDecl funcDecl: FunctionDeclSyntax, ] + lifetimeAttrs + disfavoredOverload) + .with(\.modifiers, funcDecl.modifiers + (hasVisibilityModifier ? [] : [DeclModifierSyntax(name: .identifier("public"))])) return DeclSyntax(newFunc) } diff --git a/test/Macros/SwiftifyImport/CountedBy/CountExpr.swift b/test/Macros/SwiftifyImport/CountedBy/CountExpr.swift index 92fe4889bdad..d2b84757061b 100644 --- a/test/Macros/SwiftifyImport/CountedBy/CountExpr.swift +++ b/test/Macros/SwiftifyImport/CountedBy/CountExpr.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafePointer, _ size: CInt, _ count: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer, _ size: CInt, _ count: CInt) { // CHECK-NEXT: let _ptrCount: some BinaryInteger = size * count // CHECK-NEXT: if ptr.count < _ptrCount || _ptrCount < 0 { diff --git a/test/Macros/SwiftifyImport/CountedBy/MultipleParams.swift b/test/Macros/SwiftifyImport/CountedBy/MultipleParams.swift index 6ad7bf0cc782..827c6422101d 100644 --- a/test/Macros/SwiftifyImport/CountedBy/MultipleParams.swift +++ b/test/Macros/SwiftifyImport/CountedBy/MultipleParams.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafePointer, _ len: CInt, _ ptr2: UnsafePointer, _ len2: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer, _ ptr2: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!, ptr2.baseAddress!, CInt(exactly: ptr2.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/Mutable.swift b/test/Macros/SwiftifyImport/CountedBy/Mutable.swift index 1df1df132911..50ab5d37da01 100644 --- a/test/Macros/SwiftifyImport/CountedBy/Mutable.swift +++ b/test/Macros/SwiftifyImport/CountedBy/Mutable.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafeMutablePointer, _ len: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeMutableBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/MutableSpan.swift b/test/Macros/SwiftifyImport/CountedBy/MutableSpan.swift index e03ccbcb7653..25511ea7e8f2 100644 --- a/test/Macros/SwiftifyImport/CountedBy/MutableSpan.swift +++ b/test/Macros/SwiftifyImport/CountedBy/MutableSpan.swift @@ -7,7 +7,7 @@ func myFunc(_ ptr: UnsafeMutablePointer, _ len: CInt) { } -// CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) +// CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) public // CHECK-NEXT: func myFunc(_ ptr: inout MutableSpan) { // CHECK-NEXT: return unsafe ptr.withUnsafeMutableBufferPointer { _ptrPtr in // CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: ptr.count)!) diff --git a/test/Macros/SwiftifyImport/CountedBy/NamedParams.swift b/test/Macros/SwiftifyImport/CountedBy/NamedParams.swift index 6e450b8afa12..eaf74b94177e 100644 --- a/test/Macros/SwiftifyImport/CountedBy/NamedParams.swift +++ b/test/Macros/SwiftifyImport/CountedBy/NamedParams.swift @@ -26,32 +26,32 @@ func allNamed(ptr: UnsafePointer, len: CInt) { func allNamedOther(buf ptr: UnsafePointer, count len: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func ptrNamed(ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe ptrNamed(ptr: ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func ptrNamedOther(buf ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe ptrNamedOther(buf: ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func lenNamed(_ ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe lenNamed(ptr.baseAddress!, len: CInt(exactly: ptr.count)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func lenNamedOther(_ ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe lenNamedOther(ptr.baseAddress!, count: CInt(exactly: ptr.count)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func allNamed(ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe allNamed(ptr: ptr.baseAddress!, len: CInt(exactly: ptr.count)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func allNamedOther(buf ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe allNamedOther(buf: ptr.baseAddress!, count: CInt(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/Nullable.swift b/test/Macros/SwiftifyImport/CountedBy/Nullable.swift index b0f3f2c926ab..477544564efb 100644 --- a/test/Macros/SwiftifyImport/CountedBy/Nullable.swift +++ b/test/Macros/SwiftifyImport/CountedBy/Nullable.swift @@ -18,12 +18,12 @@ func myFunc3(_ ptr: UnsafeMutablePointer?, _ len: CInt, _ ptr2: UnsafeMuta func myFunc4(_ ptr: UnsafeMutablePointer?, _ len: CInt) -> UnsafeMutablePointer? { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer?) { // CHECK-NEXT: return unsafe myFunc(ptr?.baseAddress, CInt(exactly: ptr?.count ?? 0)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) +// CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) public // CHECK-NEXT: func myFunc2(_ ptr: inout MutableSpan?) { // CHECK-NEXT: return { () in // CHECK-NEXT: return if ptr == nil { @@ -36,7 +36,7 @@ func myFunc4(_ ptr: UnsafeMutablePointer?, _ len: CInt) -> UnsafeMutablePo // CHECK-NEXT: }() // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) @lifetime(ptr2: copy ptr2) +// CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) @lifetime(ptr2: copy ptr2) public // CHECK-NEXT: func myFunc3(_ ptr: inout MutableSpan?, _ ptr2: inout MutableSpan?) { // CHECK-NEXT: return { () in // CHECK-NEXT: return if ptr2 == nil { @@ -65,7 +65,7 @@ func myFunc4(_ ptr: UnsafeMutablePointer?, _ len: CInt) -> UnsafeMutablePo // CHECK-NEXT: }() // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(copy ptr) @lifetime(ptr: copy ptr) +// CHECK: @_alwaysEmitIntoClient @lifetime(copy ptr) @lifetime(ptr: copy ptr) public // CHECK-NEXT: func myFunc4(_ ptr: inout MutableSpan?, _ len: CInt) -> MutableSpan? { // CHECK-NEXT: let _ptrCount: some BinaryInteger = len // CHECK-NEXT: if ptr?.count ?? 0 < _ptrCount || _ptrCount < 0 { diff --git a/test/Macros/SwiftifyImport/CountedBy/PointerReturn.swift b/test/Macros/SwiftifyImport/CountedBy/PointerReturn.swift index d1de7eeadd18..f5e01837d296 100644 --- a/test/Macros/SwiftifyImport/CountedBy/PointerReturn.swift +++ b/test/Macros/SwiftifyImport/CountedBy/PointerReturn.swift @@ -19,23 +19,23 @@ func lifetimeDependentCopy(_ p: UnsafePointer, _ len1: CInt, _ len2: CInt) func lifetimeDependentBorrow(_ p: borrowing UnsafePointer, _ len1: CInt, _ len2: CInt) -> UnsafePointer { } -// CHECK: @_alwaysEmitIntoClient @_disfavoredOverload +// CHECK: @_alwaysEmitIntoClient @_disfavoredOverload public // CHECK-NEXT: func myFunc(_ len: CInt) -> UnsafeMutableBufferPointer { // CHECK-NEXT: return unsafe UnsafeMutableBufferPointer (start: unsafe myFunc(len), count: Int(len)) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @_disfavoredOverload +// CHECK: @_alwaysEmitIntoClient @_disfavoredOverload public // CHECK-NEXT: func nonEscaping(_ len: CInt) -> UnsafeBufferPointer { // CHECK-NEXT: return unsafe UnsafeBufferPointer (start: unsafe nonEscaping(len), count: Int(len)) -// CHECK: @_alwaysEmitIntoClient @lifetime(copy p) +// CHECK: @_alwaysEmitIntoClient @lifetime(copy p) public // CHECK-NEXT: func lifetimeDependentCopy(_ p: Span, _ len2: CInt) -> Span { // CHECK-NEXT: return unsafe Span (_unsafeStart: unsafe p.withUnsafeBufferPointer { _pPtr in // CHECK-NEXT: return unsafe lifetimeDependentCopy(_pPtr.baseAddress!, CInt(exactly: p.count)!, len2) // CHECK-NEXT: }, count: Int(len2)) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(borrow p) +// CHECK: @_alwaysEmitIntoClient @lifetime(borrow p) public // CHECK-NEXT: func lifetimeDependentBorrow(_ p: borrowing UnsafeBufferPointer, _ len2: CInt) -> Span { // CHECK-NEXT: return unsafe Span (_unsafeStart: unsafe lifetimeDependentBorrow(p.baseAddress!, CInt(exactly: p.count)!, len2), count: Int(len2)) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/Protocol.swift b/test/Macros/SwiftifyImport/CountedBy/Protocol.swift index 853adffa130b..7f4882aba15e 100644 --- a/test/Macros/SwiftifyImport/CountedBy/Protocol.swift +++ b/test/Macros/SwiftifyImport/CountedBy/Protocol.swift @@ -8,7 +8,7 @@ protocol SimpleProtocol { } // CHECK: extension SimpleProtocol { -// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } @@ -22,14 +22,14 @@ protocol SpanProtocol { } // CHECK: extension SpanProtocol { -// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: @_alwaysEmitIntoClient public // CHECK-NEXT: func foo(_ ptr: Span) { // CHECK-NEXT: return unsafe ptr.withUnsafeBufferPointer { _ptrPtr in // CHECK-NEXT: return unsafe foo(_ptrPtr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK-NEXT: @_alwaysEmitIntoClient @lifetime(borrow self) @_disfavoredOverload +// CHECK-NEXT: @_alwaysEmitIntoClient @lifetime(borrow self) @_disfavoredOverload public // CHECK-NEXT: func bar(_ len: CInt) -> Span { // CHECK-NEXT: return unsafe Span(_unsafeStart: unsafe bar(len), count: Int(len)) // CHECK-NEXT: } @@ -43,15 +43,14 @@ protocol MixedProtocol { } // CHECK: extension MixedProtocol { -// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: @_alwaysEmitIntoClient public // CHECK-NEXT: func foo(_ ptr: Span) { // CHECK-NEXT: return unsafe ptr.withUnsafeBufferPointer { _ptrPtr in // CHECK-NEXT: return unsafe foo(_ptrPtr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: @_alwaysEmitIntoClient public // CHECK-NEXT: func bar(_ ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe bar(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } - diff --git a/test/Macros/SwiftifyImport/CountedBy/QualifiedTypes.swift b/test/Macros/SwiftifyImport/CountedBy/QualifiedTypes.swift index 3a7139e92f13..6dac3a80daef 100644 --- a/test/Macros/SwiftifyImport/CountedBy/QualifiedTypes.swift +++ b/test/Macros/SwiftifyImport/CountedBy/QualifiedTypes.swift @@ -10,12 +10,12 @@ func foo(_ ptr: Swift.UnsafePointer, _ len: Swift.Int) -> Swift.Void func bar(_ ptr: Swift.UnsafePointer, _ len: Swift.Int) -> () { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func foo(_ ptr: Swift.UnsafeBufferPointer) -> Swift.Void { // CHECK-NEXT: return unsafe foo(ptr.baseAddress!, ptr.count) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func bar(_ ptr: Swift.UnsafeBufferPointer) -> () { // CHECK-NEXT: return unsafe bar(ptr.baseAddress!, ptr.count) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/Return.swift b/test/Macros/SwiftifyImport/CountedBy/Return.swift index ceebe3e43ac8..fdc6f62c979a 100644 --- a/test/Macros/SwiftifyImport/CountedBy/Return.swift +++ b/test/Macros/SwiftifyImport/CountedBy/Return.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafePointer, _ len: CInt) -> CInt { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer) -> CInt { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/SharedCount.swift b/test/Macros/SwiftifyImport/CountedBy/SharedCount.swift index 71a084acb6f7..27c2b96457bb 100644 --- a/test/Macros/SwiftifyImport/CountedBy/SharedCount.swift +++ b/test/Macros/SwiftifyImport/CountedBy/SharedCount.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafePointer, _ ptr2: UnsafePointer, _ len: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer, _ ptr2: UnsafeBufferPointer, _ len: CInt) { // CHECK-NEXT: let _ptrCount: some BinaryInteger = len // CHECK-NEXT: if ptr.count < _ptrCount || _ptrCount < 0 { diff --git a/test/Macros/SwiftifyImport/CountedBy/SimpleCount.swift b/test/Macros/SwiftifyImport/CountedBy/SimpleCount.swift index 3f252815fc55..b3f75cc15968 100644 --- a/test/Macros/SwiftifyImport/CountedBy/SimpleCount.swift +++ b/test/Macros/SwiftifyImport/CountedBy/SimpleCount.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafePointer, _ len: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/SimpleSpan.swift b/test/Macros/SwiftifyImport/CountedBy/SimpleSpan.swift index 69de53f1d9cf..a535527994f9 100644 --- a/test/Macros/SwiftifyImport/CountedBy/SimpleSpan.swift +++ b/test/Macros/SwiftifyImport/CountedBy/SimpleSpan.swift @@ -7,7 +7,7 @@ func myFunc(_ ptr: UnsafePointer, _ len: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: Span) { // CHECK-NEXT: return unsafe ptr.withUnsafeBufferPointer { _ptrPtr in // CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: ptr.count)!) diff --git a/test/Macros/SwiftifyImport/CountedBy/SimpleSpanWithReturn.swift b/test/Macros/SwiftifyImport/CountedBy/SimpleSpanWithReturn.swift index 28f60f497137..2adda99ceed7 100644 --- a/test/Macros/SwiftifyImport/CountedBy/SimpleSpanWithReturn.swift +++ b/test/Macros/SwiftifyImport/CountedBy/SimpleSpanWithReturn.swift @@ -7,7 +7,7 @@ func myFunc(_ ptr: UnsafePointer, _ len: CInt) -> CInt { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: Span) -> CInt { // CHECK-NEXT: return unsafe ptr.withUnsafeBufferPointer { _ptrPtr in // CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: ptr.count)!) diff --git a/test/Macros/SwiftifyImport/CountedBy/SpanAndUnsafeBuffer.swift b/test/Macros/SwiftifyImport/CountedBy/SpanAndUnsafeBuffer.swift index b7774a244aa7..ec433190d1df 100644 --- a/test/Macros/SwiftifyImport/CountedBy/SpanAndUnsafeBuffer.swift +++ b/test/Macros/SwiftifyImport/CountedBy/SpanAndUnsafeBuffer.swift @@ -8,7 +8,7 @@ func myFunc(_ ptr1: UnsafePointer, _ len1: CInt, _ ptr2: UnsafePointer, _ len2: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr1: Span, _ ptr2: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe ptr1.withUnsafeBufferPointer { _ptr1Ptr in // CHECK-NEXT: return unsafe myFunc(_ptr1Ptr.baseAddress!, CInt(exactly: ptr1.count)!, ptr2.baseAddress!, CInt(exactly: ptr2.count)!) diff --git a/test/Macros/SwiftifyImport/CountedBy/Unwrapped.swift b/test/Macros/SwiftifyImport/CountedBy/Unwrapped.swift index 8677adf97a74..2bdcde465e4e 100644 --- a/test/Macros/SwiftifyImport/CountedBy/Unwrapped.swift +++ b/test/Macros/SwiftifyImport/CountedBy/Unwrapped.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafePointer!, _ len: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CxxSpan/LifetimeboundSpan.swift b/test/Macros/SwiftifyImport/CxxSpan/LifetimeboundSpan.swift index 17ed319fa0fe..7f279e6c679f 100644 --- a/test/Macros/SwiftifyImport/CxxSpan/LifetimeboundSpan.swift +++ b/test/Macros/SwiftifyImport/CxxSpan/LifetimeboundSpan.swift @@ -57,32 +57,32 @@ func myFunc8(_ ptr: UnsafeRawPointer, _ span: SpanOfInt, _ count: CInt, _ size: func myFunc9(_ span: MutableSpanOfInt) -> MutableSpanOfInt { } -// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) +// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) public // CHECK-NEXT: func myFunc(_ span: Span) -> Span { // CHECK-NEXT: return unsafe _cxxOverrideLifetime(Span(_unsafeCxxSpan: unsafe myFunc(SpanOfInt(span))), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(borrow vec) @_disfavoredOverload +// CHECK: @_alwaysEmitIntoClient @lifetime(borrow vec) @_disfavoredOverload public // CHECK-NEXT: func myFunc2(_ vec: borrowing VecOfInt) -> Span { // CHECK-NEXT: return unsafe _cxxOverrideLifetime(Span(_unsafeCxxSpan: unsafe myFunc2(vec)), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(copy span1, copy span2) +// CHECK: @_alwaysEmitIntoClient @lifetime(copy span1, copy span2) public // CHECK-NEXT: func myFunc3(_ span1: Span, _ span2: Span) -> Span { // CHECK-NEXT: return unsafe _cxxOverrideLifetime(Span(_unsafeCxxSpan: unsafe myFunc3(SpanOfInt(span1), SpanOfInt(span2))), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(borrow vec, copy span) +// CHECK: @_alwaysEmitIntoClient @lifetime(borrow vec, copy span) public // CHECK-NEXT: func myFunc4(_ vec: borrowing VecOfInt, _ span: Span) -> Span { // CHECK-NEXT: return unsafe _cxxOverrideLifetime(Span(_unsafeCxxSpan: unsafe myFunc4(vec, SpanOfInt(span))), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(borrow self) @_disfavoredOverload +// CHECK: @_alwaysEmitIntoClient @lifetime(borrow self) @_disfavoredOverload public // CHECK-NEXT: func myFunc5() -> Span { // CHECK-NEXT: return unsafe _cxxOverrideLifetime(Span(_unsafeCxxSpan: unsafe myFunc5()), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) +// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) public // CHECK-NEXT: func myFunc6(_ span: Span, _ ptr: RawSpan, _ count: CInt, _ size: CInt) -> Span { // CHECK-NEXT: let _ptrCount: some BinaryInteger = count * size // CHECK-NEXT: if ptr.byteCount < _ptrCount || _ptrCount < 0 { @@ -93,7 +93,7 @@ func myFunc9(_ span: MutableSpanOfInt) -> MutableSpanOfInt { // CHECK-NEXT: }), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) +// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) public // CHECK-NEXT: func myFunc7(_ span: Span, _ ptr: RawSpan, _ count: CInt, _ size: CInt) -> Span { // CHECK-NEXT: let _ptrCount: some BinaryInteger = count * size // CHECK-NEXT: if ptr.byteCount < _ptrCount || _ptrCount < 0 { @@ -104,7 +104,7 @@ func myFunc9(_ span: MutableSpanOfInt) -> MutableSpanOfInt { // CHECK-NEXT: }), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) +// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) public // CHECK-NEXT: func myFunc8(_ ptr: RawSpan, _ span: Span, _ count: CInt, _ size: CInt) -> Span { // CHECK-NEXT: let _ptrCount: some BinaryInteger = count * size // CHECK-NEXT: if ptr.byteCount < _ptrCount || _ptrCount < 0 { @@ -115,7 +115,7 @@ func myFunc9(_ span: MutableSpanOfInt) -> MutableSpanOfInt { // CHECK-NEXT: }), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) @lifetime(span: copy span) +// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) @lifetime(span: copy span) public // CHECK-NEXT: func myFunc9(_ span: inout MutableSpan) -> MutableSpan { // CHECK-NEXT: return unsafe _cxxOverrideLifetime(MutableSpan(_unsafeCxxSpan: unsafe span.withUnsafeMutableBufferPointer { _spanPtr in // CHECK-NEXT: return unsafe myFunc9(MutableSpanOfInt(_spanPtr)) diff --git a/test/Macros/SwiftifyImport/CxxSpan/NoEscapeSpan.swift b/test/Macros/SwiftifyImport/CxxSpan/NoEscapeSpan.swift index 84474ac42795..c5298f5863cf 100644 --- a/test/Macros/SwiftifyImport/CxxSpan/NoEscapeSpan.swift +++ b/test/Macros/SwiftifyImport/CxxSpan/NoEscapeSpan.swift @@ -25,26 +25,26 @@ func myFunc3(_ span: MutableSpanOfInt, _ secondSpan: SpanOfInt) { func myFunc4(_ span: MutableSpanOfInt, _ secondSpan: MutableSpanOfInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ span: Span, _ secondSpan: SpanOfInt) { // CHECK-NEXT: return unsafe myFunc(SpanOfInt(span), secondSpan) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(span: copy span) +// CHECK: @_alwaysEmitIntoClient @lifetime(span: copy span) public // CHECK-NEXT: func myFunc2(_ span: inout MutableSpan, _ secondSpan: MutableSpanOfInt) { // CHECK-NEXT: return unsafe span.withUnsafeMutableBufferPointer { _spanPtr in // CHECK-NEXT: return unsafe myFunc2(MutableSpanOfInt(_spanPtr), secondSpan) // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(span: copy span) +// CHECK: @_alwaysEmitIntoClient @lifetime(span: copy span) public // CHECK-NEXT: func myFunc3(_ span: inout MutableSpan, _ secondSpan: Span) { // CHECK-NEXT: return unsafe span.withUnsafeMutableBufferPointer { _spanPtr in // CHECK-NEXT: return unsafe myFunc3(MutableSpanOfInt(_spanPtr), SpanOfInt(secondSpan)) // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(span: copy span) @lifetime(secondSpan: copy secondSpan) +// CHECK: @_alwaysEmitIntoClient @lifetime(span: copy span) @lifetime(secondSpan: copy secondSpan) public // CHECK-NEXT: func myFunc4(_ span: inout MutableSpan, _ secondSpan: inout MutableSpan) { // CHECK-NEXT: return unsafe secondSpan.withUnsafeMutableBufferPointer { _secondSpanPtr in // CHECK-NEXT: return unsafe span.withUnsafeMutableBufferPointer { _spanPtr in diff --git a/test/Macros/SwiftifyImport/MacroErrors/UnexpectedCountType.swift b/test/Macros/SwiftifyImport/MacroErrors/UnexpectedCountType.swift index 6a230425c477..30bc51fce4b8 100644 --- a/test/Macros/SwiftifyImport/MacroErrors/UnexpectedCountType.swift +++ b/test/Macros/SwiftifyImport/MacroErrors/UnexpectedCountType.swift @@ -9,7 +9,7 @@ func myFunc(_ ptr: UnsafePointer, _ len: String) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer) { // CHECK-NEXT: myFunc(ptr.baseAddress!, String(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/MultipleParams.swift b/test/Macros/SwiftifyImport/SizedBy/MultipleParams.swift index 912c9dbcd882..be505e51b9ef 100644 --- a/test/Macros/SwiftifyImport/SizedBy/MultipleParams.swift +++ b/test/Macros/SwiftifyImport/SizedBy/MultipleParams.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafeRawPointer, _ size: CInt, _ ptr2: UnsafeRawPointer, _ size2: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeRawBufferPointer, _ ptr2: UnsafeRawBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!, ptr2.baseAddress!, CInt(exactly: ptr2.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/Mutable.swift b/test/Macros/SwiftifyImport/SizedBy/Mutable.swift index 1e8e9d9023d8..2ee9bfafeaa9 100644 --- a/test/Macros/SwiftifyImport/SizedBy/Mutable.swift +++ b/test/Macros/SwiftifyImport/SizedBy/Mutable.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafeMutableRawPointer, _ size: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeMutableRawBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/MutableRawSpan.swift b/test/Macros/SwiftifyImport/SizedBy/MutableRawSpan.swift index 912329466aca..a5446e853506 100644 --- a/test/Macros/SwiftifyImport/SizedBy/MutableRawSpan.swift +++ b/test/Macros/SwiftifyImport/SizedBy/MutableRawSpan.swift @@ -7,7 +7,7 @@ func myFunc(_ ptr: UnsafeMutableRawPointer, _ size: CInt) { } -// CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) +// CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) public // CHECK-NEXT: func myFunc(_ ptr: inout MutableRawSpan) { // CHECK-NEXT: return unsafe ptr.withUnsafeMutableBytes { _ptrPtr in // CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: ptr.byteCount)!) diff --git a/test/Macros/SwiftifyImport/SizedBy/Nullable.swift b/test/Macros/SwiftifyImport/SizedBy/Nullable.swift index 6a8059725c4c..9f33c53fca94 100644 --- a/test/Macros/SwiftifyImport/SizedBy/Nullable.swift +++ b/test/Macros/SwiftifyImport/SizedBy/Nullable.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafeRawPointer?, _ size: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeRawBufferPointer?) { // CHECK-NEXT: return unsafe myFunc(ptr?.baseAddress, CInt(exactly: ptr?.count ?? 0)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/Opaque.swift b/test/Macros/SwiftifyImport/SizedBy/Opaque.swift index c396d7f9cc29..5588f4fed7f3 100644 --- a/test/Macros/SwiftifyImport/SizedBy/Opaque.swift +++ b/test/Macros/SwiftifyImport/SizedBy/Opaque.swift @@ -26,29 +26,29 @@ func nullableSpan(_ ptr: OpaquePointer?, _ size: CInt) { func impNullableSpan(_ ptr: OpaquePointer!, _ size: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func nonnullUnsafeRawBufferPointer(_ ptr: UnsafeRawBufferPointer) { // CHECK-NEXT: return unsafe nonnullUnsafeRawBufferPointer(OpaquePointer(ptr.baseAddress!), CInt(exactly: ptr.count)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func nullableUnsafeRawBufferPointer(_ ptr: UnsafeRawBufferPointer?) { // CHECK-NEXT: return unsafe nullableUnsafeRawBufferPointer(OpaquePointer(ptr?.baseAddress), CInt(exactly: ptr?.count ?? 0)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func impNullableUnsafeRawBufferPointer(_ ptr: UnsafeRawBufferPointer) { // CHECK-NEXT: return unsafe impNullableUnsafeRawBufferPointer(OpaquePointer(ptr.baseAddress!), CInt(exactly: ptr.count)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func nonnullSpan(_ ptr: RawSpan) { // CHECK-NEXT: return unsafe ptr.withUnsafeBytes { _ptrPtr in // CHECK-NEXT: return unsafe nonnullSpan(OpaquePointer(_ptrPtr.baseAddress!), CInt(exactly: ptr.byteCount)!) // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func nullableSpan(_ ptr: RawSpan?) { // CHECK-NEXT: return { () in // CHECK-NEXT: return if ptr == nil { @@ -61,7 +61,7 @@ func impNullableSpan(_ ptr: OpaquePointer!, _ size: CInt) { // CHECK-NEXT: }() // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func impNullableSpan(_ ptr: RawSpan) { // CHECK-NEXT: return unsafe ptr.withUnsafeBytes { _ptrPtr in // CHECK-NEXT: return unsafe impNullableSpan(OpaquePointer(_ptrPtr.baseAddress!), CInt(exactly: ptr.byteCount)!) diff --git a/test/Macros/SwiftifyImport/SizedBy/Return.swift b/test/Macros/SwiftifyImport/SizedBy/Return.swift index 61dcbc976486..7fa2df20b79b 100644 --- a/test/Macros/SwiftifyImport/SizedBy/Return.swift +++ b/test/Macros/SwiftifyImport/SizedBy/Return.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafeRawPointer, _ size: CInt) -> CInt { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeRawBufferPointer) -> CInt { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/SharedCount.swift b/test/Macros/SwiftifyImport/SizedBy/SharedCount.swift index 2d331b9c1980..0fc5baa76fa2 100644 --- a/test/Macros/SwiftifyImport/SizedBy/SharedCount.swift +++ b/test/Macros/SwiftifyImport/SizedBy/SharedCount.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafeRawPointer, _ ptr2: UnsafeRawPointer, _ size: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeRawBufferPointer, _ ptr2: UnsafeRawBufferPointer, _ size: CInt) { // CHECK-NEXT: let _ptrCount: some BinaryInteger = size // CHECK-NEXT: if ptr.count < _ptrCount || _ptrCount < 0 { diff --git a/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpan.swift b/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpan.swift index c7ed798638e3..e3bd9d809868 100644 --- a/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpan.swift +++ b/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpan.swift @@ -7,7 +7,7 @@ func myFunc(_ ptr: UnsafeRawPointer, _ size: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: RawSpan) { // CHECK-NEXT: return unsafe ptr.withUnsafeBytes { _ptrPtr in // CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: ptr.byteCount)!) diff --git a/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpanWithReturn.swift b/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpanWithReturn.swift index 92586787da5b..e64079372526 100644 --- a/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpanWithReturn.swift +++ b/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpanWithReturn.swift @@ -7,7 +7,7 @@ func myFunc(_ ptr: UnsafeRawPointer, _ size: CInt) -> CInt { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: RawSpan) -> CInt { // CHECK-NEXT: return unsafe ptr.withUnsafeBytes { _ptrPtr in // CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: ptr.byteCount)!) diff --git a/test/Macros/SwiftifyImport/SizedBy/SimpleSize.swift b/test/Macros/SwiftifyImport/SizedBy/SimpleSize.swift index 803d81e788d1..e9ce505ecdd4 100644 --- a/test/Macros/SwiftifyImport/SizedBy/SimpleSize.swift +++ b/test/Macros/SwiftifyImport/SizedBy/SimpleSize.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafeRawPointer, _ size: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeRawBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/SizeExpr.swift b/test/Macros/SwiftifyImport/SizedBy/SizeExpr.swift index 506ae8da2b68..33acde7225e5 100644 --- a/test/Macros/SwiftifyImport/SizedBy/SizeExpr.swift +++ b/test/Macros/SwiftifyImport/SizedBy/SizeExpr.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafeRawPointer, _ size: CInt, _ count: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeRawBufferPointer, _ size: CInt, _ count: CInt) { // CHECK-NEXT: let _ptrCount: some BinaryInteger = size * count // CHECK-NEXT: if ptr.count < _ptrCount || _ptrCount < 0 { diff --git a/test/Macros/SwiftifyImport/SizedBy/Unwrapped.swift b/test/Macros/SwiftifyImport/SizedBy/Unwrapped.swift index c18be3ae42f6..031fd76c375f 100644 --- a/test/Macros/SwiftifyImport/SizedBy/Unwrapped.swift +++ b/test/Macros/SwiftifyImport/SizedBy/Unwrapped.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafeRawPointer!, _ len: CInt) { } -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient public // CHECK-NEXT: func myFunc(_ ptr: UnsafeRawBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } From 9e89957d2ec1b2c891ff1ac073a424a60ce93bfc Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Wed, 19 Feb 2025 21:44:52 -0800 Subject: [PATCH 05/10] [ClangImporter] Attach _SwiftifyImportProtocol to imported protocols with bounds attributes This creates safe overloads for any methods in the protocol annotated with bounds information. rdar://144335990 --- lib/AST/ConformanceLookup.cpp | 25 +- lib/ClangImporter/ImportDecl.cpp | 260 +++++++++++++---- lib/ClangImporter/ImporterImpl.h | 1 + lib/DriverTool/swift_api_digester_main.cpp | 1 + .../SwiftMacros/SwiftifyImportMacro.swift | 270 ++++++++++++++---- lib/Sema/TypeCheckMacros.cpp | 7 + stdlib/public/Cxx/CxxSpan.swift | 44 +-- stdlib/public/Cxx/CxxVector.swift | 2 +- stdlib/public/core/SwiftifyImport.swift | 45 ++- .../counted-by-in-namespace.swift | 4 +- .../swiftify-import/counted-by-method.swift | 6 +- .../counted-by-in-class-noescape.swift | 200 +++++++++++++ .../swiftify-import/counted-by-in-class.swift | 45 ++- .../counted-by-protocol-noescape.swift | 138 +++++++++ .../swiftify-import/counted-by-protocol.swift | 107 +++++++ .../SwiftifyImport/CountedBy/CountExpr.swift | 4 +- .../CountedBy/MultipleParams.swift | 4 +- .../SwiftifyImport/CountedBy/Mutable.swift | 4 +- .../CountedBy/MutableSpan.swift | 6 +- .../CountedBy/NamedParams.swift | 24 +- .../SwiftifyImport/CountedBy/Nullable.swift | 24 +- .../CountedBy/PointerReturn.swift | 24 +- .../SwiftifyImport/CountedBy/Protocol.swift | 67 +++-- .../CountedBy/QualifiedTypes.swift | 8 +- .../SwiftifyImport/CountedBy/Return.swift | 4 +- .../CountedBy/SharedCount.swift | 4 +- .../CountedBy/SimpleCount.swift | 4 +- .../SwiftifyImport/CountedBy/SimpleSpan.swift | 6 +- .../CountedBy/SimpleSpanWithReturn.swift | 6 +- .../CountedBy/SpanAndUnsafeBuffer.swift | 6 +- .../SwiftifyImport/CountedBy/Unwrapped.swift | 4 +- .../CxxSpan/LifetimeboundSpan.swift | 54 ++-- .../SwiftifyImport/CxxSpan/NoEscapeSpan.swift | 16 +- .../MacroErrors/UnexpectedCountType.swift | 4 +- .../SizedBy/MultipleParams.swift | 4 +- .../SwiftifyImport/SizedBy/Mutable.swift | 4 +- .../SizedBy/MutableRawSpan.swift | 6 +- .../SwiftifyImport/SizedBy/Nullable.swift | 4 +- .../SwiftifyImport/SizedBy/Opaque.swift | 30 +- .../SwiftifyImport/SizedBy/Return.swift | 4 +- .../SwiftifyImport/SizedBy/SharedCount.swift | 4 +- .../SizedBy/SimpleRawSpan.swift | 6 +- .../SizedBy/SimpleRawSpanWithReturn.swift | 6 +- .../SwiftifyImport/SizedBy/SimpleSize.swift | 4 +- .../SwiftifyImport/SizedBy/SizeExpr.swift | 4 +- .../SwiftifyImport/SizedBy/Unwrapped.swift | 4 +- 46 files changed, 1168 insertions(+), 340 deletions(-) create mode 100644 test/Interop/ObjC/swiftify-import/counted-by-in-class-noescape.swift create mode 100644 test/Interop/ObjC/swiftify-import/counted-by-protocol-noescape.swift create mode 100644 test/Interop/ObjC/swiftify-import/counted-by-protocol.swift diff --git a/lib/AST/ConformanceLookup.cpp b/lib/AST/ConformanceLookup.cpp index 671b2e2e3caa..5719d1d1720f 100644 --- a/lib/AST/ConformanceLookup.cpp +++ b/lib/AST/ConformanceLookup.cpp @@ -533,6 +533,22 @@ static ProtocolConformanceRef getPackTypeConformance( PackConformance::get(type, protocol, patternConformances)); } +static bool shouldExpandExtensionMacro(Evaluator &evaluator, NominalTypeDecl *nominal) { + if (evaluator.hasActiveRequest(ExpandExtensionMacros{nominal})) { + return false; + } + + // Expanding an extension macro for this type will require pretty printing the node, + // leading to evaluation of it's members. Once the macro expansion requrest has started + // it's too late to check for cycles. + for (auto member : nominal->getMembers()) + if (auto VD = dyn_cast(member)) + if (evaluator.hasActiveRequest(InterfaceTypeRequest{VD})) + return false; + + return true; +} + ProtocolConformanceRef LookupConformanceInModuleRequest::evaluate( Evaluator &evaluator, LookupConformanceDescriptor desc) const { @@ -670,10 +686,11 @@ LookupConformanceInModuleRequest::evaluate( // extension macro can generate a conformance to the // given protocol, but conformance macros do not specify // that information upfront. - (void)evaluateOrDefault( - ctx.evaluator, - ExpandExtensionMacros{nominal}, - { }); + if (shouldExpandExtensionMacro(ctx.evaluator, nominal)) + (void)evaluateOrDefault( + evaluator, + ExpandExtensionMacros{nominal}, + { }); // Find the root conformance in the nominal type declaration's // conformance lookup table. diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 93dc9c20abfe..f2d0f6feecde 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -15,10 +15,12 @@ //===----------------------------------------------------------------------===// #include "CFTypeInfo.h" +#include "ClangAdapter.h" #include "ClangDerivedConformances.h" #include "ImporterImpl.h" #include "SwiftDeclSynthesizer.h" #include "swift/AST/ASTContext.h" +#include "swift/AST/ASTPrinter.h" #include "swift/AST/Attr.h" #include "swift/AST/AvailabilityInference.h" #include "swift/AST/Builtins.h" @@ -5810,6 +5812,8 @@ namespace { result->setMemberLoader(&Impl, 0); + Impl.swiftifyProtocol(result); + return result; } @@ -6031,6 +6035,8 @@ namespace { } } } + + Impl.swiftifyProtocol(result); return result; } @@ -9039,18 +9045,25 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) { } namespace { +class SwiftifyInfoPrinter; +static bool swiftifyImpl(SwiftifyInfoPrinter &printer, const FuncDecl *MappedDecl); + class SwiftifyInfoPrinter { public: static const ssize_t SELF_PARAM_INDEX = -2; static const ssize_t RETURN_VALUE_INDEX = -1; + +protected: clang::ASTContext &ctx; + ASTContext &SwiftContext; llvm::raw_ostream &out; bool firstParam = true; llvm::StringMap typeMapping; - SwiftifyInfoPrinter(clang::ASTContext &ctx, llvm::raw_ostream &out) - : ctx(ctx), out(out) { - out << "@_SwiftifyImport("; +public: + SwiftifyInfoPrinter(clang::ASTContext &ctx, ASTContext &SwiftContext, llvm::raw_ostream &out) + : ctx(ctx), SwiftContext(SwiftContext), out(out) { + out << "("; } ~SwiftifyInfoPrinter() { out << ")"; } @@ -9116,15 +9129,20 @@ class SwiftifyInfoPrinter { out << "]"; } -private: - void printSeparator() { - if (!firstParam) { - out << ", "; - } else { - firstParam = false; + void printAvailability() { + printSeparator(); + out << "availability: ["; + if (!SwiftContext.LangOpts.Target.isOSDarwin() && !SwiftContext.LangOpts.Target.isDriverKit()) { + out << ":]"; + return; } + printAvailabilityOfType("Span"); + printSeparator(); + printAvailabilityOfType("MutableSpan"); + out << "]"; } +private: void printParamOrReturn(ssize_t pointerIndex) { if (pointerIndex == SELF_PARAM_INDEX) out << ".self"; @@ -9133,75 +9151,191 @@ class SwiftifyInfoPrinter { else out << ".param(" << pointerIndex + 1 << ")"; } + + ValueDecl *getDecl(StringRef DeclName) { + SmallVector decls; + SwiftContext.lookupInSwiftModule(DeclName, decls); + assert(decls.size() == 1); + if (decls.size() != 1) return nullptr; + return decls[0]; + } + + StringRef getDarwinOSString() { + auto Target = SwiftContext.LangOpts.Target; + if (Target.isMacOSX()) { + return "macOS"; + } else if (Target.isTvOS()) { + return "tvOS"; + } else if (Target.isiOS()) { + return "iOS"; + } else if (Target.isWatchOS()) { + return "watchOS"; + } else if (Target.isXROS()) { + return "visionOS"; + } + llvm_unreachable("unknown darwin OS"); + } + + void printAvailabilityOfType(StringRef Name) { + ValueDecl *D = getDecl(Name); + auto Availability = AvailabilityInference::availableRange(D); + + out << "\"" << Name << "\":" << "\"" << getDarwinOSString() << " " << Availability.getVersionString() << "\""; + } + +protected: + void printSeparator() { + if (!firstParam) { + out << ", "; + } else { + firstParam = false; + } + } }; -} // namespace -void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) { - if (!SwiftContext.LangOpts.hasFeature(Feature::SafeInteropWrappers)) - return; - auto ClangDecl = - dyn_cast_or_null(MappedDecl->getClangDecl()); - if (!ClangDecl) - return; +class SwiftifyProtocolInfoPrinter : public SwiftifyInfoPrinter { +public: + SwiftifyProtocolInfoPrinter(clang::ASTContext &ctx, ASTContext &SwiftContext, llvm::raw_ostream &out) + : SwiftifyInfoPrinter(ctx, SwiftContext, out) {} + + bool printMethod(const FuncDecl *Method) { + // don't emit .method() if we know it's going to be empty + if (!isa_and_nonnull(Method->getClangDecl())) + return false; + + printSeparator(); + out << ".method(signature: \""; + printMethodSignature(Method); + out << "\", paramInfo: ["; + // reset firstParam inside paramInfo array. At this point firstParam will + // always be false, so no need to save the current value. + assert(!firstParam); + firstParam = true; + bool hadAttributes = swiftifyImpl(*this, Method); + firstParam = false; + out << "])"; + return hadAttributes; + } + +private: + void printMethodSignature(const FuncDecl *Method) { + auto options = PrintOptions::printForDiagnostics(AccessLevel::Private, true); + StreamPrinter printer(out); + Method->print(printer, options); + } +}; + +static bool swiftifyImpl(SwiftifyInfoPrinter &printer, const FuncDecl *MappedDecl) { + const clang::Decl *ClangDecl = MappedDecl->getClangDecl(); + auto FuncD = dyn_cast(ClangDecl); + auto MethodD = dyn_cast(ClangDecl); + assert(FuncD || MethodD); - llvm::SmallString<128> MacroString; // We only attach the macro if it will produce an overload. Any __counted_by // will produce an overload, since UnsafeBufferPointer is still an improvement // over UnsafePointer, but std::span will only produce an overload if it also // has lifetime information, since std::span already contains bounds info. bool attachMacro = false; - { - llvm::raw_svector_ostream out(MacroString); - SwiftifyInfoPrinter printer(getClangASTContext(), out); - bool returnIsStdSpan = printer.registerStdSpanTypeMapping( - MappedDecl->getResultInterfaceType(), ClangDecl->getReturnType()); - if (auto CAT = - ClangDecl->getReturnType()->getAs()) { - printer.printCountedBy(CAT, SwiftifyInfoPrinter::RETURN_VALUE_INDEX); - attachMacro = true; - } - bool returnHasLifetimeInfo = false; - if (SwiftDeclConverter::getImplicitObjectParamAnnotation< - clang::LifetimeBoundAttr>(ClangDecl)) { - printer.printLifetimeboundReturn(SwiftifyInfoPrinter::SELF_PARAM_INDEX, - true); + clang::QualType returnType = FuncD ? FuncD->getReturnType() : MethodD->getReturnType(); + bool returnIsStdSpan = printer.registerStdSpanTypeMapping( + MappedDecl->getResultInterfaceType(), returnType); + if (auto CAT = returnType->getAs()) { + printer.printCountedBy(CAT, SwiftifyInfoPrinter::RETURN_VALUE_INDEX); + attachMacro = true; + } + bool returnHasLifetimeInfo = false; + if (FuncD && SwiftDeclConverter::getImplicitObjectParamAnnotation(FuncD)) { + printer.printLifetimeboundReturn(SwiftifyInfoPrinter::SELF_PARAM_INDEX, + true); + returnHasLifetimeInfo = true; + } + + auto parameters = FuncD ? FuncD->parameters() : MethodD->parameters(); + for (auto [index, clangParam] : llvm::enumerate(parameters)) { + auto clangParamTy = clangParam->getType(); + auto swiftParam = MappedDecl->getParameters()->get(index); + bool paramHasBoundsInfo = false; + if (auto CAT = clangParamTy->getAs()) { + printer.printCountedBy(CAT, index); + attachMacro = paramHasBoundsInfo = true; + } + bool paramIsStdSpan = printer.registerStdSpanTypeMapping( + swiftParam->getInterfaceType(), clangParamTy); + paramHasBoundsInfo |= paramIsStdSpan; + + bool paramHasLifetimeInfo = false; + if (clangParam->hasAttr()) { + printer.printNonEscaping(index); + paramHasLifetimeInfo = true; + } + if (clangParam->hasAttr()) { + printer.printLifetimeboundReturn( + index, !paramHasBoundsInfo && + swiftParam->getInterfaceType()->isEscapable()); + paramHasLifetimeInfo = true; returnHasLifetimeInfo = true; } - for (auto [index, clangParam] : llvm::enumerate(ClangDecl->parameters())) { - auto clangParamTy = clangParam->getType(); - auto swiftParam = MappedDecl->getParameters()->get(index); - bool paramHasBoundsInfo = false; - if (auto CAT = clangParamTy->getAs()) { - printer.printCountedBy(CAT, index); - attachMacro = paramHasBoundsInfo = true; - } - bool paramIsStdSpan = printer.registerStdSpanTypeMapping( - swiftParam->getInterfaceType(), clangParamTy); - paramHasBoundsInfo |= paramIsStdSpan; - - bool paramHasLifetimeInfo = false; - if (clangParam->hasAttr()) { - printer.printNonEscaping(index); - paramHasLifetimeInfo = true; - } - if (clangParam->hasAttr()) { - printer.printLifetimeboundReturn( - index, !paramHasBoundsInfo && - swiftParam->getInterfaceType()->isEscapable()); - paramHasLifetimeInfo = true; - returnHasLifetimeInfo = true; - } - if (paramIsStdSpan && paramHasLifetimeInfo) - attachMacro = true; - } - if (returnIsStdSpan && returnHasLifetimeInfo) + if (paramIsStdSpan && paramHasLifetimeInfo) attachMacro = true; + } + if (returnIsStdSpan && returnHasLifetimeInfo) + attachMacro = true; + + return attachMacro; +} +} // namespace + +void ClangImporter::Implementation::swiftifyProtocol( + NominalTypeDecl *MappedDecl) { + if (!SwiftContext.LangOpts.hasFeature(Feature::SafeInteropWrappers)) + return; + if (!isa(MappedDecl)) + return; + + llvm::SmallString<128> MacroString; + { + llvm::raw_svector_ostream out(MacroString); + out << "@_SwiftifyImportProtocol"; + + bool hasBoundsAttributes = false; + SwiftifyProtocolInfoPrinter printer(getClangASTContext(), SwiftContext, out); + for (Decl *SwiftMember : cast(MappedDecl)->getAllMembers()) { + FuncDecl *SwiftDecl = dyn_cast(SwiftMember); + if (!SwiftDecl) + continue; + hasBoundsAttributes |= + printer.printMethod(SwiftDecl); + } + + if (!hasBoundsAttributes) + return; + printer.printAvailability(); + printer.printTypeMapping(); + } + + importNontrivialAttribute(MappedDecl, MacroString); +} + +void ClangImporter::Implementation::swiftify( + FuncDecl *MappedDecl) { + if (!SwiftContext.LangOpts.hasFeature(Feature::SafeInteropWrappers)) + return; + if (!isa_and_nonnull(MappedDecl->getClangDecl())) + return; + + llvm::SmallString<128> MacroString; + { + llvm::raw_svector_ostream out(MacroString); + out << "@_SwiftifyImport"; + + SwiftifyInfoPrinter printer(getClangASTContext(), SwiftContext, out); + if (!swiftifyImpl(printer, MappedDecl)) + return; printer.printTypeMapping(); } - if (attachMacro) - importNontrivialAttribute(MappedDecl, MacroString); + importNontrivialAttribute(MappedDecl, MacroString); } static bool isUsingMacroName(clang::SourceManager &SM, diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h index 870e68a2152e..93ea7603482c 100644 --- a/lib/ClangImporter/ImporterImpl.h +++ b/lib/ClangImporter/ImporterImpl.h @@ -1755,6 +1755,7 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation void importSwiftAttrAttributes(Decl *decl); void swiftify(FuncDecl *MappedDecl); + void swiftifyProtocol(NominalTypeDecl *MappedDecl); /// Find the lookup table that corresponds to the given Clang module. /// diff --git a/lib/DriverTool/swift_api_digester_main.cpp b/lib/DriverTool/swift_api_digester_main.cpp index e90269541f93..340a6a29b72a 100644 --- a/lib/DriverTool/swift_api_digester_main.cpp +++ b/lib/DriverTool/swift_api_digester_main.cpp @@ -652,6 +652,7 @@ class PrunePass : public MatchedNodeListener, public SDKTreeDiffPass { ProtocolReqAllowlist(std::move(prAllowlist)), DebugMapping(DebugMapping) {} + void diagnoseMissingAvailable(SDKNodeDecl *D) { // For extensions of external types, we diagnose individual member's missing // available attribute instead of the extension itself. diff --git a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift index fd062295994a..cb39aa6b07a8 100644 --- a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift +++ b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift @@ -545,7 +545,7 @@ struct CxxSpanReturnThunkBuilder: SpanBoundsThunkBuilder { } else { "MutableSpan" } - return "unsafe _cxxOverrideLifetime(\(raw: cast)(_unsafeCxxSpan: \(call)), copying: ())" + return "unsafe _swiftifyOverrideLifetime(\(raw: cast)(_unsafeCxxSpan: \(call)), copying: ())" } } @@ -701,10 +701,14 @@ struct CountedOrSizedReturnPointerThunkBuilder: PointerBoundsThunkBuilder { }() """ } - return - """ - unsafe \(raw: cast)(\(raw: startLabel): \(call), count: Int(\(countExpr))) + var expr = ExprSyntax( """ + \(raw: cast)(\(raw: startLabel): \(call), count: Int(\(countExpr))) + """) + if generateSpan { + expr = "_swiftifyOverrideLifetime(\(expr), copying: ())" + } + return "unsafe \(expr)" } } @@ -778,6 +782,14 @@ struct CountedOrSizedPointerThunkBuilder: ParamBoundsThunkBuilder, PointerBounds let argExpr = ExprSyntax("\(unwrappedName).baseAddress") assert(args[index] == nil) args[index] = try castPointerToOpaquePointer(unwrapIfNonnullable(argExpr)) + + if skipTrivialCount { + if let countVar = countExpr.as(DeclReferenceExprSyntax.self) { + let i = try getParameterIndexForDeclRef(signature.parameterClause.parameters, countVar) + args[i] = castIntToTargetType( + expr: "\(unwrappedName).count", type: getParam(signature, i).type) + } + } let call = try base.buildFunctionCall(args) let ptrRef = unwrapIfNullable(ExprSyntax(DeclReferenceExprSyntax(baseName: name))) @@ -851,11 +863,13 @@ struct CountedOrSizedPointerThunkBuilder: ParamBoundsThunkBuilder, PointerBounds nullArgs[index] = ExprSyntax(NilLiteralExprSyntax(nilKeyword: .keyword(.nil))) return ExprSyntax( """ - { () in return if \(name) == nil { + { () in + return if \(name) == nil { \(try base.buildFunctionCall(nullArgs)) } else { \(unwrappedCall) - } }() + } + }() """) } return unwrappedCall @@ -1057,14 +1071,7 @@ func parseLifetimeDependence(_ enumConstructorExpr: FunctionCallExprSyntax) thro return (pointer, dependence) } -func parseTypeMappingParam(_ paramAST: LabeledExprSyntax?) throws -> [String: String]? { - guard let unwrappedParamAST = paramAST else { - return nil - } - let paramExpr = unwrappedParamAST.expression - guard let dictExpr = paramExpr.as(DictionaryExprSyntax.self) else { - return nil - } +func parseStringLiteralDict(_ dictExpr: DictionaryExprSyntax) throws -> [String: String] { var dict: [String: String] = [:] switch dictExpr.content { case .colon(_): @@ -1086,6 +1093,32 @@ func parseTypeMappingParam(_ paramAST: LabeledExprSyntax?) throws -> [String: St return dict } +func parseStringMappingParam(_ paramAST: LabeledExprSyntax?, paramName: String) throws -> [String: + String]? +{ + guard let unwrappedParamAST = paramAST else { + return nil + } + guard let label = unwrappedParamAST.label else { + return nil + } + if label.trimmed.text != paramName { + return nil + } + let paramExpr = unwrappedParamAST.expression + guard let dictExpr = paramExpr.as(DictionaryExprSyntax.self) else { + return nil + } + return try parseStringLiteralDict(dictExpr) +} + +func parseTypeMappingParam(_ paramAST: LabeledExprSyntax?) throws -> [String: String]? { + return try parseStringMappingParam(paramAST, paramName: "typeMappings") +} +func parseAvailabilityParam(_ paramAST: LabeledExprSyntax?) throws -> [String: String]? { + return try parseStringMappingParam(paramAST, paramName: "availability") +} + func parseCxxSpansInSignature( _ signature: FunctionSignatureSyntax, _ typeMappings: [String: String]? @@ -1303,6 +1336,23 @@ func isMutableSpan(_ type: TypeSyntax) -> Bool { return name == "MutableSpan" || name == "MutableRawSpan" } +func isImmutableSpan(_ type: TypeSyntax) -> Bool { + if let optType = type.as(OptionalTypeSyntax.self) { + return isImmutableSpan(optType.wrappedType) + } + if let impOptType = type.as(ImplicitlyUnwrappedOptionalTypeSyntax.self) { + return isImmutableSpan(impOptType.wrappedType) + } + if let attrType = type.as(AttributedTypeSyntax.self) { + return isImmutableSpan(attrType.baseType) + } + guard let identifierType = type.as(IdentifierTypeSyntax.self) else { + return false + } + let name = identifierType.name.text + return name == "Span" || name == "RawSpan" +} + func containsLifetimeAttr(_ attrs: AttributeListSyntax, for paramName: TokenSyntax) -> Bool { for elem in attrs { guard let attr = elem.as(AttributeSyntax.self) else { @@ -1350,13 +1400,78 @@ func paramLifetimeAttributes( return defaultLifetimes } -func constructOverloadFunction(forDecl funcDecl: FunctionDeclSyntax, - args arguments: [ExprSyntax], - typeMappings: [String: String]?) throws -> DeclSyntax { +func getAvailability(_ newSignature: FunctionSignatureSyntax, _ typeAvailability: [String: String]?) + -> [AttributeListSyntax.Element] +{ + guard let typeAvailability = typeAvailability else { + return [] + } + var hasMutableSpan = false + var hasSpan = false + if let returnClause = newSignature.returnClause { + hasMutableSpan = isMutableSpan(returnClause.type) + hasSpan = isImmutableSpan(returnClause.type) + } + for param in newSignature.parameterClause.parameters { + if hasMutableSpan { + break + } + hasMutableSpan = isMutableSpan(param.type) + hasSpan = hasSpan || isImmutableSpan(param.type) + } + if !hasMutableSpan && !hasSpan { + return [] + } + let availability = + if hasMutableSpan { + typeAvailability["MutableSpan"] + } else { + typeAvailability["Span"] + } + return [.attribute(AttributeSyntax("@available(\(raw: availability!), *)"))] +} + +func setVisibility(_ modifiers: inout DeclModifierListSyntax, _ funcKeyword: inout TokenSyntax) { + var hasVisibilityModifier = false + for i in modifiers.indices { + let modName = modifiers[i].name.trimmed.text + if modName == "public" || modName == "internal" || modName == "private" || modName == "filePrivate" { + return + } + if modName == "open" { + modifiers[i] = modifiers[i].with(\.name, .identifier("public", + leadingTrivia: modifiers[i].leadingTrivia, trailingTrivia: modifiers[i].trailingTrivia)) + return + } + } + // We have no visibility modifier, so insert "public" + // If the next token has a line break, steal that to make it print consistently + if let firstMod = modifiers.first { + if !firstMod.leadingTrivia.isEmpty { + modifiers = [DeclModifierSyntax(name: .identifier("public", leadingTrivia: firstMod.leadingTrivia)), + firstMod.trimmed] + modifiers.dropFirst() + } + return + } + if !funcKeyword.leadingTrivia.isEmpty { + modifiers = [DeclModifierSyntax(name: .identifier("public", leadingTrivia: funcKeyword.leadingTrivia))] + modifiers + funcKeyword = .identifier("func", trailingTrivia: funcKeyword.trailingTrivia) + return + } + modifiers = [DeclModifierSyntax(name: .identifier("public"))] + modifiers +} + +func constructOverloadFunction( + forDecl funcDecl: FunctionDeclSyntax, + args arguments: [ExprSyntax], + typeAvailability: [String: String]?, + typeMappings: [String: String]? +) throws -> DeclSyntax { var nonescapingPointers = Set() - var lifetimeDependencies : [SwiftifyExpr: [LifetimeDependence]] = [:] + var lifetimeDependencies: [SwiftifyExpr: [LifetimeDependence]] = [:] var parsedArgs = try arguments.compactMap { - try parseMacroParam($0, funcDecl.signature, nonescapingPointers: &nonescapingPointers, + try parseMacroParam( + $0, funcDecl.signature, nonescapingPointers: &nonescapingPointers, lifetimeDependencies: &lifetimeDependencies) } parsedArgs.append(contentsOf: try parseCxxSpansInSignature(funcDecl.signature, typeMappings)) @@ -1407,16 +1522,19 @@ func constructOverloadFunction(forDecl funcDecl: FunctionDeclSyntax, let returnLifetimeAttribute = getReturnLifetimeAttribute(funcDecl, lifetimeDependencies) let lifetimeAttrs = returnLifetimeAttribute + paramLifetimeAttributes(newSignature, funcDecl.attributes) - let disfavoredOverload: [AttributeListSyntax.Element] = (onlyReturnTypeChanged ? [ - .attribute( - AttributeSyntax( - atSign: .atSignToken(), - attributeName: IdentifierTypeSyntax(name: "_disfavoredOverload"))) - ] : []) - let hasVisibilityModifier = funcDecl.modifiers.contains { modifier in - let modName = modifier.name.trimmed.text - return modName == "public" || modName == "internal" || modName == "open" || modName == "private" || modName == "filePrivate" - } + let availabilityAttr = getAvailability(newSignature, typeAvailability) + let disfavoredOverload: [AttributeListSyntax.Element] = + (onlyReturnTypeChanged + ? [ + .attribute( + AttributeSyntax( + atSign: .atSignToken(), + attributeName: IdentifierTypeSyntax(name: "_disfavoredOverload"))) + ] : []) + // non-@objc methods should not be open, fall back to public instead + var modifiers: DeclModifierListSyntax = funcDecl.modifiers + var funcKeyword: TokenSyntax = funcDecl.funcKeyword + setVisibility(&modifiers, &funcKeyword) let newFunc = funcDecl .with(\.signature, newSignature) @@ -1437,10 +1555,14 @@ func constructOverloadFunction(forDecl funcDecl: FunctionDeclSyntax, atSign: .atSignToken(), attributeName: IdentifierTypeSyntax(name: "_alwaysEmitIntoClient"))) ] - + lifetimeAttrs - + disfavoredOverload) - .with(\.modifiers, funcDecl.modifiers + (hasVisibilityModifier ? [] : [DeclModifierSyntax(name: .identifier("public"))])) - return DeclSyntax(newFunc) + + availabilityAttr + + lifetimeAttrs + + disfavoredOverload + ) + // Break up the expression to let the compiler type check + return DeclSyntax(newFunc + .with(\.modifiers, modifiers) + .with(\.funcKeyword, funcKeyword)) } /// A macro that adds safe(r) wrappers for functions with unsafe pointer types. @@ -1466,8 +1588,16 @@ public struct SwiftifyImportMacro: PeerMacro { if typeMappings != nil { arguments = arguments.dropLast() } + let typeAvailability = try parseAvailabilityParam(arguments.last) + if typeAvailability != nil { + arguments = arguments.dropLast() + } let args = arguments.map { $0.expression } - return [try constructOverloadFunction(forDecl: funcDecl, args: args, typeMappings: typeMappings)] + return [ + try constructOverloadFunction( + forDecl: funcDecl, args: args, typeAvailability: typeAvailability, + typeMappings: typeMappings) + ] } catch let error as DiagnosticError { context.diagnose( Diagnostic( @@ -1485,7 +1615,8 @@ func parseProtocolMacroParam( let paramExpr = paramAST.expression guard let enumConstructorExpr = paramExpr.as(FunctionCallExprSyntax.self) else { throw DiagnosticError( - "expected _SwiftifyProtocolMethodInfo enum literal as argument, got '\(paramExpr)'", node: paramExpr) + "expected _SwiftifyProtocolMethodInfo enum literal as argument, got '\(paramExpr)'", + node: paramExpr) } let enumName = try parseEnumName(paramExpr) if enumName != "method" { @@ -1494,18 +1625,28 @@ func parseProtocolMacroParam( node: enumConstructorExpr) } let argumentList = enumConstructorExpr.arguments - let methodNameArg = try getArgumentByName(argumentList, "name") - guard let methodNameStringLit = methodNameArg.as(StringLiteralExprSyntax.self) else { + let methodSignatureArg = try getArgumentBySignature(argumentList, "signature") + guard let methodSignatureStringLit = methodSignatureArg.as(StringLiteralExprSyntax.self) else { throw DiagnosticError( - "expected string literal for 'name' parameter, got \(methodNameArg)", node: methodNameArg) - } - let methodName = methodNameStringLit.representedLiteralValue! - guard let methodSyntax = methods[methodName] else { - throw DiagnosticError("method with name \(methodName) not found in protocol", node: methodNameArg) + "expected string literal for 'signature' parameter, got \(methodSignatureArg)", node: methodSignatureArg) + } + let methodSignature = methodSignatureStringLit.representedLiteralValue! + guard let methodSyntax = methods[methodSignature] else { + var notes: [Note] = [] + var name = methodSignature + if let methodSyntax = DeclSyntax("\(raw: methodSignature)").as(FunctionDeclSyntax.self) { + name = methodSyntax.name.trimmed.text + } + for (_, method) in methods where method.name.trimmed.text == name { + notes.append(Note(node: Syntax(method.name), message: MacroExpansionNoteMessage("did you mean '\(method.trimmed.description)'?"))) + } + throw DiagnosticError( + "method with signature '\(methodSignature)' not found in protocol", node: methodNameArg, notes: notes) } let paramInfoArg = try getArgumentByName(argumentList, "paramInfo") guard let paramInfoArgList = paramInfoArg.as(ArrayExprSyntax.self) else { - throw DiagnosticError("expected array literal for 'paramInfo' parameter, got \(paramInfoArg)", node: paramInfoArg) + throw DiagnosticError( + "expected array literal for 'paramInfo' parameter, got \(paramInfoArg)", node: paramInfoArg) } return (methodSyntax, paramInfoArgList.elements.map { ExprSyntax($0.expression) }) } @@ -1521,34 +1662,53 @@ public struct SwiftifyImportProtocolMacro: ExtensionMacro { in context: some MacroExpansionContext ) throws -> [ExtensionDeclSyntax] { do { - guard let protocolDecl = declaration.as(ProtocolDeclSyntax.self) else { - throw DiagnosticError("@_SwiftifyImportProtocol only works on protocols", node: declaration) - } + let members: MemberBlockItemListSyntax = + switch declaration.kind { + case .protocolDecl: + declaration.as(ProtocolDeclSyntax.self)!.memberBlock.members + case .classDecl: + declaration.as(ClassDeclSyntax.self)!.memberBlock.members + default: + throw DiagnosticError( + "@_SwiftifyImportProtocol only works on protocols and classes", node: declaration) + } let argumentList = node.arguments!.as(LabeledExprListSyntax.self)! var arguments = [LabeledExprSyntax](argumentList) let typeMappings = try parseTypeMappingParam(arguments.last) if typeMappings != nil { arguments = arguments.dropLast() } + let typeAvailability = try parseAvailabilityParam(arguments.last) + if typeAvailability != nil { + arguments = arguments.dropLast() + } var methods: [String: FunctionDeclSyntax] = [:] - for member in protocolDecl.memberBlock.members { + for member in members { guard let methodDecl = member.decl.as(FunctionDeclSyntax.self) else { continue } - methods[methodDecl.name.trimmed.text] = methodDecl + let trimmedDecl = methodDecl.with(\.body, nil) + .with(\.attributes, []) + .trimmed + methods[trimmedDecl.description] = methodDecl } let overloads = try arguments.map { let (method, args) = try parseProtocolMacroParam($0, methods: methods) - let function = try constructOverloadFunction(forDecl: method, args: args, typeMappings: typeMappings) + let function = try constructOverloadFunction( + forDecl: method, args: args, typeAvailability: typeAvailability, + typeMappings: typeMappings) return MemberBlockItemSyntax(decl: function) } - - return [ExtensionDeclSyntax(extensionKeyword: .identifier("extension"), extendedType: type, - memberBlock: MemberBlockSyntax(leftBrace: .leftBraceToken(), - members: MemberBlockItemListSyntax(overloads), - rightBrace: .rightBraceToken()) - )] + return [ + ExtensionDeclSyntax( + extensionKeyword: .identifier("extension"), extendedType: type, + memberBlock: MemberBlockSyntax( + leftBrace: .leftBraceToken(), + members: MemberBlockItemListSyntax(overloads), + rightBrace: .rightBraceToken()) + ) + ] } catch let error as DiagnosticError { context.diagnose( Diagnostic( diff --git a/lib/Sema/TypeCheckMacros.cpp b/lib/Sema/TypeCheckMacros.cpp index 2f3e1de63820..986c4972cb1d 100644 --- a/lib/Sema/TypeCheckMacros.cpp +++ b/lib/Sema/TypeCheckMacros.cpp @@ -1375,6 +1375,13 @@ static SourceFile *evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, } else if (role == MacroRole::Conformance || role == MacroRole::Extension) { // Conformance macros always expand to extensions at file-scope. dc = attachedTo->getDeclContext()->getParentSourceFile(); + if (!dc) { + assert(isa( + attachedTo->getDeclContext()->getModuleScopeContext())); + dc = attachedTo->getDeclContext(); + // decls imported from clang do not have a SourceFile + assert(isa(dc)); + } } else { dc = attachedTo->getInnermostDeclContext(); } diff --git a/stdlib/public/Cxx/CxxSpan.swift b/stdlib/public/Cxx/CxxSpan.swift index 4064a650f889..adc9425c85cf 100644 --- a/stdlib/public/Cxx/CxxSpan.swift +++ b/stdlib/public/Cxx/CxxSpan.swift @@ -18,46 +18,6 @@ internal func unsafeBitCast( Builtin.reinterpretCast(x) } -/// Unsafely discard any lifetime dependency on the `dependent` argument. Return -/// a value identical to `dependent` with a lifetime dependency on the caller's -/// borrow scope of the `source` argument. -/// -/// This mimics the stdlib definition. It is public for use with import macros. -@unsafe -@_unsafeNonescapableResult -@_alwaysEmitIntoClient -@_transparent -@lifetime(borrow source) -public func _cxxOverrideLifetime< - T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable ->( - _ dependent: consuming T, borrowing source: borrowing U -) -> T { - // TODO: Remove @_unsafeNonescapableResult. Instead, the unsafe dependence - // should be expressed by a builtin that is hidden within the function body. - dependent -} - -/// Unsafely discard any lifetime dependency on the `dependent` argument. Return -/// a value identical to `dependent` that inherits all lifetime dependencies from -/// the `source` argument. -/// -/// This mimics the stdlib definition. It is public for use with import macros. -@unsafe -@_unsafeNonescapableResult -@_alwaysEmitIntoClient -@_transparent -@lifetime(copy source) -public func _cxxOverrideLifetime< - T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable ->( - _ dependent: consuming T, copying source: borrowing U -) -> T { - // TODO: Remove @_unsafeNonescapableResult. Instead, the unsafe dependence - // should be expressed by a builtin that is hidden within the function body. - dependent -} - /// A C++ type that is an object that can refer to a contiguous sequence of objects. /// /// C++ standard library type `std::span` conforms to this protocol. @@ -111,7 +71,7 @@ extension Span { let buffer = unsafe UnsafeBufferPointer(start: span.__dataUnsafe(), count: Int(span.size())) let newSpan = unsafe Span(_unsafeElements: buffer) // 'self' is limited to the caller's scope of the variable passed to the 'span' argument. - self = unsafe _cxxOverrideLifetime(newSpan, borrowing: span) + self = unsafe _swiftifyOverrideLifetime(newSpan, borrowing: span) } } @@ -127,7 +87,7 @@ extension MutableSpan { let buffer = unsafe UnsafeMutableBufferPointer(start: span.__dataUnsafe(), count: Int(span.size())) let newSpan = unsafe MutableSpan(_unsafeElements: buffer) // 'self' is limited to the caller's scope of the variable passed to the 'span' argument. - self = unsafe _cxxOverrideLifetime(newSpan, borrowing: span) + self = unsafe _swiftifyOverrideLifetime(newSpan, borrowing: span) } } diff --git a/stdlib/public/Cxx/CxxVector.swift b/stdlib/public/Cxx/CxxVector.swift index b226b3a6755a..e3adf3266eb9 100644 --- a/stdlib/public/Cxx/CxxVector.swift +++ b/stdlib/public/Cxx/CxxVector.swift @@ -58,7 +58,7 @@ extension CxxVector { borrowing get { let buffer = unsafe UnsafeBufferPointer(start: self.__dataUnsafe(), count: Int(self.size())) let span = unsafe Span(_unsafeElements: buffer) - return unsafe _cxxOverrideLifetime(span, borrowing: self) + return unsafe _swiftifyOverrideLifetime(span, borrowing: self) } } } diff --git a/stdlib/public/core/SwiftifyImport.swift b/stdlib/public/core/SwiftifyImport.swift index 8ddddf6af98f..784dcfe8c634 100644 --- a/stdlib/public/core/SwiftifyImport.swift +++ b/stdlib/public/core/SwiftifyImport.swift @@ -60,7 +60,7 @@ public enum _SwiftifyInfo { /// safety of the generated wrapper function depends on this info being extensive and accurate. #if hasFeature(Macros) @attached(peer, names: overloaded) -public macro _SwiftifyImport(_ paramInfo: _SwiftifyInfo..., typeMappings: [String: String] = [:]) = +public macro _SwiftifyImport(_ paramInfo: _SwiftifyInfo..., availability: [String: String] = [:], typeMappings: [String: String] = [:]) = #externalMacro(module: "SwiftMacros", type: "SwiftifyImportMacro") #endif @@ -71,7 +71,7 @@ public macro _SwiftifyImport(_ paramInfo: _SwiftifyInfo..., typeMappings: [Strin /// _SwiftifyImportProtocolMethod, so they should not affect linkage since there are never any instances /// at runtime. public enum _SwiftifyProtocolMethodInfo { - case method(name: String, paramInfo: [_SwiftifyInfo]) + case method(signature: String, paramInfo: [_SwiftifyInfo]) } /// Like _SwiftifyImport, but since protocols cannot contain function implementations they need to @@ -81,6 +81,47 @@ public enum _SwiftifyProtocolMethodInfo { #if hasFeature(Macros) @attached(extension, names: arbitrary) public macro _SwiftifyImportProtocol(_ methodInfo: _SwiftifyProtocolMethodInfo..., + availability: [String: String] = [:], typeMappings: [String: String] = [:]) = #externalMacro(module: "SwiftMacros", type: "SwiftifyImportProtocolMacro") #endif + +/// Unsafely discard any lifetime dependency on the `dependent` argument. Return +/// a value identical to `dependent` with a lifetime dependency on the caller's +/// borrow scope of the `source` argument. +/// +/// This mimics the stdlib definition. It is public for use with import macros. +@unsafe +@_unsafeNonescapableResult +@_alwaysEmitIntoClient +@_transparent +@lifetime(borrow source) +public func _swiftifyOverrideLifetime< + T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable +>( + _ dependent: consuming T, borrowing source: borrowing U +) -> T { + // TODO: Remove @_unsafeNonescapableResult. Instead, the unsafe dependence + // should be expressed by a builtin that is hidden within the function body. + dependent +} + +/// Unsafely discard any lifetime dependency on the `dependent` argument. Return +/// a value identical to `dependent` that inherits all lifetime dependencies from +/// the `source` argument. +/// +/// This mimics the stdlib definition. It is public for use with import macros. +@unsafe +@_unsafeNonescapableResult +@_alwaysEmitIntoClient +@_transparent +@lifetime(copy source) +public func _swiftifyOverrideLifetime< + T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable +>( + _ dependent: consuming T, copying source: borrowing U +) -> T { + // TODO: Remove @_unsafeNonescapableResult. Instead, the unsafe dependence + // should be expressed by a builtin that is hidden within the function body. + dependent +} \ No newline at end of file diff --git a/test/Interop/Cxx/swiftify-import/counted-by-in-namespace.swift b/test/Interop/Cxx/swiftify-import/counted-by-in-namespace.swift index 38b3425136b1..6b10a18baedc 100644 --- a/test/Interop/Cxx/swiftify-import/counted-by-in-namespace.swift +++ b/test/Interop/Cxx/swiftify-import/counted-by-in-namespace.swift @@ -22,7 +22,7 @@ namespace foo { //--- namespace.swift import Namespace - + func test(s: UnsafeMutableBufferPointer) { foo.bar(s) -} +} diff --git a/test/Interop/Cxx/swiftify-import/counted-by-method.swift b/test/Interop/Cxx/swiftify-import/counted-by-method.swift index c15cd8564bc8..b05f5c0ed173 100644 --- a/test/Interop/Cxx/swiftify-import/counted-by-method.swift +++ b/test/Interop/Cxx/swiftify-import/counted-by-method.swift @@ -5,7 +5,7 @@ // RUN: %target-swift-ide-test -plugin-path %swift-plugin-dir -I %t/Inputs -cxx-interoperability-mode=upcoming-swift -enable-experimental-feature SafeInteropWrappers -print-module -module-to-print=Method -source-filename=x | %FileCheck %s // RUN: %target-swift-frontend -plugin-path %swift-plugin-dir -I %t/Inputs -cxx-interoperability-mode=default -enable-experimental-feature SafeInteropWrappers %t/method.swift -dump-macro-expansions -typecheck -verify -// CHECK: @_alwaysEmitIntoClient +// CHECK: @_alwaysEmitIntoClient // CHECK-SAME: public mutating func bar(_ p: UnsafeMutableBufferPointer) //--- Inputs/module.modulemap @@ -23,8 +23,8 @@ public: //--- method.swift import Method - + func test(s: UnsafeMutableBufferPointer) { var foo = Foo() foo.bar(s) -} +} diff --git a/test/Interop/ObjC/swiftify-import/counted-by-in-class-noescape.swift b/test/Interop/ObjC/swiftify-import/counted-by-in-class-noescape.swift new file mode 100644 index 000000000000..ab403d900db0 --- /dev/null +++ b/test/Interop/ObjC/swiftify-import/counted-by-in-class-noescape.swift @@ -0,0 +1,200 @@ +// REQUIRES: swift_feature_SafeInteropWrappers +// REQUIRES: swift_feature_LifetimeDependence + +// swift-ide-test doesn't currently trigger extension macro expansion, nor does it typecheck macro expansions, so dump macros with swift-frontend + +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-swift-frontend -emit-module -plugin-path %swift-plugin-dir -o %t/CountedByClassSpan.swiftmodule -I %t/Inputs -enable-experimental-feature SafeInteropWrappers -enable-experimental-feature LifetimeDependence %t/counted-by-class-noescape.swift -dump-macro-expansions -swift-version 6 2>&1 | %FileCheck %s + +//--- Inputs/module.modulemap +module CountedByClassNoescapeClang { + header "counted-by-class-noescape.h" + export * +} + +//--- Inputs/counted-by-class-noescape.h +#pragma once + +#define __counted_by(x) __attribute__((__counted_by__(x))) +#define __noescape __attribute__((__noescape__)) +#define __lifetimebound __attribute__((__lifetimebound__)) + +__attribute__((swift_attr("@available(SwiftStdlib 6.2, *)"))) +@interface CountedByClassSpan + - (void) simple:(int)len :(int * __counted_by(len) __noescape)p; + - (void) shared:(int)len :(int * __counted_by(len) __noescape)p1 :(int * __counted_by(len) __noescape)p2; + - (void) complexExpr:(int)len :(int) offset :(int * __counted_by(len - offset) __noescape)p; + - (void) nullUnspecified:(int)len :(int * __counted_by(len) _Null_unspecified __noescape)p; + - (void) nonnull:(int)len :(int * __counted_by(len) _Nonnull __noescape)p; + - (void) nullable:(int)len :(int * __counted_by(len) _Nullable __noescape)p; + + - (int * __counted_by(len)) returnPointer:(int)len :(int)len2 :(int * __counted_by(len2) __lifetimebound) p; + + + (void) staticMethod:(int)len :(int * __counted_by(len) __noescape)p; +@end + +// CHECK-LABEL: extension CountedByClassSpan { +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public class func simple(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe simple(Int32(exactly: _pPtr.count)!, _pPtr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public func simple(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe simple(Int32(exactly: _pPtr.count)!, _pPtr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p1: copy p1) @lifetime(p2: copy p2) +// CHECK-NEXT: public class func shared(_ len: Int32, _ p1: inout MutableSpan, _ p2: inout MutableSpan) { +// CHECK-NEXT: let _p1Count: some BinaryInteger = len +// CHECK-NEXT: if p1.count < _p1Count || _p1Count < 0 { +// CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") +// CHECK-NEXT: } +// CHECK-NEXT: let _p2Count: some BinaryInteger = len +// CHECK-NEXT: if p2.count < _p2Count || _p2Count < 0 { +// CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") +// CHECK-NEXT: } +// CHECK-NEXT: return unsafe p2.withUnsafeMutableBufferPointer { _p2Ptr in +// CHECK-NEXT: return unsafe p1.withUnsafeMutableBufferPointer { _p1Ptr in +// CHECK-NEXT: return unsafe shared(len, _p1Ptr.baseAddress!, _p2Ptr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p1: copy p1) @lifetime(p2: copy p2) +// CHECK-NEXT: public func shared(_ len: Int32, _ p1: inout MutableSpan, _ p2: inout MutableSpan) { +// CHECK-NEXT: let _p1Count: some BinaryInteger = len +// CHECK-NEXT: if p1.count < _p1Count || _p1Count < 0 { +// CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") +// CHECK-NEXT: } +// CHECK-NEXT: let _p2Count: some BinaryInteger = len +// CHECK-NEXT: if p2.count < _p2Count || _p2Count < 0 { +// CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") +// CHECK-NEXT: } +// CHECK-NEXT: return unsafe p2.withUnsafeMutableBufferPointer { _p2Ptr in +// CHECK-NEXT: return unsafe p1.withUnsafeMutableBufferPointer { _p1Ptr in +// CHECK-NEXT: return unsafe shared(len, _p1Ptr.baseAddress!, _p2Ptr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public class func complexExpr(_ len: Int32, _ offset: Int32, _ p: inout MutableSpan) { +// CHECK-NEXT: let _pCount: some BinaryInteger = len - offset +// CHECK-NEXT: if p.count < _pCount || _pCount < 0 { +// CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") +// CHECK-NEXT: } +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe complexExpr(len, offset, _pPtr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public func complexExpr(_ len: Int32, _ offset: Int32, _ p: inout MutableSpan) { +// CHECK-NEXT: let _pCount: some BinaryInteger = len - offset +// CHECK-NEXT: if p.count < _pCount || _pCount < 0 { +// CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") +// CHECK-NEXT: } +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe complexExpr(len, offset, _pPtr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public class func nullUnspecified(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe nullUnspecified(Int32(exactly: _pPtr.count)!, _pPtr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public func nullUnspecified(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe nullUnspecified(Int32(exactly: _pPtr.count)!, _pPtr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public class func nonnull(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe nonnull(Int32(exactly: _pPtr.count)!, _pPtr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public func nonnull(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe nonnull(Int32(exactly: _pPtr.count)!, _pPtr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public class func nullable(_ p: inout MutableSpan?) { +// CHECK-NEXT: return { () in +// CHECK-NEXT: return if p == nil { +// CHECK-NEXT: unsafe nullable(Int32(exactly: p?.count ?? 0)!, nil) +// CHECK-NEXT: } else { +// CHECK-NEXT: unsafe p!.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe nullable(Int32(exactly: _pPtr.count)!, _pPtr.baseAddress) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: }() +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public func nullable(_ p: inout MutableSpan?) { +// CHECK-NEXT: return { () in +// CHECK-NEXT: return if p == nil { +// CHECK-NEXT: unsafe nullable(Int32(exactly: p?.count ?? 0)!, nil) +// CHECK-NEXT: } else { +// CHECK-NEXT: unsafe p!.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe nullable(Int32(exactly: _pPtr.count)!, _pPtr.baseAddress) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: }() +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(copy p) @lifetime(p: copy p) +// CHECK-NEXT: public class func returnPointer(_ len: Int32, _ p: inout MutableSpan) -> MutableSpan { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(MutableSpan(_unsafeStart: unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe returnPointer(len, Int32(exactly: _pPtr.count)!, _pPtr.baseAddress!) +// CHECK-NEXT: }, count: Int(len)), copying: ()) +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(copy p) @lifetime(p: copy p) +// CHECK-NEXT: public func returnPointer(_ len: Int32, _ p: inout MutableSpan) -> MutableSpan { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(MutableSpan(_unsafeStart: unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe returnPointer(len, Int32(exactly: _pPtr.count)!, _pPtr.baseAddress!) +// CHECK-NEXT: }, count: Int(len)), copying: ()) +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public class func staticMethod(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe staticMethod(Int32(exactly: _pPtr.count)!, _pPtr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } + +__attribute__((swift_attr("@_SwiftifyImportProtocol(.method(name: \"open func swiftAttr(_ len: Int32, _ p: UnsafeMutablePointer!)\", paramInfo: [.countedBy(pointer: .param(2), count: \"len\"), .nonescaping(pointer: .param(2))]), availability: [\"Span\": \"macOS 9999\", \"MutableSpan\": \"macOS 9999\"])"))) +@interface SwiftAttrClass + - (void)swiftAttr:(int)len :(int *)p; +@end + +// CHECK: extension SwiftAttrClass { +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public func swiftAttr(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe swiftAttr(Int32(exactly: _pPtr.count)!, _pPtr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } + +//--- counted-by-class-noescape.swift +import CountedByClassNoescapeClang +import Cxx + +@available(macOS 9999, *) +@lifetime(p1: copy p1) @lifetime(p2: copy p2) +public func call(p1: inout MutableSpan, p2: inout MutableSpan, p3: inout MutableSpan?, x: CInt, y: CInt, a: CountedByClassSpan, b: SwiftAttrClass) { + a.simple(&p1) + a.shared(x, &p1, &p2) + a.complexExpr(x, y, &p1) + a.nullUnspecified(&p1) + a.nonnull(&p1) + a.nullable(&p3) + let r1: MutableSpan = a.returnPointer(x, &p1) + b.swiftAttr(&p1) +} \ No newline at end of file diff --git a/test/Interop/ObjC/swiftify-import/counted-by-in-class.swift b/test/Interop/ObjC/swiftify-import/counted-by-in-class.swift index 5cfa11553be9..05754faa63b6 100644 --- a/test/Interop/ObjC/swiftify-import/counted-by-in-class.swift +++ b/test/Interop/ObjC/swiftify-import/counted-by-in-class.swift @@ -7,8 +7,11 @@ // REQUIRES: objc_interop -// CHECK: class Foo { -// CHECK: func bar(_ p: UnsafeMutableBufferPointer) +// CHECK: class Foo { +// CHECK-NEXT: class func swiftAttr(_ p: UnsafeMutablePointer!, count len: Int32) +// CHECK-NEXT: @_alwaysEmitIntoClient public func swiftAttr(_ p: UnsafeMutableBufferPointer) +// CHECK-NEXT: func swiftAttr(_ p: UnsafeMutablePointer!, count len: Int32) +// CHECK-NEXT: } //--- Inputs/module.modulemap module Method { @@ -18,12 +21,40 @@ module Method { //--- Inputs/method.h @interface Foo --(void)bar:(float *)p count:(int)len __attribute__((swift_attr("@_SwiftifyImport(.countedBy(pointer: .param(1), count: \"len\"))"))); +-(void)swiftAttr:(float *)p count:(int)len __attribute__((swift_attr("@_SwiftifyImport(.countedBy(pointer: .param(1), count: \"len\"))"))); +@end + +#define __counted_by(x) __attribute__((__counted_by__(x))) +#define __noescape __attribute__((__noescape__)) +#define __lifetimebound __attribute__((__lifetimebound__)) + +@interface Bar + - (void) simple:(int)len :(int * __counted_by(len))p; + - (void) shared:(int)len :(int * __counted_by(len))p1 :(int * __counted_by(len))p2; + - (void) complexExpr:(int)len :(int) offset :(int * __counted_by(len - offset))p; + - (void) nullUnspecified:(int)len :(int * __counted_by(len) _Null_unspecified)p; + - (void) nonnull:(int)len :(int * __counted_by(len) _Nonnull)p; + - (void) nullable:(int)len :(int * __counted_by(len) _Nullable)p; + - (int * __counted_by(len)) returnPointer:(int)len; + + + (void) staticMethod:(int)len :(int * __counted_by(len))p; @end //--- method.swift import Method - -func test(foo: Foo, s: UnsafeMutableBufferPointer) { - foo.bar(s) -} + +func testFoo(foo: Foo, s: UnsafeMutableBufferPointer) { + foo.swiftAttr(s) +} + +public func testBar(p: UnsafeMutableBufferPointer, x: CInt, y: CInt, a: Bar) { + a.simple(p) + a.shared(x, p, p) + a.complexExpr(x, y, p) + a.nullUnspecified(p) + a.nonnull(p) + a.nullable(p) + let _: UnsafeMutableBufferPointer = a.returnPointer(x) + let r = a.returnPointer(x) + let _: UnsafeMutablePointer? = r // make sure the original is the favored overload +} diff --git a/test/Interop/ObjC/swiftify-import/counted-by-protocol-noescape.swift b/test/Interop/ObjC/swiftify-import/counted-by-protocol-noescape.swift new file mode 100644 index 000000000000..971f018c7a2c --- /dev/null +++ b/test/Interop/ObjC/swiftify-import/counted-by-protocol-noescape.swift @@ -0,0 +1,138 @@ +// REQUIRES: swift_feature_SafeInteropWrappers +// REQUIRES: swift_feature_LifetimeDependence + +// swift-ide-test doesn't currently trigger extension macro expansion, nor does it typecheck macro expansions, so dump macros with swift-frontend + +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-swift-frontend -emit-module -plugin-path %swift-plugin-dir -o %t/CountedByProtocolSpan.swiftmodule -I %t/Inputs -enable-experimental-feature SafeInteropWrappers -enable-experimental-feature LifetimeDependence %t/counted-by-protocol-noescape.swift -dump-macro-expansions -swift-version 6 2>&1 | %FileCheck %s + +//--- Inputs/module.modulemap +module CountedByProtocolNoescapeClang { + header "counted-by-protocol-noescape.h" + export * +} + +//--- Inputs/counted-by-protocol-noescape.h +#pragma once + +#define __counted_by(x) __attribute__((__counted_by__(x))) +#define __noescape __attribute__((__noescape__)) +#define __lifetimebound __attribute__((__lifetimebound__)) + +__attribute__((swift_attr("@available(SwiftStdlib 6.2, *)"))) +@protocol CountedByProtocolSpan + - (void) simple:(int)len :(int * __counted_by(len) __noescape)p; + - (void) shared:(int)len :(int * __counted_by(len) __noescape)p1 :(int * __counted_by(len) __noescape)p2; + - (void) complexExpr:(int)len :(int) offset :(int * __counted_by(len - offset) __noescape)p; + - (void) nullUnspecified:(int)len :(int * __counted_by(len) _Null_unspecified __noescape)p; + - (void) nonnull:(int)len :(int * __counted_by(len) _Nonnull __noescape)p; + - (void) nullable:(int)len :(int * __counted_by(len) _Nullable __noescape)p; + + - (int * __counted_by(len)) returnPointer:(int)len :(int)len2 :(int * __counted_by(len2) __lifetimebound) p; + + + (void) staticMethod:(int)len :(int * __counted_by(len) __noescape)p; +@end + +// CHECK-LABEL: extension CountedByProtocolSpan { +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public func simple(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe simple(Int32(exactly: _pPtr.count)!, _pPtr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p1: copy p1) @lifetime(p2: copy p2) +// CHECK-NEXT: public func shared(_ len: Int32, _ p1: inout MutableSpan, _ p2: inout MutableSpan) { +// CHECK-NEXT: let _p1Count: some BinaryInteger = len +// CHECK-NEXT: if p1.count < _p1Count || _p1Count < 0 { +// CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") +// CHECK-NEXT: } +// CHECK-NEXT: let _p2Count: some BinaryInteger = len +// CHECK-NEXT: if p2.count < _p2Count || _p2Count < 0 { +// CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") +// CHECK-NEXT: } +// CHECK-NEXT: return unsafe p2.withUnsafeMutableBufferPointer { _p2Ptr in +// CHECK-NEXT: return unsafe p1.withUnsafeMutableBufferPointer { _p1Ptr in +// CHECK-NEXT: return unsafe shared(len, _p1Ptr.baseAddress!, _p2Ptr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public func complexExpr(_ len: Int32, _ offset: Int32, _ p: inout MutableSpan) { +// CHECK-NEXT: let _pCount: some BinaryInteger = len - offset +// CHECK-NEXT: if p.count < _pCount || _pCount < 0 { +// CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") +// CHECK-NEXT: } +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe complexExpr(len, offset, _pPtr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public func nullUnspecified(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe nullUnspecified(Int32(exactly: _pPtr.count)!, _pPtr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public func nonnull(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe nonnull(Int32(exactly: _pPtr.count)!, _pPtr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public func nullable(_ p: inout MutableSpan?) { +// CHECK-NEXT: return { () in +// CHECK-NEXT: if p == nil { +// CHECK-NEXT: unsafe nullable(Int32(exactly: p?.count ?? 0)!, nil) +// CHECK-NEXT: } else { +// CHECK-NEXT: unsafe p!.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe nullable(Int32(exactly: _pPtr.count)!, _pPtr.baseAddress) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: }() +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(copy p) @lifetime(p: copy p) +// CHECK-NEXT: public func returnPointer(_ len: Int32, _ p: inout MutableSpan) -> MutableSpan { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(MutableSpan(_unsafeStart: unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe returnPointer(len, Int32(exactly: _pPtr.count)!, _pPtr.baseAddress!) +// CHECK-NEXT: }, count: Int(len)), copying: ()) +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public static func staticMethod(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe staticMethod(Int32(exactly: _pPtr.count)!, _pPtr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } + +__attribute__((swift_attr("@_SwiftifyImportProtocol(.method(name: \"func swiftAttr(_ len: Int32, _ p: UnsafeMutablePointer!)\", paramInfo: [.countedBy(pointer: .param(2), count: \"len\"), .nonescaping(pointer: .param(2))]), availability: [\"Span\": \"macOS 9999\", \"MutableSpan\": \"macOS 9999\"])"))) +@protocol SwiftAttrProtocol + - (void)swiftAttr:(int)len :(int *)p; +@end + +// CHECK-LABEL: extension SwiftAttrProtocol { +// CHECK-NEXT: @_alwaysEmitIntoClient @available(macOS 9999, *) @lifetime(p: copy p) +// CHECK-NEXT: public func swiftAttr(_ p: inout MutableSpan) { +// CHECK-NEXT: return unsafe p.withUnsafeMutableBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe swiftAttr(Int32(exactly: _pPtr.count)!, _pPtr.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } + +//--- counted-by-protocol-noescape.swift +import CountedByProtocolNoescapeClang +import Cxx + +@available(macOS 9999, *) +@lifetime(p1: copy p1) @lifetime(p2: copy p2) +public func call(p1: inout MutableSpan, p2: inout MutableSpan, p3: inout MutableSpan?, x: CInt, y: CInt, a: CountedByProtocolSpan, b: SwiftAttrProtocol) { + a.simple(&p1) + a.shared(x, &p1, &p2) + a.complexExpr(x, y, &p1) + a.nullUnspecified(&p1) + a.nonnull(&p1) + a.nullable(&p3) + let r1: MutableSpan = a.returnPointer(x, &p1) + b.swiftAttr(&p1) +} diff --git a/test/Interop/ObjC/swiftify-import/counted-by-protocol.swift b/test/Interop/ObjC/swiftify-import/counted-by-protocol.swift new file mode 100644 index 000000000000..723db7decb60 --- /dev/null +++ b/test/Interop/ObjC/swiftify-import/counted-by-protocol.swift @@ -0,0 +1,107 @@ +// REQUIRES: swift_feature_SafeInteropWrappers + +// swift-ide-test doesn't currently trigger extension macro expansion, nor does it typecheck macro expansions, so dump macros with swift-frontend + +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-swift-frontend -emit-module -plugin-path %swift-plugin-dir -o %t/CountedByProtocol.swiftmodule -I %t/Inputs -enable-experimental-feature SafeInteropWrappers %t/counted-by-protocol.swift -dump-macro-expansions 2>&1 | %FileCheck %s + +//--- Inputs/module.modulemap +module CountedByProtocolClang { + header "counted-by-protocol.h" + export * +} + +//--- Inputs/counted-by-protocol.h +#pragma once + +#define __counted_by(x) __attribute__((__counted_by__(x))) + +@protocol CountedByProtocol + - (void) simple:(int)len :(int * __counted_by(len))p; + - (void) shared:(int)len :(int * __counted_by(len))p1 :(int * __counted_by(len))p2; + - (void) complexExpr:(int)len :(int) offset :(int * __counted_by(len - offset))p; + - (void) nullUnspecified:(int)len :(int * __counted_by(len) _Null_unspecified)p; + - (void) nonnull:(int)len :(int * __counted_by(len) _Nonnull)p; + - (void) nullable:(int)len :(int * __counted_by(len) _Nullable)p; + - (int * __counted_by(len)) returnPointer:(int)len; + + + (void) staticMethod:(int)len :(int * __counted_by(len))p; +@end + +// CHECK-LABEL: extension CountedByProtocol { +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: public func simple(_ p: UnsafeMutableBufferPointer) { +// CHECK-NEXT: return unsafe simple(Int{{.*}}(exactly: p.count)!, p.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: public func shared(_ len: Int{{.*}}, _ p1: UnsafeMutableBufferPointer, _ p2: UnsafeMutableBufferPointer) { +// CHECK-NEXT: let _p1Count: some BinaryInteger = len +// CHECK-NEXT: if p1.count < _p1Count || _p1Count < 0 { +// CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") +// CHECK-NEXT: } +// CHECK-NEXT: let _p2Count: some BinaryInteger = len +// CHECK-NEXT: if p2.count < _p2Count || _p2Count < 0 { +// CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") +// CHECK-NEXT: } +// CHECK-NEXT: return unsafe shared(len, p1.baseAddress!, p2.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: public func complexExpr(_ len: Int{{.*}}, _ offset: Int{{.*}}, _ p: UnsafeMutableBufferPointer) { +// CHECK-NEXT: let _pCount: some BinaryInteger = len - offset +// CHECK-NEXT: if p.count < _pCount || _pCount < 0 { +// CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") +// CHECK-NEXT: } +// CHECK-NEXT: return unsafe complexExpr(len, offset, p.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: public func nullUnspecified(_ p: UnsafeMutableBufferPointer) { +// CHECK-NEXT: return unsafe nullUnspecified(Int{{.*}}(exactly: p.count)!, p.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: public func nonnull(_ p: UnsafeMutableBufferPointer) { +// CHECK-NEXT: return unsafe nonnull(Int{{.*}}(exactly: p.count)!, p.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: public func nullable(_ p: UnsafeMutableBufferPointer?) { +// CHECK-NEXT: return unsafe nullable(Int{{.*}}(exactly: p?.count ?? 0)!, p?.baseAddress) +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload +// CHECK-NEXT: public func returnPointer(_ len: Int{{.*}}) -> UnsafeMutableBufferPointer { +// CHECK-NEXT: return unsafe UnsafeMutableBufferPointer(start: unsafe returnPointer(len), count: Int(len)) +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: public static func staticMethod(_ p: UnsafeMutableBufferPointer) { +// CHECK-NEXT: return unsafe staticMethod(Int{{.*}}(exactly: p.count)!, p.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } + +__attribute__((swift_attr("@_SwiftifyImportProtocol(.method(name: \"func swiftAttr(_ len: Int32, _ p: UnsafeMutablePointer!)\", paramInfo: [.countedBy(pointer: .param(2), count: \"len\")]))"))) +@protocol SwiftAttrProtocol + - (void)swiftAttr:(int)len :(int *)p; +@end + +// CHECK-LABEL: extension SwiftAttrProtocol { +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: public func swiftAttr(_ p: UnsafeMutableBufferPointer) { +// CHECK-NEXT: return unsafe swiftAttr(Int32(exactly: p.count)!, p.baseAddress!) +// CHECK-NEXT: } +// CHECK-NEXT: } + +//--- counted-by-protocol.swift +import CountedByProtocolClang + +@inlinable +public func call(p: UnsafeMutableBufferPointer, x: CInt, y: CInt, a: CountedByProtocol, b: SwiftAttrProtocol) { + a.simple(p) + a.shared(x, p, p) + a.complexExpr(x, y, p) + a.nullUnspecified(p) + a.nonnull(p) + a.nullable(p) + let r1: UnsafeMutableBufferPointer = a.returnPointer(x) + let r2 = a.returnPointer(x) + let r3: UnsafeMutablePointer? = r2 // make sure the original is the favored overload + b.swiftAttr(p) +} diff --git a/test/Macros/SwiftifyImport/CountedBy/CountExpr.swift b/test/Macros/SwiftifyImport/CountedBy/CountExpr.swift index d2b84757061b..8e6983645d0a 100644 --- a/test/Macros/SwiftifyImport/CountedBy/CountExpr.swift +++ b/test/Macros/SwiftifyImport/CountedBy/CountExpr.swift @@ -6,8 +6,8 @@ func myFunc(_ ptr: UnsafePointer, _ size: CInt, _ count: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer, _ size: CInt, _ count: CInt) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeBufferPointer, _ size: CInt, _ count: CInt) { // CHECK-NEXT: let _ptrCount: some BinaryInteger = size * count // CHECK-NEXT: if ptr.count < _ptrCount || _ptrCount < 0 { // CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") diff --git a/test/Macros/SwiftifyImport/CountedBy/MultipleParams.swift b/test/Macros/SwiftifyImport/CountedBy/MultipleParams.swift index 827c6422101d..1c8a609fb41c 100644 --- a/test/Macros/SwiftifyImport/CountedBy/MultipleParams.swift +++ b/test/Macros/SwiftifyImport/CountedBy/MultipleParams.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafePointer, _ len: CInt, _ ptr2: UnsafePointer, _ len2: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer, _ ptr2: UnsafeBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeBufferPointer, _ ptr2: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!, ptr2.baseAddress!, CInt(exactly: ptr2.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/Mutable.swift b/test/Macros/SwiftifyImport/CountedBy/Mutable.swift index 50ab5d37da01..487c08101fb8 100644 --- a/test/Macros/SwiftifyImport/CountedBy/Mutable.swift +++ b/test/Macros/SwiftifyImport/CountedBy/Mutable.swift @@ -6,8 +6,8 @@ func myFunc(_ ptr: UnsafeMutablePointer, _ len: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeMutableBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeMutableBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/MutableSpan.swift b/test/Macros/SwiftifyImport/CountedBy/MutableSpan.swift index 25511ea7e8f2..97c305ea3c3e 100644 --- a/test/Macros/SwiftifyImport/CountedBy/MutableSpan.swift +++ b/test/Macros/SwiftifyImport/CountedBy/MutableSpan.swift @@ -7,9 +7,9 @@ func myFunc(_ ptr: UnsafeMutablePointer, _ len: CInt) { } -// CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) public -// CHECK-NEXT: func myFunc(_ ptr: inout MutableSpan) { +// CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) +// CHECK-NEXT: public func myFunc(_ ptr: inout MutableSpan) { // CHECK-NEXT: return unsafe ptr.withUnsafeMutableBufferPointer { _ptrPtr in -// CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: ptr.count)!) +// CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: _ptrPtr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/NamedParams.swift b/test/Macros/SwiftifyImport/CountedBy/NamedParams.swift index eaf74b94177e..645e4a04a56d 100644 --- a/test/Macros/SwiftifyImport/CountedBy/NamedParams.swift +++ b/test/Macros/SwiftifyImport/CountedBy/NamedParams.swift @@ -26,33 +26,33 @@ func allNamed(ptr: UnsafePointer, len: CInt) { func allNamedOther(buf ptr: UnsafePointer, count len: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func ptrNamed(ptr: UnsafeBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func ptrNamed(ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe ptrNamed(ptr: ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func ptrNamedOther(buf ptr: UnsafeBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func ptrNamedOther(buf ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe ptrNamedOther(buf: ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func lenNamed(_ ptr: UnsafeBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func lenNamed(_ ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe lenNamed(ptr.baseAddress!, len: CInt(exactly: ptr.count)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func lenNamedOther(_ ptr: UnsafeBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func lenNamedOther(_ ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe lenNamedOther(ptr.baseAddress!, count: CInt(exactly: ptr.count)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func allNamed(ptr: UnsafeBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func allNamed(ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe allNamed(ptr: ptr.baseAddress!, len: CInt(exactly: ptr.count)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func allNamedOther(buf ptr: UnsafeBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func allNamedOther(buf ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe allNamedOther(buf: ptr.baseAddress!, count: CInt(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/Nullable.swift b/test/Macros/SwiftifyImport/CountedBy/Nullable.swift index 477544564efb..9f79f3f859bd 100644 --- a/test/Macros/SwiftifyImport/CountedBy/Nullable.swift +++ b/test/Macros/SwiftifyImport/CountedBy/Nullable.swift @@ -18,26 +18,26 @@ func myFunc3(_ ptr: UnsafeMutablePointer?, _ len: CInt, _ ptr2: UnsafeMuta func myFunc4(_ ptr: UnsafeMutablePointer?, _ len: CInt) -> UnsafeMutablePointer? { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer?) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeBufferPointer?) { // CHECK-NEXT: return unsafe myFunc(ptr?.baseAddress, CInt(exactly: ptr?.count ?? 0)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) public -// CHECK-NEXT: func myFunc2(_ ptr: inout MutableSpan?) { +// CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) +// CHECK-NEXT: public func myFunc2(_ ptr: inout MutableSpan?) { // CHECK-NEXT: return { () in // CHECK-NEXT: return if ptr == nil { // CHECK-NEXT: unsafe myFunc2(nil, CInt(exactly: ptr?.count ?? 0)!) // CHECK-NEXT: } else { // CHECK-NEXT: unsafe ptr!.withUnsafeMutableBufferPointer { _ptrPtr in -// CHECK-NEXT: return unsafe myFunc2(_ptrPtr.baseAddress, CInt(exactly: ptr?.count ?? 0)!) +// CHECK-NEXT: return unsafe myFunc2(_ptrPtr.baseAddress, CInt(exactly: _ptrPtr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: }() // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) @lifetime(ptr2: copy ptr2) public -// CHECK-NEXT: func myFunc3(_ ptr: inout MutableSpan?, _ ptr2: inout MutableSpan?) { +// CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) @lifetime(ptr2: copy ptr2) +// CHECK-NEXT: public func myFunc3(_ ptr: inout MutableSpan?, _ ptr2: inout MutableSpan?) { // CHECK-NEXT: return { () in // CHECK-NEXT: return if ptr2 == nil { // CHECK-NEXT: { () in @@ -45,7 +45,7 @@ func myFunc4(_ ptr: UnsafeMutablePointer?, _ len: CInt) -> UnsafeMutablePo // CHECK-NEXT: unsafe myFunc3(nil, CInt(exactly: ptr?.count ?? 0)!, nil, CInt(exactly: ptr2?.count ?? 0)!) // CHECK-NEXT: } else { // CHECK-NEXT: unsafe ptr!.withUnsafeMutableBufferPointer { _ptrPtr in -// CHECK-NEXT: return unsafe myFunc3(_ptrPtr.baseAddress, CInt(exactly: ptr?.count ?? 0)!, nil, CInt(exactly: ptr2?.count ?? 0)!) +// CHECK-NEXT: return unsafe myFunc3(_ptrPtr.baseAddress, CInt(exactly: _ptrPtr.count)!, nil, CInt(exactly: ptr2?.count ?? 0)!) // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: }() @@ -53,10 +53,10 @@ func myFunc4(_ ptr: UnsafeMutablePointer?, _ len: CInt) -> UnsafeMutablePo // CHECK-NEXT: unsafe ptr2!.withUnsafeMutableBufferPointer { _ptr2Ptr in // CHECK-NEXT: return { () in // CHECK-NEXT: return if ptr == nil { -// CHECK-NEXT: unsafe myFunc3(nil, CInt(exactly: ptr?.count ?? 0)!, _ptr2Ptr.baseAddress, CInt(exactly: ptr2?.count ?? 0)!) +// CHECK-NEXT: unsafe myFunc3(nil, CInt(exactly: ptr?.count ?? 0)!, _ptr2Ptr.baseAddress, CInt(exactly: _ptr2Ptr.count)!) // CHECK-NEXT: } else { // CHECK-NEXT: unsafe ptr!.withUnsafeMutableBufferPointer { _ptrPtr in -// CHECK-NEXT: return unsafe myFunc3(_ptrPtr.baseAddress, CInt(exactly: ptr?.count ?? 0)!, _ptr2Ptr.baseAddress, CInt(exactly: ptr2?.count ?? 0)!) +// CHECK-NEXT: return unsafe myFunc3(_ptrPtr.baseAddress, CInt(exactly: _ptrPtr.count)!, _ptr2Ptr.baseAddress, CInt(exactly: _ptr2Ptr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: }() @@ -65,8 +65,8 @@ func myFunc4(_ ptr: UnsafeMutablePointer?, _ len: CInt) -> UnsafeMutablePo // CHECK-NEXT: }() // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(copy ptr) @lifetime(ptr: copy ptr) public -// CHECK-NEXT: func myFunc4(_ ptr: inout MutableSpan?, _ len: CInt) -> MutableSpan? { +// CHECK: @_alwaysEmitIntoClient @lifetime(copy ptr) @lifetime(ptr: copy ptr) +// CHECK-NEXT: public func myFunc4(_ ptr: inout MutableSpan?, _ len: CInt) -> MutableSpan? { // CHECK-NEXT: let _ptrCount: some BinaryInteger = len // CHECK-NEXT: if ptr?.count ?? 0 < _ptrCount || _ptrCount < 0 { // CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") diff --git a/test/Macros/SwiftifyImport/CountedBy/PointerReturn.swift b/test/Macros/SwiftifyImport/CountedBy/PointerReturn.swift index f5e01837d296..fcd63d46e306 100644 --- a/test/Macros/SwiftifyImport/CountedBy/PointerReturn.swift +++ b/test/Macros/SwiftifyImport/CountedBy/PointerReturn.swift @@ -19,24 +19,24 @@ func lifetimeDependentCopy(_ p: UnsafePointer, _ len1: CInt, _ len2: CInt) func lifetimeDependentBorrow(_ p: borrowing UnsafePointer, _ len1: CInt, _ len2: CInt) -> UnsafePointer { } -// CHECK: @_alwaysEmitIntoClient @_disfavoredOverload public -// CHECK-NEXT: func myFunc(_ len: CInt) -> UnsafeMutableBufferPointer { +// CHECK: @_alwaysEmitIntoClient @_disfavoredOverload +// CHECK-NEXT: public func myFunc(_ len: CInt) -> UnsafeMutableBufferPointer { // CHECK-NEXT: return unsafe UnsafeMutableBufferPointer (start: unsafe myFunc(len), count: Int(len)) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @_disfavoredOverload public -// CHECK-NEXT: func nonEscaping(_ len: CInt) -> UnsafeBufferPointer { +// CHECK: @_alwaysEmitIntoClient @_disfavoredOverload +// CHECK-NEXT: public func nonEscaping(_ len: CInt) -> UnsafeBufferPointer { // CHECK-NEXT: return unsafe UnsafeBufferPointer (start: unsafe nonEscaping(len), count: Int(len)) -// CHECK: @_alwaysEmitIntoClient @lifetime(copy p) public -// CHECK-NEXT: func lifetimeDependentCopy(_ p: Span, _ len2: CInt) -> Span { -// CHECK-NEXT: return unsafe Span (_unsafeStart: unsafe p.withUnsafeBufferPointer { _pPtr in -// CHECK-NEXT: return unsafe lifetimeDependentCopy(_pPtr.baseAddress!, CInt(exactly: p.count)!, len2) -// CHECK-NEXT: }, count: Int(len2)) +// CHECK: @_alwaysEmitIntoClient @lifetime(copy p) +// CHECK-NEXT: public func lifetimeDependentCopy(_ p: Span, _ len2: CInt) -> Span { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(Span (_unsafeStart: unsafe p.withUnsafeBufferPointer { _pPtr in +// CHECK-NEXT: return unsafe lifetimeDependentCopy(_pPtr.baseAddress!, CInt(exactly: _pPtr.count)!, len2) +// CHECK-NEXT: }, count: Int(len2)), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(borrow p) public -// CHECK-NEXT: func lifetimeDependentBorrow(_ p: borrowing UnsafeBufferPointer, _ len2: CInt) -> Span { -// CHECK-NEXT: return unsafe Span (_unsafeStart: unsafe lifetimeDependentBorrow(p.baseAddress!, CInt(exactly: p.count)!, len2), count: Int(len2)) +// CHECK: @_alwaysEmitIntoClient @lifetime(borrow p) +// CHECK-NEXT: public func lifetimeDependentBorrow(_ p: borrowing UnsafeBufferPointer, _ len2: CInt) -> Span { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(Span (_unsafeStart: unsafe lifetimeDependentBorrow(p.baseAddress!, CInt(exactly: p.count)!, len2), count: Int(len2)), copying: ()) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/Protocol.swift b/test/Macros/SwiftifyImport/CountedBy/Protocol.swift index 7f4882aba15e..4ae66d754b6c 100644 --- a/test/Macros/SwiftifyImport/CountedBy/Protocol.swift +++ b/test/Macros/SwiftifyImport/CountedBy/Protocol.swift @@ -2,55 +2,86 @@ // RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -dump-macro-expansions -enable-experimental-feature Span -enable-experimental-feature LifetimeDependence 2>&1 | %FileCheck --match-full-lines %s -@_SwiftifyImportProtocol(.method(name: "myFunc", paramInfo: [.countedBy(pointer: .param(1), count: "len")])) +@_SwiftifyImportProtocol(.method(name: "func myFunc(_ ptr: UnsafePointer, _ len: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len")])) protocol SimpleProtocol { func myFunc(_ ptr: UnsafePointer, _ len: CInt) } // CHECK: extension SimpleProtocol { -// CHECK-NEXT: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer) { +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } -@_SwiftifyImportProtocol(.method(name: "foo", paramInfo: [.countedBy(pointer: .param(1), count: "len"), .nonescaping(pointer: .param(1))]), - .method(name: "bar", paramInfo: [.countedBy(pointer: .return, count: "len"), .nonescaping(pointer: .return), .lifetimeDependence(dependsOn: .self, pointer: .return, type: .borrow)])) +@_SwiftifyImportProtocol(.method(name: "func foo(_ ptr: UnsafePointer, _ len: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len"), .nonescaping(pointer: .param(1))]), + .method(name: "func bar(_ len: CInt) -> UnsafePointer", paramInfo: [.countedBy(pointer: .return, count: "len"), .nonescaping(pointer: .return), .lifetimeDependence(dependsOn: .self, pointer: .return, type: .borrow)])) protocol SpanProtocol { func foo(_ ptr: UnsafePointer, _ len: CInt) func bar(_ len: CInt) -> UnsafePointer } // CHECK: extension SpanProtocol { -// CHECK-NEXT: @_alwaysEmitIntoClient public -// CHECK-NEXT: func foo(_ ptr: Span) { +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: public func foo(_ ptr: Span) { // CHECK-NEXT: return unsafe ptr.withUnsafeBufferPointer { _ptrPtr in -// CHECK-NEXT: return unsafe foo(_ptrPtr.baseAddress!, CInt(exactly: ptr.count)!) +// CHECK-NEXT: return unsafe foo(_ptrPtr.baseAddress!, CInt(exactly: _ptrPtr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK-NEXT: @_alwaysEmitIntoClient @lifetime(borrow self) @_disfavoredOverload public -// CHECK-NEXT: func bar(_ len: CInt) -> Span { -// CHECK-NEXT: return unsafe Span(_unsafeStart: unsafe bar(len), count: Int(len)) +// CHECK-NEXT: @_alwaysEmitIntoClient @lifetime(borrow self) @_disfavoredOverload +// CHECK-NEXT: public func bar(_ len: CInt) -> Span { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(Span(_unsafeStart: unsafe bar(len), count: Int(len)), copying: ()) // CHECK-NEXT: } // CHECK-NEXT: } -@_SwiftifyImportProtocol(.method(name: "foo", paramInfo: [.countedBy(pointer: .param(1), count: "len"), .nonescaping(pointer: .param(1))]), - .method(name: "bar", paramInfo: [.countedBy(pointer: .param(1), count: "len")])) +@_SwiftifyImportProtocol(.method(name: "func foo(_ ptr: UnsafePointer, _ len: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len"), .nonescaping(pointer: .param(1))]), + .method(name: "func bar(_ ptr: UnsafePointer, _ len: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len")])) protocol MixedProtocol { func foo(_ ptr: UnsafePointer, _ len: CInt) func bar(_ ptr: UnsafePointer, _ len: CInt) } // CHECK: extension MixedProtocol { -// CHECK-NEXT: @_alwaysEmitIntoClient public -// CHECK-NEXT: func foo(_ ptr: Span) { +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: public func foo(_ ptr: Span) { // CHECK-NEXT: return unsafe ptr.withUnsafeBufferPointer { _ptrPtr in -// CHECK-NEXT: return unsafe foo(_ptrPtr.baseAddress!, CInt(exactly: ptr.count)!) +// CHECK-NEXT: return unsafe foo(_ptrPtr.baseAddress!, CInt(exactly: _ptrPtr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK-NEXT: @_alwaysEmitIntoClient public -// CHECK-NEXT: func bar(_ ptr: UnsafeBufferPointer) { +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: public func bar(_ ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe bar(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } + +@_SwiftifyImportProtocol(.method(name: "func foo(_ ptr: UnsafePointer, _ len1: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len1")]), + .method(name: "func foo(bar: UnsafePointer, _ len2: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len2")])) +protocol OverloadedProtocol { + func foo(_ ptr: UnsafePointer, _ len1: CInt) + func foo(bar: UnsafePointer, _ len2: CInt) + func foo() +} + +// CHECK: extension OverloadedProtocol { +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: public func foo(_ ptr: UnsafeBufferPointer) { +// CHECK-NEXT: return unsafe foo(ptr.baseAddress!, CInt(exactly: ptr.count)!) +// CHECK-NEXT: } +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: public func foo(bar: UnsafeBufferPointer) { +// CHECK-NEXT: return unsafe foo(bar: bar.baseAddress!, CInt(exactly: bar.count)!) +// CHECK-NEXT: } +// CHECK-NEXT: } + +@_SwiftifyImportProtocol(.method(name: "open func myFunc(_ ptr: UnsafePointer, _ len: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len")])) +class SimpleClass { + open func myFunc(_ ptr: UnsafePointer, _ len: CInt) {} +} + +// CHECK: extension SimpleClass { +// CHECK-NEXT: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeBufferPointer) { +// CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) +// CHECK-NEXT: } +// CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/QualifiedTypes.swift b/test/Macros/SwiftifyImport/CountedBy/QualifiedTypes.swift index 6dac3a80daef..7577b2cd56f8 100644 --- a/test/Macros/SwiftifyImport/CountedBy/QualifiedTypes.swift +++ b/test/Macros/SwiftifyImport/CountedBy/QualifiedTypes.swift @@ -10,13 +10,13 @@ func foo(_ ptr: Swift.UnsafePointer, _ len: Swift.Int) -> Swift.Void func bar(_ ptr: Swift.UnsafePointer, _ len: Swift.Int) -> () { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func foo(_ ptr: Swift.UnsafeBufferPointer) -> Swift.Void { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func foo(_ ptr: Swift.UnsafeBufferPointer) -> Swift.Void { // CHECK-NEXT: return unsafe foo(ptr.baseAddress!, ptr.count) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func bar(_ ptr: Swift.UnsafeBufferPointer) -> () { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func bar(_ ptr: Swift.UnsafeBufferPointer) -> () { // CHECK-NEXT: return unsafe bar(ptr.baseAddress!, ptr.count) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/Return.swift b/test/Macros/SwiftifyImport/CountedBy/Return.swift index fdc6f62c979a..9c36b472942c 100644 --- a/test/Macros/SwiftifyImport/CountedBy/Return.swift +++ b/test/Macros/SwiftifyImport/CountedBy/Return.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafePointer, _ len: CInt) -> CInt { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer) -> CInt { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeBufferPointer) -> CInt { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/SharedCount.swift b/test/Macros/SwiftifyImport/CountedBy/SharedCount.swift index 27c2b96457bb..fdd70c5777a0 100644 --- a/test/Macros/SwiftifyImport/CountedBy/SharedCount.swift +++ b/test/Macros/SwiftifyImport/CountedBy/SharedCount.swift @@ -6,8 +6,8 @@ func myFunc(_ ptr: UnsafePointer, _ ptr2: UnsafePointer, _ len: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer, _ ptr2: UnsafeBufferPointer, _ len: CInt) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeBufferPointer, _ ptr2: UnsafeBufferPointer, _ len: CInt) { // CHECK-NEXT: let _ptrCount: some BinaryInteger = len // CHECK-NEXT: if ptr.count < _ptrCount || _ptrCount < 0 { // CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") diff --git a/test/Macros/SwiftifyImport/CountedBy/SimpleCount.swift b/test/Macros/SwiftifyImport/CountedBy/SimpleCount.swift index b3f75cc15968..b90dc336c129 100644 --- a/test/Macros/SwiftifyImport/CountedBy/SimpleCount.swift +++ b/test/Macros/SwiftifyImport/CountedBy/SimpleCount.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafePointer, _ len: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/SimpleSpan.swift b/test/Macros/SwiftifyImport/CountedBy/SimpleSpan.swift index a535527994f9..28a74b4a377f 100644 --- a/test/Macros/SwiftifyImport/CountedBy/SimpleSpan.swift +++ b/test/Macros/SwiftifyImport/CountedBy/SimpleSpan.swift @@ -7,9 +7,9 @@ func myFunc(_ ptr: UnsafePointer, _ len: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: Span) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: Span) { // CHECK-NEXT: return unsafe ptr.withUnsafeBufferPointer { _ptrPtr in -// CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: ptr.count)!) +// CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: _ptrPtr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/SimpleSpanWithReturn.swift b/test/Macros/SwiftifyImport/CountedBy/SimpleSpanWithReturn.swift index 2adda99ceed7..9de243ac471b 100644 --- a/test/Macros/SwiftifyImport/CountedBy/SimpleSpanWithReturn.swift +++ b/test/Macros/SwiftifyImport/CountedBy/SimpleSpanWithReturn.swift @@ -7,9 +7,9 @@ func myFunc(_ ptr: UnsafePointer, _ len: CInt) -> CInt { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: Span) -> CInt { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: Span) -> CInt { // CHECK-NEXT: return unsafe ptr.withUnsafeBufferPointer { _ptrPtr in -// CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: ptr.count)!) +// CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: _ptrPtr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/SpanAndUnsafeBuffer.swift b/test/Macros/SwiftifyImport/CountedBy/SpanAndUnsafeBuffer.swift index ec433190d1df..c3e47b56a093 100644 --- a/test/Macros/SwiftifyImport/CountedBy/SpanAndUnsafeBuffer.swift +++ b/test/Macros/SwiftifyImport/CountedBy/SpanAndUnsafeBuffer.swift @@ -8,10 +8,10 @@ func myFunc(_ ptr1: UnsafePointer, _ len1: CInt, _ ptr2: UnsafePointer, _ len2: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr1: Span, _ ptr2: UnsafeBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr1: Span, _ ptr2: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe ptr1.withUnsafeBufferPointer { _ptr1Ptr in -// CHECK-NEXT: return unsafe myFunc(_ptr1Ptr.baseAddress!, CInt(exactly: ptr1.count)!, ptr2.baseAddress!, CInt(exactly: ptr2.count)!) +// CHECK-NEXT: return unsafe myFunc(_ptr1Ptr.baseAddress!, CInt(exactly: _ptr1Ptr.count)!, ptr2.baseAddress!, CInt(exactly: ptr2.count)!) // CHECK-NEXT: } // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/Unwrapped.swift b/test/Macros/SwiftifyImport/CountedBy/Unwrapped.swift index 2bdcde465e4e..36f73095388c 100644 --- a/test/Macros/SwiftifyImport/CountedBy/Unwrapped.swift +++ b/test/Macros/SwiftifyImport/CountedBy/Unwrapped.swift @@ -6,8 +6,8 @@ func myFunc(_ ptr: UnsafePointer!, _ len: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CxxSpan/LifetimeboundSpan.swift b/test/Macros/SwiftifyImport/CxxSpan/LifetimeboundSpan.swift index 7f279e6c679f..4bbd39f6cefd 100644 --- a/test/Macros/SwiftifyImport/CxxSpan/LifetimeboundSpan.swift +++ b/test/Macros/SwiftifyImport/CxxSpan/LifetimeboundSpan.swift @@ -57,67 +57,67 @@ func myFunc8(_ ptr: UnsafeRawPointer, _ span: SpanOfInt, _ count: CInt, _ size: func myFunc9(_ span: MutableSpanOfInt) -> MutableSpanOfInt { } -// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) public -// CHECK-NEXT: func myFunc(_ span: Span) -> Span { -// CHECK-NEXT: return unsafe _cxxOverrideLifetime(Span(_unsafeCxxSpan: unsafe myFunc(SpanOfInt(span))), copying: ()) +// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) +// CHECK-NEXT: public func myFunc(_ span: Span) -> Span { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(Span(_unsafeCxxSpan: unsafe myFunc(SpanOfInt(span))), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(borrow vec) @_disfavoredOverload public -// CHECK-NEXT: func myFunc2(_ vec: borrowing VecOfInt) -> Span { -// CHECK-NEXT: return unsafe _cxxOverrideLifetime(Span(_unsafeCxxSpan: unsafe myFunc2(vec)), copying: ()) +// CHECK: @_alwaysEmitIntoClient @lifetime(borrow vec) @_disfavoredOverload +// CHECK-NEXT: public func myFunc2(_ vec: borrowing VecOfInt) -> Span { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(Span(_unsafeCxxSpan: unsafe myFunc2(vec)), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(copy span1, copy span2) public -// CHECK-NEXT: func myFunc3(_ span1: Span, _ span2: Span) -> Span { -// CHECK-NEXT: return unsafe _cxxOverrideLifetime(Span(_unsafeCxxSpan: unsafe myFunc3(SpanOfInt(span1), SpanOfInt(span2))), copying: ()) +// CHECK: @_alwaysEmitIntoClient @lifetime(copy span1, copy span2) +// CHECK-NEXT: public func myFunc3(_ span1: Span, _ span2: Span) -> Span { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(Span(_unsafeCxxSpan: unsafe myFunc3(SpanOfInt(span1), SpanOfInt(span2))), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(borrow vec, copy span) public -// CHECK-NEXT: func myFunc4(_ vec: borrowing VecOfInt, _ span: Span) -> Span { -// CHECK-NEXT: return unsafe _cxxOverrideLifetime(Span(_unsafeCxxSpan: unsafe myFunc4(vec, SpanOfInt(span))), copying: ()) +// CHECK: @_alwaysEmitIntoClient @lifetime(borrow vec, copy span) +// CHECK-NEXT: public func myFunc4(_ vec: borrowing VecOfInt, _ span: Span) -> Span { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(Span(_unsafeCxxSpan: unsafe myFunc4(vec, SpanOfInt(span))), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(borrow self) @_disfavoredOverload public -// CHECK-NEXT: func myFunc5() -> Span { -// CHECK-NEXT: return unsafe _cxxOverrideLifetime(Span(_unsafeCxxSpan: unsafe myFunc5()), copying: ()) +// CHECK: @_alwaysEmitIntoClient @lifetime(borrow self) @_disfavoredOverload +// CHECK-NEXT: public func myFunc5() -> Span { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(Span(_unsafeCxxSpan: unsafe myFunc5()), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) public -// CHECK-NEXT: func myFunc6(_ span: Span, _ ptr: RawSpan, _ count: CInt, _ size: CInt) -> Span { +// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) +// CHECK-NEXT: public func myFunc6(_ span: Span, _ ptr: RawSpan, _ count: CInt, _ size: CInt) -> Span { // CHECK-NEXT: let _ptrCount: some BinaryInteger = count * size // CHECK-NEXT: if ptr.byteCount < _ptrCount || _ptrCount < 0 { // CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") // CHECK-NEXT: } -// CHECK-NEXT: return unsafe _cxxOverrideLifetime(Span(_unsafeCxxSpan: unsafe ptr.withUnsafeBytes { _ptrPtr in +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(Span(_unsafeCxxSpan: unsafe ptr.withUnsafeBytes { _ptrPtr in // CHECK-NEXT: return unsafe myFunc6(SpanOfInt(span), _ptrPtr.baseAddress!, count, size) // CHECK-NEXT: }), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) public -// CHECK-NEXT: func myFunc7(_ span: Span, _ ptr: RawSpan, _ count: CInt, _ size: CInt) -> Span { +// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) +// CHECK-NEXT: public func myFunc7(_ span: Span, _ ptr: RawSpan, _ count: CInt, _ size: CInt) -> Span { // CHECK-NEXT: let _ptrCount: some BinaryInteger = count * size // CHECK-NEXT: if ptr.byteCount < _ptrCount || _ptrCount < 0 { // CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") // CHECK-NEXT: } -// CHECK-NEXT: return unsafe _cxxOverrideLifetime(Span(_unsafeCxxSpan: unsafe ptr.withUnsafeBytes { _ptrPtr in +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(Span(_unsafeCxxSpan: unsafe ptr.withUnsafeBytes { _ptrPtr in // CHECK-NEXT: return unsafe myFunc7(SpanOfInt(span), _ptrPtr.baseAddress!, count, size) // CHECK-NEXT: }), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) public -// CHECK-NEXT: func myFunc8(_ ptr: RawSpan, _ span: Span, _ count: CInt, _ size: CInt) -> Span { +// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) +// CHECK-NEXT: public func myFunc8(_ ptr: RawSpan, _ span: Span, _ count: CInt, _ size: CInt) -> Span { // CHECK-NEXT: let _ptrCount: some BinaryInteger = count * size // CHECK-NEXT: if ptr.byteCount < _ptrCount || _ptrCount < 0 { // CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") // CHECK-NEXT: } -// CHECK-NEXT: return unsafe _cxxOverrideLifetime(Span(_unsafeCxxSpan: unsafe ptr.withUnsafeBytes { _ptrPtr in +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(Span(_unsafeCxxSpan: unsafe ptr.withUnsafeBytes { _ptrPtr in // CHECK-NEXT: return unsafe myFunc8(_ptrPtr.baseAddress!, SpanOfInt(span), count, size) // CHECK-NEXT: }), copying: ()) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) @lifetime(span: copy span) public -// CHECK-NEXT: func myFunc9(_ span: inout MutableSpan) -> MutableSpan { -// CHECK-NEXT: return unsafe _cxxOverrideLifetime(MutableSpan(_unsafeCxxSpan: unsafe span.withUnsafeMutableBufferPointer { _spanPtr in +// CHECK: @_alwaysEmitIntoClient @lifetime(copy span) @lifetime(span: copy span) +// CHECK-NEXT: public func myFunc9(_ span: inout MutableSpan) -> MutableSpan { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(MutableSpan(_unsafeCxxSpan: unsafe span.withUnsafeMutableBufferPointer { _spanPtr in // CHECK-NEXT: return unsafe myFunc9(MutableSpanOfInt(_spanPtr)) // CHECK-NEXT: }), copying: ()) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CxxSpan/NoEscapeSpan.swift b/test/Macros/SwiftifyImport/CxxSpan/NoEscapeSpan.swift index c5298f5863cf..1a604c46e430 100644 --- a/test/Macros/SwiftifyImport/CxxSpan/NoEscapeSpan.swift +++ b/test/Macros/SwiftifyImport/CxxSpan/NoEscapeSpan.swift @@ -25,27 +25,27 @@ func myFunc3(_ span: MutableSpanOfInt, _ secondSpan: SpanOfInt) { func myFunc4(_ span: MutableSpanOfInt, _ secondSpan: MutableSpanOfInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ span: Span, _ secondSpan: SpanOfInt) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ span: Span, _ secondSpan: SpanOfInt) { // CHECK-NEXT: return unsafe myFunc(SpanOfInt(span), secondSpan) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(span: copy span) public -// CHECK-NEXT: func myFunc2(_ span: inout MutableSpan, _ secondSpan: MutableSpanOfInt) { +// CHECK: @_alwaysEmitIntoClient @lifetime(span: copy span) +// CHECK-NEXT: public func myFunc2(_ span: inout MutableSpan, _ secondSpan: MutableSpanOfInt) { // CHECK-NEXT: return unsafe span.withUnsafeMutableBufferPointer { _spanPtr in // CHECK-NEXT: return unsafe myFunc2(MutableSpanOfInt(_spanPtr), secondSpan) // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(span: copy span) public -// CHECK-NEXT: func myFunc3(_ span: inout MutableSpan, _ secondSpan: Span) { +// CHECK: @_alwaysEmitIntoClient @lifetime(span: copy span) +// CHECK-NEXT: public func myFunc3(_ span: inout MutableSpan, _ secondSpan: Span) { // CHECK-NEXT: return unsafe span.withUnsafeMutableBufferPointer { _spanPtr in // CHECK-NEXT: return unsafe myFunc3(MutableSpanOfInt(_spanPtr), SpanOfInt(secondSpan)) // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(span: copy span) @lifetime(secondSpan: copy secondSpan) public -// CHECK-NEXT: func myFunc4(_ span: inout MutableSpan, _ secondSpan: inout MutableSpan) { +// CHECK: @_alwaysEmitIntoClient @lifetime(span: copy span) @lifetime(secondSpan: copy secondSpan) +// CHECK-NEXT: public func myFunc4(_ span: inout MutableSpan, _ secondSpan: inout MutableSpan) { // CHECK-NEXT: return unsafe secondSpan.withUnsafeMutableBufferPointer { _secondSpanPtr in // CHECK-NEXT: return unsafe span.withUnsafeMutableBufferPointer { _spanPtr in // CHECK-NEXT: return unsafe myFunc4(MutableSpanOfInt(_spanPtr), MutableSpanOfInt(_secondSpanPtr)) diff --git a/test/Macros/SwiftifyImport/MacroErrors/UnexpectedCountType.swift b/test/Macros/SwiftifyImport/MacroErrors/UnexpectedCountType.swift index 30bc51fce4b8..686649b266eb 100644 --- a/test/Macros/SwiftifyImport/MacroErrors/UnexpectedCountType.swift +++ b/test/Macros/SwiftifyImport/MacroErrors/UnexpectedCountType.swift @@ -9,8 +9,8 @@ func myFunc(_ ptr: UnsafePointer, _ len: String) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeBufferPointer) { // CHECK-NEXT: myFunc(ptr.baseAddress!, String(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/MultipleParams.swift b/test/Macros/SwiftifyImport/SizedBy/MultipleParams.swift index be505e51b9ef..ff57e275664b 100644 --- a/test/Macros/SwiftifyImport/SizedBy/MultipleParams.swift +++ b/test/Macros/SwiftifyImport/SizedBy/MultipleParams.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafeRawPointer, _ size: CInt, _ ptr2: UnsafeRawPointer, _ size2: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeRawBufferPointer, _ ptr2: UnsafeRawBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeRawBufferPointer, _ ptr2: UnsafeRawBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!, ptr2.baseAddress!, CInt(exactly: ptr2.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/Mutable.swift b/test/Macros/SwiftifyImport/SizedBy/Mutable.swift index 2ee9bfafeaa9..d389782a0245 100644 --- a/test/Macros/SwiftifyImport/SizedBy/Mutable.swift +++ b/test/Macros/SwiftifyImport/SizedBy/Mutable.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafeMutableRawPointer, _ size: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeMutableRawBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeMutableRawBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/MutableRawSpan.swift b/test/Macros/SwiftifyImport/SizedBy/MutableRawSpan.swift index a5446e853506..ba1d14088bbc 100644 --- a/test/Macros/SwiftifyImport/SizedBy/MutableRawSpan.swift +++ b/test/Macros/SwiftifyImport/SizedBy/MutableRawSpan.swift @@ -7,9 +7,9 @@ func myFunc(_ ptr: UnsafeMutableRawPointer, _ size: CInt) { } -// CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) public -// CHECK-NEXT: func myFunc(_ ptr: inout MutableRawSpan) { +// CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) +// CHECK-NEXT: public func myFunc(_ ptr: inout MutableRawSpan) { // CHECK-NEXT: return unsafe ptr.withUnsafeMutableBytes { _ptrPtr in -// CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: ptr.byteCount)!) +// CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: _ptrPtr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/Nullable.swift b/test/Macros/SwiftifyImport/SizedBy/Nullable.swift index 9f33c53fca94..3d60c3ba2afa 100644 --- a/test/Macros/SwiftifyImport/SizedBy/Nullable.swift +++ b/test/Macros/SwiftifyImport/SizedBy/Nullable.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafeRawPointer?, _ size: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeRawBufferPointer?) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeRawBufferPointer?) { // CHECK-NEXT: return unsafe myFunc(ptr?.baseAddress, CInt(exactly: ptr?.count ?? 0)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/Opaque.swift b/test/Macros/SwiftifyImport/SizedBy/Opaque.swift index 5588f4fed7f3..f276222d8325 100644 --- a/test/Macros/SwiftifyImport/SizedBy/Opaque.swift +++ b/test/Macros/SwiftifyImport/SizedBy/Opaque.swift @@ -26,45 +26,45 @@ func nullableSpan(_ ptr: OpaquePointer?, _ size: CInt) { func impNullableSpan(_ ptr: OpaquePointer!, _ size: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func nonnullUnsafeRawBufferPointer(_ ptr: UnsafeRawBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func nonnullUnsafeRawBufferPointer(_ ptr: UnsafeRawBufferPointer) { // CHECK-NEXT: return unsafe nonnullUnsafeRawBufferPointer(OpaquePointer(ptr.baseAddress!), CInt(exactly: ptr.count)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func nullableUnsafeRawBufferPointer(_ ptr: UnsafeRawBufferPointer?) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func nullableUnsafeRawBufferPointer(_ ptr: UnsafeRawBufferPointer?) { // CHECK-NEXT: return unsafe nullableUnsafeRawBufferPointer(OpaquePointer(ptr?.baseAddress), CInt(exactly: ptr?.count ?? 0)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func impNullableUnsafeRawBufferPointer(_ ptr: UnsafeRawBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func impNullableUnsafeRawBufferPointer(_ ptr: UnsafeRawBufferPointer) { // CHECK-NEXT: return unsafe impNullableUnsafeRawBufferPointer(OpaquePointer(ptr.baseAddress!), CInt(exactly: ptr.count)!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func nonnullSpan(_ ptr: RawSpan) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func nonnullSpan(_ ptr: RawSpan) { // CHECK-NEXT: return unsafe ptr.withUnsafeBytes { _ptrPtr in -// CHECK-NEXT: return unsafe nonnullSpan(OpaquePointer(_ptrPtr.baseAddress!), CInt(exactly: ptr.byteCount)!) +// CHECK-NEXT: return unsafe nonnullSpan(OpaquePointer(_ptrPtr.baseAddress!), CInt(exactly: _ptrPtr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func nullableSpan(_ ptr: RawSpan?) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func nullableSpan(_ ptr: RawSpan?) { // CHECK-NEXT: return { () in // CHECK-NEXT: return if ptr == nil { // CHECK-NEXT: unsafe nullableSpan(nil, CInt(exactly: ptr?.byteCount ?? 0)!) // CHECK-NEXT: } else { // CHECK-NEXT: unsafe ptr!.withUnsafeBytes { _ptrPtr in -// CHECK-NEXT: return unsafe nullableSpan(OpaquePointer(_ptrPtr.baseAddress), CInt(exactly: ptr?.byteCount ?? 0)!) +// CHECK-NEXT: return unsafe nullableSpan(OpaquePointer(_ptrPtr.baseAddress), CInt(exactly: _ptrPtr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: }() // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func impNullableSpan(_ ptr: RawSpan) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func impNullableSpan(_ ptr: RawSpan) { // CHECK-NEXT: return unsafe ptr.withUnsafeBytes { _ptrPtr in -// CHECK-NEXT: return unsafe impNullableSpan(OpaquePointer(_ptrPtr.baseAddress!), CInt(exactly: ptr.byteCount)!) +// CHECK-NEXT: return unsafe impNullableSpan(OpaquePointer(_ptrPtr.baseAddress!), CInt(exactly: _ptrPtr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/Return.swift b/test/Macros/SwiftifyImport/SizedBy/Return.swift index 7fa2df20b79b..3481b037660a 100644 --- a/test/Macros/SwiftifyImport/SizedBy/Return.swift +++ b/test/Macros/SwiftifyImport/SizedBy/Return.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafeRawPointer, _ size: CInt) -> CInt { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeRawBufferPointer) -> CInt { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeRawBufferPointer) -> CInt { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/SharedCount.swift b/test/Macros/SwiftifyImport/SizedBy/SharedCount.swift index 0fc5baa76fa2..7629e680718f 100644 --- a/test/Macros/SwiftifyImport/SizedBy/SharedCount.swift +++ b/test/Macros/SwiftifyImport/SizedBy/SharedCount.swift @@ -6,8 +6,8 @@ func myFunc(_ ptr: UnsafeRawPointer, _ ptr2: UnsafeRawPointer, _ size: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeRawBufferPointer, _ ptr2: UnsafeRawBufferPointer, _ size: CInt) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeRawBufferPointer, _ ptr2: UnsafeRawBufferPointer, _ size: CInt) { // CHECK-NEXT: let _ptrCount: some BinaryInteger = size // CHECK-NEXT: if ptr.count < _ptrCount || _ptrCount < 0 { // CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") diff --git a/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpan.swift b/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpan.swift index e3bd9d809868..ff1352c18403 100644 --- a/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpan.swift +++ b/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpan.swift @@ -7,9 +7,9 @@ func myFunc(_ ptr: UnsafeRawPointer, _ size: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: RawSpan) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: RawSpan) { // CHECK-NEXT: return unsafe ptr.withUnsafeBytes { _ptrPtr in -// CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: ptr.byteCount)!) +// CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: _ptrPtr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpanWithReturn.swift b/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpanWithReturn.swift index e64079372526..1d2e7fdf27b8 100644 --- a/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpanWithReturn.swift +++ b/test/Macros/SwiftifyImport/SizedBy/SimpleRawSpanWithReturn.swift @@ -7,9 +7,9 @@ func myFunc(_ ptr: UnsafeRawPointer, _ size: CInt) -> CInt { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: RawSpan) -> CInt { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: RawSpan) -> CInt { // CHECK-NEXT: return unsafe ptr.withUnsafeBytes { _ptrPtr in -// CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: ptr.byteCount)!) +// CHECK-NEXT: return unsafe myFunc(_ptrPtr.baseAddress!, CInt(exactly: _ptrPtr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/SimpleSize.swift b/test/Macros/SwiftifyImport/SizedBy/SimpleSize.swift index e9ce505ecdd4..9c17189c19d5 100644 --- a/test/Macros/SwiftifyImport/SizedBy/SimpleSize.swift +++ b/test/Macros/SwiftifyImport/SizedBy/SimpleSize.swift @@ -6,7 +6,7 @@ func myFunc(_ ptr: UnsafeRawPointer, _ size: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeRawBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeRawBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/SizeExpr.swift b/test/Macros/SwiftifyImport/SizedBy/SizeExpr.swift index 33acde7225e5..b4055cf14a36 100644 --- a/test/Macros/SwiftifyImport/SizedBy/SizeExpr.swift +++ b/test/Macros/SwiftifyImport/SizedBy/SizeExpr.swift @@ -6,8 +6,8 @@ func myFunc(_ ptr: UnsafeRawPointer, _ size: CInt, _ count: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeRawBufferPointer, _ size: CInt, _ count: CInt) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeRawBufferPointer, _ size: CInt, _ count: CInt) { // CHECK-NEXT: let _ptrCount: some BinaryInteger = size * count // CHECK-NEXT: if ptr.count < _ptrCount || _ptrCount < 0 { // CHECK-NEXT: fatalError("bounds check failure when calling unsafe function") diff --git a/test/Macros/SwiftifyImport/SizedBy/Unwrapped.swift b/test/Macros/SwiftifyImport/SizedBy/Unwrapped.swift index 031fd76c375f..656908178330 100644 --- a/test/Macros/SwiftifyImport/SizedBy/Unwrapped.swift +++ b/test/Macros/SwiftifyImport/SizedBy/Unwrapped.swift @@ -6,8 +6,8 @@ func myFunc(_ ptr: UnsafeRawPointer!, _ len: CInt) { } -// CHECK: @_alwaysEmitIntoClient public -// CHECK-NEXT: func myFunc(_ ptr: UnsafeRawBufferPointer) { +// CHECK: @_alwaysEmitIntoClient +// CHECK-NEXT: public func myFunc(_ ptr: UnsafeRawBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } From cfe7c0cd17c53c70a6a9640839ad19842fd73c0b Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Thu, 24 Apr 2025 11:13:13 -0700 Subject: [PATCH 06/10] Rename .method parameter "name" to "signature" To disambiguate overloaded methods in _SwiftifyImportProtocol we now pass the entire function signature instead of just the function name. This should be reflected in the parameter name. --- .../SwiftMacros/SwiftifyImportMacro.swift | 4 ++-- .../SwiftifyImport/CountedBy/Protocol.swift | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift index cb39aa6b07a8..9625cb19aedd 100644 --- a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift +++ b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift @@ -1625,7 +1625,7 @@ func parseProtocolMacroParam( node: enumConstructorExpr) } let argumentList = enumConstructorExpr.arguments - let methodSignatureArg = try getArgumentBySignature(argumentList, "signature") + let methodSignatureArg = try getArgumentByName(argumentList, "signature") guard let methodSignatureStringLit = methodSignatureArg.as(StringLiteralExprSyntax.self) else { throw DiagnosticError( "expected string literal for 'signature' parameter, got \(methodSignatureArg)", node: methodSignatureArg) @@ -1641,7 +1641,7 @@ func parseProtocolMacroParam( notes.append(Note(node: Syntax(method.name), message: MacroExpansionNoteMessage("did you mean '\(method.trimmed.description)'?"))) } throw DiagnosticError( - "method with signature '\(methodSignature)' not found in protocol", node: methodNameArg, notes: notes) + "method with signature '\(methodSignature)' not found in protocol", node: methodSignatureArg, notes: notes) } let paramInfoArg = try getArgumentByName(argumentList, "paramInfo") guard let paramInfoArgList = paramInfoArg.as(ArrayExprSyntax.self) else { diff --git a/test/Macros/SwiftifyImport/CountedBy/Protocol.swift b/test/Macros/SwiftifyImport/CountedBy/Protocol.swift index 4ae66d754b6c..4c712ee77ea5 100644 --- a/test/Macros/SwiftifyImport/CountedBy/Protocol.swift +++ b/test/Macros/SwiftifyImport/CountedBy/Protocol.swift @@ -2,7 +2,7 @@ // RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -plugin-path %swift-plugin-dir -dump-macro-expansions -enable-experimental-feature Span -enable-experimental-feature LifetimeDependence 2>&1 | %FileCheck --match-full-lines %s -@_SwiftifyImportProtocol(.method(name: "func myFunc(_ ptr: UnsafePointer, _ len: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len")])) +@_SwiftifyImportProtocol(.method(signature: "func myFunc(_ ptr: UnsafePointer, _ len: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len")])) protocol SimpleProtocol { func myFunc(_ ptr: UnsafePointer, _ len: CInt) } @@ -14,8 +14,8 @@ protocol SimpleProtocol { // CHECK-NEXT: } // CHECK-NEXT: } -@_SwiftifyImportProtocol(.method(name: "func foo(_ ptr: UnsafePointer, _ len: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len"), .nonescaping(pointer: .param(1))]), - .method(name: "func bar(_ len: CInt) -> UnsafePointer", paramInfo: [.countedBy(pointer: .return, count: "len"), .nonescaping(pointer: .return), .lifetimeDependence(dependsOn: .self, pointer: .return, type: .borrow)])) +@_SwiftifyImportProtocol(.method(signature: "func foo(_ ptr: UnsafePointer, _ len: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len"), .nonescaping(pointer: .param(1))]), + .method(signature: "func bar(_ len: CInt) -> UnsafePointer", paramInfo: [.countedBy(pointer: .return, count: "len"), .nonescaping(pointer: .return), .lifetimeDependence(dependsOn: .self, pointer: .return, type: .borrow)])) protocol SpanProtocol { func foo(_ ptr: UnsafePointer, _ len: CInt) func bar(_ len: CInt) -> UnsafePointer @@ -35,8 +35,8 @@ protocol SpanProtocol { // CHECK-NEXT: } // CHECK-NEXT: } -@_SwiftifyImportProtocol(.method(name: "func foo(_ ptr: UnsafePointer, _ len: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len"), .nonescaping(pointer: .param(1))]), - .method(name: "func bar(_ ptr: UnsafePointer, _ len: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len")])) +@_SwiftifyImportProtocol(.method(signature: "func foo(_ ptr: UnsafePointer, _ len: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len"), .nonescaping(pointer: .param(1))]), + .method(signature: "func bar(_ ptr: UnsafePointer, _ len: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len")])) protocol MixedProtocol { func foo(_ ptr: UnsafePointer, _ len: CInt) func bar(_ ptr: UnsafePointer, _ len: CInt) @@ -55,8 +55,8 @@ protocol MixedProtocol { // CHECK-NEXT: } // CHECK-NEXT: } -@_SwiftifyImportProtocol(.method(name: "func foo(_ ptr: UnsafePointer, _ len1: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len1")]), - .method(name: "func foo(bar: UnsafePointer, _ len2: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len2")])) +@_SwiftifyImportProtocol(.method(signature: "func foo(_ ptr: UnsafePointer, _ len1: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len1")]), + .method(signature: "func foo(bar: UnsafePointer, _ len2: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len2")])) protocol OverloadedProtocol { func foo(_ ptr: UnsafePointer, _ len1: CInt) func foo(bar: UnsafePointer, _ len2: CInt) @@ -74,7 +74,7 @@ protocol OverloadedProtocol { // CHECK-NEXT: } // CHECK-NEXT: } -@_SwiftifyImportProtocol(.method(name: "open func myFunc(_ ptr: UnsafePointer, _ len: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len")])) +@_SwiftifyImportProtocol(.method(signature: "open func myFunc(_ ptr: UnsafePointer, _ len: CInt)", paramInfo: [.countedBy(pointer: .param(1), count: "len")])) class SimpleClass { open func myFunc(_ ptr: UnsafePointer, _ len: CInt) {} } From bb55d6c66a8172fea0b5222fa5d05d83f3ceb997 Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Thu, 24 Apr 2025 11:15:52 -0700 Subject: [PATCH 07/10] Update assert We previously asserted that a variable contained a FileUnit, but the intention of this was to separate it from SourceFiles, and SourceFile is a subtype of FileUnit, so it wouldn't trigger if the variable actually contained a SourceFile. --- lib/Sema/TypeCheckMacros.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Sema/TypeCheckMacros.cpp b/lib/Sema/TypeCheckMacros.cpp index 986c4972cb1d..a04b12b5f91c 100644 --- a/lib/Sema/TypeCheckMacros.cpp +++ b/lib/Sema/TypeCheckMacros.cpp @@ -1380,7 +1380,7 @@ static SourceFile *evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, attachedTo->getDeclContext()->getModuleScopeContext())); dc = attachedTo->getDeclContext(); // decls imported from clang do not have a SourceFile - assert(isa(dc)); + assert(isa(dc) && !isa(dc)); } } else { dc = attachedTo->getInnermostDeclContext(); From 1305b27116c52335157ec81d5db8f631d27e1776 Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Thu, 24 Apr 2025 11:18:17 -0700 Subject: [PATCH 08/10] add _SwiftifyProtocolMethodInfo to abi tests --- test/abi/Inputs/macOS/arm64/stdlib/baseline | 4 ++++ test/abi/Inputs/macOS/arm64/stdlib/baseline-asserts | 4 ++++ test/abi/Inputs/macOS/x86_64/stdlib/baseline | 4 ++++ test/abi/Inputs/macOS/x86_64/stdlib/baseline-asserts | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/test/abi/Inputs/macOS/arm64/stdlib/baseline b/test/abi/Inputs/macOS/arm64/stdlib/baseline index 7fa9a942d906..4dfa8d6a7c56 100644 --- a/test/abi/Inputs/macOS/arm64/stdlib/baseline +++ b/test/abi/Inputs/macOS/arm64/stdlib/baseline @@ -8937,6 +8937,10 @@ _$ss27_BidirectionalCollectionBoxCMu _$ss27_BidirectionalCollectionBoxCfD _$ss27_BidirectionalCollectionBoxCfd _$ss27_BidirectionalCollectionBoxCy7ElementQzs09_AnyIndexC0_pcig +_$ss27_SwiftifyProtocolMethodInfoO6methodyABSS_Says01_aD0OGtcABmFWC +_$ss27_SwiftifyProtocolMethodInfoOMa +_$ss27_SwiftifyProtocolMethodInfoOMn +_$ss27_SwiftifyProtocolMethodInfoON _$ss27_allocateUninitializedArrayySayxG_BptBwlF _$ss27_bridgeAnythingToObjectiveCyyXlxlF _$ss27_debuggerTestingCheckExpectyySS_SStF diff --git a/test/abi/Inputs/macOS/arm64/stdlib/baseline-asserts b/test/abi/Inputs/macOS/arm64/stdlib/baseline-asserts index 4807b19909ef..1589099082f8 100644 --- a/test/abi/Inputs/macOS/arm64/stdlib/baseline-asserts +++ b/test/abi/Inputs/macOS/arm64/stdlib/baseline-asserts @@ -8949,6 +8949,10 @@ _$ss27_BidirectionalCollectionBoxCMu _$ss27_BidirectionalCollectionBoxCfD _$ss27_BidirectionalCollectionBoxCfd _$ss27_BidirectionalCollectionBoxCy7ElementQzs09_AnyIndexC0_pcig +_$ss27_SwiftifyProtocolMethodInfoO6methodyABSS_Says01_aD0OGtcABmFWC +_$ss27_SwiftifyProtocolMethodInfoOMa +_$ss27_SwiftifyProtocolMethodInfoOMn +_$ss27_SwiftifyProtocolMethodInfoON _$ss27_allocateUninitializedArrayySayxG_BptBwlF _$ss27_bridgeAnythingToObjectiveCyyXlxlF _$ss27_debuggerTestingCheckExpectyySS_SStF diff --git a/test/abi/Inputs/macOS/x86_64/stdlib/baseline b/test/abi/Inputs/macOS/x86_64/stdlib/baseline index bc79fe5f8987..e05241dc5d31 100644 --- a/test/abi/Inputs/macOS/x86_64/stdlib/baseline +++ b/test/abi/Inputs/macOS/x86_64/stdlib/baseline @@ -8962,6 +8962,10 @@ _$ss27_BidirectionalCollectionBoxCMu _$ss27_BidirectionalCollectionBoxCfD _$ss27_BidirectionalCollectionBoxCfd _$ss27_BidirectionalCollectionBoxCy7ElementQzs09_AnyIndexC0_pcig +_$ss27_SwiftifyProtocolMethodInfoO6methodyABSS_Says01_aD0OGtcABmFWC +_$ss27_SwiftifyProtocolMethodInfoOMa +_$ss27_SwiftifyProtocolMethodInfoOMn +_$ss27_SwiftifyProtocolMethodInfoON _$ss27_allocateUninitializedArrayySayxG_BptBwlF _$ss27_bridgeAnythingToObjectiveCyyXlxlF _$ss27_debuggerTestingCheckExpectyySS_SStF diff --git a/test/abi/Inputs/macOS/x86_64/stdlib/baseline-asserts b/test/abi/Inputs/macOS/x86_64/stdlib/baseline-asserts index ba9fb06fe7c5..cc4c136826ca 100644 --- a/test/abi/Inputs/macOS/x86_64/stdlib/baseline-asserts +++ b/test/abi/Inputs/macOS/x86_64/stdlib/baseline-asserts @@ -8974,6 +8974,10 @@ _$ss27_BidirectionalCollectionBoxCMu _$ss27_BidirectionalCollectionBoxCfD _$ss27_BidirectionalCollectionBoxCfd _$ss27_BidirectionalCollectionBoxCy7ElementQzs09_AnyIndexC0_pcig +_$ss27_SwiftifyProtocolMethodInfoO6methodyABSS_Says01_aD0OGtcABmFWC +_$ss27_SwiftifyProtocolMethodInfoOMa +_$ss27_SwiftifyProtocolMethodInfoOMn +_$ss27_SwiftifyProtocolMethodInfoON _$ss27_allocateUninitializedArrayySayxG_BptBwlF _$ss27_bridgeAnythingToObjectiveCyyXlxlF _$ss27_debuggerTestingCheckExpectyySS_SStF From 6a28b6a5aed4f5d6e1714a93cbc1e4bdc86dd742 Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Thu, 24 Apr 2025 14:45:52 -0700 Subject: [PATCH 09/10] Pass availability to _SwiftifyImport This was only passed to _SwiftifyImportProtocol, now it is also passed to _SwiftifyImport. This results in @available being attached to generated overloads that use [Mutable][Raw]Span. --- lib/ClangImporter/ImportDecl.cpp | 1 + .../C/swiftify-import/Inputs/counted-by-noescape.h | 2 +- .../Interop/C/swiftify-import/Inputs/sized-by-noescape.h | 2 +- test/Interop/C/swiftify-import/counted-by-noescape.swift | 9 ++++++++- test/Interop/C/swiftify-import/sized-by-noescape.swift | 9 ++++++++- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index f2d0f6feecde..ef667e6cab71 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -9332,6 +9332,7 @@ void ClangImporter::Implementation::swiftify( SwiftifyInfoPrinter printer(getClangASTContext(), SwiftContext, out); if (!swiftifyImpl(printer, MappedDecl)) return; + printer.printAvailability(); printer.printTypeMapping(); } diff --git a/test/Interop/C/swiftify-import/Inputs/counted-by-noescape.h b/test/Interop/C/swiftify-import/Inputs/counted-by-noescape.h index 6ea131586ac7..28b4be1c0c4b 100644 --- a/test/Interop/C/swiftify-import/Inputs/counted-by-noescape.h +++ b/test/Interop/C/swiftify-import/Inputs/counted-by-noescape.h @@ -7,7 +7,7 @@ void simple(int len, int * __counted_by(len) __noescape p); void swiftAttr(int len, int *p) __attribute__(( - swift_attr("@_SwiftifyImport(.countedBy(pointer: .param(2), count: \"len\"), .nonescaping(pointer: .param(2)))"))); + swift_attr("@_SwiftifyImport(.countedBy(pointer: .param(2), count: \"len\"), .nonescaping(pointer: .param(2)), availability: [\"MutableSpan\": \"macOS 9999, *\"])"))); void shared(int len, int * __counted_by(len) __noescape p1, int * __counted_by(len) __noescape p2); diff --git a/test/Interop/C/swiftify-import/Inputs/sized-by-noescape.h b/test/Interop/C/swiftify-import/Inputs/sized-by-noescape.h index 7d1865456904..d39476fc8797 100644 --- a/test/Interop/C/swiftify-import/Inputs/sized-by-noescape.h +++ b/test/Interop/C/swiftify-import/Inputs/sized-by-noescape.h @@ -6,7 +6,7 @@ void simple(int len, const void * __sized_by(len) __noescape p); void swiftAttr(int len, const void *p) __attribute__((swift_attr( - "@_SwiftifyImport(.sizedBy(pointer: .param(2), size: \"len\"), .nonescaping(pointer: .param(2)))"))); + "@_SwiftifyImport(.sizedBy(pointer: .param(2), size: \"len\"), .nonescaping(pointer: .param(2)), availability: [\"Span\": \"macOS 9999, *\"])"))); void shared(int len, const void * __sized_by(len) __noescape p1, const void * __sized_by(len) __noescape p2); diff --git a/test/Interop/C/swiftify-import/counted-by-noescape.swift b/test/Interop/C/swiftify-import/counted-by-noescape.swift index 339789074c95..024a049a507c 100644 --- a/test/Interop/C/swiftify-import/counted-by-noescape.swift +++ b/test/Interop/C/swiftify-import/counted-by-noescape.swift @@ -11,21 +11,28 @@ import CountedByNoEscapeClang -// CHECK: @lifetime(p: copy p) +// CHECK: @available(macOS 9999, *) +// CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func complexExpr(_ len: Int32, _ offset: Int32, _ p: inout MutableSpan) +// CHECK-NEXT: @available(macOS 9999, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ p: inout MutableSpan) +// CHECK-NEXT: @available(macOS 9999, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ p: inout MutableSpan) +// CHECK-NEXT: @available(macOS 9999, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func returnLifetimeBound(_ len1: Int32, _ p: inout MutableSpan) -> MutableSpan // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func returnPointer(_ len: Int32) -> UnsafeMutableBufferPointer +// CHECK-NEXT: @available(macOS 9999, *) // CHECK-NEXT: @lifetime(p1: copy p1) // CHECK-NEXT: @lifetime(p2: copy p2) // CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int32, _ p1: inout MutableSpan, _ p2: inout MutableSpan) +// CHECK-NEXT: @available(macOS 9999, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func simple(_ p: inout MutableSpan) +// CHECK-NEXT: @available(macOS 9999, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func swiftAttr(_ p: inout MutableSpan) diff --git a/test/Interop/C/swiftify-import/sized-by-noescape.swift b/test/Interop/C/swiftify-import/sized-by-noescape.swift index 2510053201ea..82c53737cbef 100644 --- a/test/Interop/C/swiftify-import/sized-by-noescape.swift +++ b/test/Interop/C/swiftify-import/sized-by-noescape.swift @@ -9,11 +9,18 @@ // Check that ClangImporter correctly infers and expands @_SwiftifyImport macros for functions with __sized_by __noescape parameters. import SizedByNoEscapeClang -// CHECK: @_alwaysEmitIntoClient public func complexExpr(_ len: Int{{.*}}, _ offset: Int{{.*}}, _ p: RawSpan) +// CHECK: @available(macOS 9999, *) +// CHECK-NEXT: @_alwaysEmitIntoClient public func complexExpr(_ len: Int{{.*}}, _ offset: Int{{.*}}, _ p: RawSpan) +// CHECK-NEXT: @available(macOS 9999, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ p: RawSpan) +// CHECK-NEXT: @available(macOS 9999, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ p: RawSpan) +// CHECK-NEXT: @available(macOS 9999, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func opaque(_ p: RawSpan) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func returnPointer(_ len: Int{{.*}}) -> UnsafeRawBufferPointer +// CHECK-NEXT: @available(macOS 9999, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int{{.*}}, _ p1: RawSpan, _ p2: RawSpan) +// CHECK-NEXT: @available(macOS 9999, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func simple(_ p: RawSpan) +// CHECK-NEXT: @available(macOS 9999, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func swiftAttr(_ p: RawSpan) From 93e659ba13b8510698069e74f00f099e82cabbfe Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Mon, 28 Apr 2025 22:38:13 -0700 Subject: [PATCH 10/10] Don't depend on implicit lifetime of Escapable inout Escapable inout parameters don't have an implicit lifetime that can be borrowed or copied, because the caller doesn't know what the lifetime of the new value is, if the callee writes to the parameter. Depending on the lifetime of an Escapable inout parameter without explicit lifetime annotation results in an error, so _SwiftifyImport should not do that. --- lib/AST/ConformanceLookup.cpp | 14 +----- lib/ClangImporter/ImportDecl.cpp | 46 +++++++++++++++++-- .../swiftify-import/counted-by-noescape.swift | 12 ++--- .../C/swiftify-import/sized-by-noescape.swift | 12 ++--- .../Cxx/stdlib/std-span-interface.swift | 30 +++++++++--- 5 files changed, 77 insertions(+), 37 deletions(-) diff --git a/lib/AST/ConformanceLookup.cpp b/lib/AST/ConformanceLookup.cpp index 5719d1d1720f..87cb80a80181 100644 --- a/lib/AST/ConformanceLookup.cpp +++ b/lib/AST/ConformanceLookup.cpp @@ -534,19 +534,7 @@ static ProtocolConformanceRef getPackTypeConformance( } static bool shouldExpandExtensionMacro(Evaluator &evaluator, NominalTypeDecl *nominal) { - if (evaluator.hasActiveRequest(ExpandExtensionMacros{nominal})) { - return false; - } - - // Expanding an extension macro for this type will require pretty printing the node, - // leading to evaluation of it's members. Once the macro expansion requrest has started - // it's too late to check for cycles. - for (auto member : nominal->getMembers()) - if (auto VD = dyn_cast(member)) - if (evaluator.hasActiveRequest(InterfaceTypeRequest{VD})) - return false; - - return true; + return !evaluator.hasActiveRequest(ExpandExtensionMacros{nominal}); } ProtocolConformanceRef diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index ef667e6cab71..6c156bd97c67 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -9225,6 +9225,30 @@ class SwiftifyProtocolInfoPrinter : public SwiftifyInfoPrinter { } }; +static bool isLifetimeTarget(const FuncDecl *Func, const ParamDecl *Param, + size_t paramIndex) { + for (auto attr : Func->getAttrs().getAttributes()) { + auto entry = attr->getLifetimeEntry(); + auto descriptorOpt = entry->getTargetDescriptor(); + if (!descriptorOpt.has_value()) + continue; + auto descriptor = descriptorOpt.value(); + switch (descriptor.getDescriptorKind()) { + case LifetimeDescriptor::DescriptorKind::Named: + if (Param->getParameterName() == descriptor.getName()) + return true; + continue; + case LifetimeDescriptor::DescriptorKind::Ordered: + if (paramIndex == descriptor.getIndex()) + return true; + continue; + case LifetimeDescriptor::DescriptorKind::Self: + continue; + } + } + return false; +} + static bool swiftifyImpl(SwiftifyInfoPrinter &printer, const FuncDecl *MappedDecl) { const clang::Decl *ClangDecl = MappedDecl->getClangDecl(); auto FuncD = dyn_cast(ClangDecl); @@ -9270,11 +9294,23 @@ static bool swiftifyImpl(SwiftifyInfoPrinter &printer, const FuncDecl *MappedDec paramHasLifetimeInfo = true; } if (clangParam->hasAttr()) { - printer.printLifetimeboundReturn( - index, !paramHasBoundsInfo && - swiftParam->getInterfaceType()->isEscapable()); - paramHasLifetimeInfo = true; - returnHasLifetimeInfo = true; + // Escapable types should have their ownership borrowed, while + // nonescapable should have their lifetime copied. + // If this parameter has bounds info, the wrapper version of it will be + // nonescapable (Span) however, so then it should be copied despite being + // escapable in the original. + bool shouldBorrowLifetime = + !paramHasBoundsInfo && swiftParam->getInterfaceType()->isEscapable(); + // For inout parameters the callee could set the parameter to a new value + // with a lifetime that the caller is not aware of. So unless there is + // explicit lifetime info for the parameter, we can't borrow the lifetime + // of an inout. + if (!swiftParam->isInOut() || + isLifetimeTarget(MappedDecl, swiftParam, index)) { + printer.printLifetimeboundReturn(index, shouldBorrowLifetime); + paramHasLifetimeInfo = true; + returnHasLifetimeInfo = true; + } } if (paramIsStdSpan && paramHasLifetimeInfo) attachMacro = true; diff --git a/test/Interop/C/swiftify-import/counted-by-noescape.swift b/test/Interop/C/swiftify-import/counted-by-noescape.swift index 024a049a507c..3d06f583c915 100644 --- a/test/Interop/C/swiftify-import/counted-by-noescape.swift +++ b/test/Interop/C/swiftify-import/counted-by-noescape.swift @@ -11,25 +11,25 @@ import CountedByNoEscapeClang -// CHECK: @available(macOS 9999, *) +// CHECK: @available(macOS {{.*}}, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func complexExpr(_ len: Int32, _ offset: Int32, _ p: inout MutableSpan) -// CHECK-NEXT: @available(macOS 9999, *) +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ p: inout MutableSpan) -// CHECK-NEXT: @available(macOS 9999, *) +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ p: inout MutableSpan) -// CHECK-NEXT: @available(macOS 9999, *) +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func returnLifetimeBound(_ len1: Int32, _ p: inout MutableSpan) -> MutableSpan // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func returnPointer(_ len: Int32) -> UnsafeMutableBufferPointer -// CHECK-NEXT: @available(macOS 9999, *) +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @lifetime(p1: copy p1) // CHECK-NEXT: @lifetime(p2: copy p2) // CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int32, _ p1: inout MutableSpan, _ p2: inout MutableSpan) -// CHECK-NEXT: @available(macOS 9999, *) +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func simple(_ p: inout MutableSpan) // CHECK-NEXT: @available(macOS 9999, *) diff --git a/test/Interop/C/swiftify-import/sized-by-noescape.swift b/test/Interop/C/swiftify-import/sized-by-noescape.swift index 82c53737cbef..363eee704bea 100644 --- a/test/Interop/C/swiftify-import/sized-by-noescape.swift +++ b/test/Interop/C/swiftify-import/sized-by-noescape.swift @@ -9,18 +9,18 @@ // Check that ClangImporter correctly infers and expands @_SwiftifyImport macros for functions with __sized_by __noescape parameters. import SizedByNoEscapeClang -// CHECK: @available(macOS 9999, *) +// CHECK: @available(macOS {{.*}}, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func complexExpr(_ len: Int{{.*}}, _ offset: Int{{.*}}, _ p: RawSpan) -// CHECK-NEXT: @available(macOS 9999, *) +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func nonnull(_ p: RawSpan) -// CHECK-NEXT: @available(macOS 9999, *) +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullUnspecified(_ p: RawSpan) -// CHECK-NEXT: @available(macOS 9999, *) +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func opaque(_ p: RawSpan) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func returnPointer(_ len: Int{{.*}}) -> UnsafeRawBufferPointer -// CHECK-NEXT: @available(macOS 9999, *) +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func shared(_ len: Int{{.*}}, _ p1: RawSpan, _ p2: RawSpan) -// CHECK-NEXT: @available(macOS 9999, *) +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func simple(_ p: RawSpan) // CHECK-NEXT: @available(macOS 9999, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func swiftAttr(_ p: RawSpan) diff --git a/test/Interop/Cxx/stdlib/std-span-interface.swift b/test/Interop/Cxx/stdlib/std-span-interface.swift index b910668fcdb1..fadf252abb0b 100644 --- a/test/Interop/Cxx/stdlib/std-span-interface.swift +++ b/test/Interop/Cxx/stdlib/std-span-interface.swift @@ -13,7 +13,8 @@ import StdSpan import CxxStdlib // CHECK: struct DependsOnSelf { -// CHECK: @lifetime(borrow self) +// CHECK: @available(macOS {{.*}}, *) +// CHECK-NEXT: @lifetime(borrow self) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public borrowing func get() -> Span // CHECK-NEXT: borrowing func get() -> ConstSpanOfInt @@ -23,51 +24,66 @@ import CxxStdlib // CHECK-NEXT: func funcWithSafeWrapper3(_ v: borrowing VecOfInt) -> ConstSpanOfInt // CHECK: struct X { // CHECK-NEXT: init() +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @_alwaysEmitIntoClient public mutating func methodWithSafeWrapper(_ s: Span) // CHECK-NEXT: mutating func methodWithSafeWrapper(_ s: ConstSpanOfInt) // CHECK-NEXT: } // CHECK: struct SpanWithoutTypeAlias { // CHECK-NEXT: init() +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @lifetime(borrow self) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public mutating func bar() -> Span // CHECK-NEXT: mutating func bar() -> std.{{.*}}span<__cxxConst, _C{{.*}}_{{.*}}> +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @_alwaysEmitIntoClient public mutating func foo(_ s: Span) // CHECK-NEXT: mutating func foo(_ s: std.{{.*}}span<__cxxConst, _C{{.*}}_{{.*}}>) // CHECK-NEXT: } -// CHECK: @lifetime(s: copy s) +// CHECK: @available(macOS {{.*}}, *) +// CHECK-NEXT: @lifetime(s: copy s) // CHECK-NEXT: @_alwaysEmitIntoClient public func FuncWithMutableSafeWrapper(_ s: inout MutableSpan) +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @lifetime(copy s) // CHECK-NEXT: @lifetime(s: copy s) // CHECK-NEXT: @_alwaysEmitIntoClient public func FuncWithMutableSafeWrapper2(_ s: inout MutableSpan) -> MutableSpan -// CHECK-NEXT: @lifetime(borrow v) -// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func FuncWithMutableSafeWrapper3(_ v: inout VecOfInt) -> MutableSpan +// CHECK-NOT: FuncWithMutableSafeWrapper3 +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper1(_ p: inout MutableSpan) -> MutableSpan -// CHECK-NEXT: @lifetime(borrow v) -// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func MixedFuncWithMutableSafeWrapper2(_ v: inout VecOfInt, _ len: Int32) -> MutableSpan +// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func MixedFuncWithMutableSafeWrapper2(_ v: inout VecOfInt, _ len: Int32) -> UnsafeMutableBufferPointer +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @lifetime(s: copy s) // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper3(_ s: inout MutableSpan, _ p: UnsafeMutableBufferPointer) +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @lifetime(s: copy s) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper4(_ s: inout MutableSpan, _ p: inout MutableSpan) +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper5(_ s: SpanOfInt, _ p: inout MutableSpan) // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper6(_ s: SpanOfInt, _ p: UnsafeMutableBufferPointer) // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper7(_ p: UnsafeMutableBufferPointer) -> SpanOfInt -// CHECK: @_alwaysEmitIntoClient public func funcWithSafeWrapper(_ s: Span) +// CHECK: @available(macOS {{.*}}, *) +// CHECK-NEXT: @_alwaysEmitIntoClient public func funcWithSafeWrapper(_ s: Span) +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @lifetime(copy s) // CHECK-NEXT: @_alwaysEmitIntoClient public func funcWithSafeWrapper2(_ s: Span) -> Span +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @lifetime(borrow v) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func funcWithSafeWrapper3(_ v: borrowing VecOfInt) -> Span +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @lifetime(copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper1(_ p: Span) -> Span +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @lifetime(borrow v) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func mixedFuncWithSafeWrapper2(_ v: borrowing VecOfInt, _ len: Int32) -> Span +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper3(_ s: Span, _ p: UnsafeMutableBufferPointer) +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper4(_ s: Span, _ p: Span) +// CHECK-NEXT: @available(macOS {{.*}}, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper5(_ s: ConstSpanOfInt, _ p: Span) // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper6(_ s: ConstSpanOfInt, _ p: UnsafeMutableBufferPointer) // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper7(_ p: UnsafeBufferPointer) -> ConstSpanOfInt