diff --git a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift index 652c53b948aa9..4188d29273586 100644 --- a/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift +++ b/lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift @@ -45,19 +45,11 @@ protocol ParamInfo: CustomStringConvertible { ) -> BoundsCheckedThunkBuilder } -func getParamName(_ param: FunctionParameterSyntax, _ paramIndex: Int) -> TokenSyntax { - let name = param.secondName ?? param.firstName - if name.trimmed.text == "_" { - return "_param\(raw: paramIndex)" - } - return name -} - func tryGetParamName(_ funcDecl: FunctionDeclSyntax, _ expr: SwiftifyExpr) -> TokenSyntax? { switch expr { case .param(let i): let funcParam = getParam(funcDecl, i - 1) - return getParamName(funcParam, i - 1) + return funcParam.name case .`self`: return .keyword(.self) default: return nil @@ -427,12 +419,7 @@ struct FunctionCallBuilder: BoundsCheckedThunkBuilder { // filter out deleted parameters, i.e. ones where argTypes[i] _contains_ nil return type == nil || type! != nil }.map { (i: Int, e: FunctionParameterSyntax) in - let param = e.with(\.type, (argTypes[i] ?? e.type)!) - let name = param.secondName ?? param.firstName - if name.trimmed.text == "_" { - return param.with(\.secondName, getParamName(param, i)) - } - return param + e.with(\.type, (argTypes[i] ?? e.type)!) } if let last = newParams.popLast() { newParams.append(last.with(\.trailingComma, nil)) @@ -450,9 +437,7 @@ struct FunctionCallBuilder: BoundsCheckedThunkBuilder { let functionRef = DeclReferenceExprSyntax(baseName: base.name) let args: [ExprSyntax] = base.signature.parameterClause.parameters.enumerated() .map { (i: Int, param: FunctionParameterSyntax) in - let name = getParamName(param, i) - let declref = DeclReferenceExprSyntax(baseName: name) - return pointerArgs[i] ?? ExprSyntax(declref) + return pointerArgs[i] ?? ExprSyntax("\(param.name)") } let labels: [TokenSyntax?] = base.signature.parameterClause.parameters.map { param in let firstName = param.firstName.trimmed @@ -468,7 +453,8 @@ struct FunctionCallBuilder: BoundsCheckedThunkBuilder { comma = .commaToken() } let colon: TokenSyntax? = label != nil ? .colonToken() : nil - return LabeledExprSyntax(label: label, colon: colon, expression: arg, trailingComma: comma) + // The compiler emits warnings if you unnecessarily escape labels in function calls + return LabeledExprSyntax(label: label?.withoutBackticks, colon: colon, expression: arg, trailingComma: comma) } let call = ExprSyntax( FunctionCallExprSyntax( @@ -510,7 +496,7 @@ struct CxxSpanThunkBuilder: SpanBoundsThunkBuilder, ParamBoundsThunkBuilder { args[index] = ExprSyntax("\(raw: typeName)(\(raw: name))") return try base.buildFunctionCall(args) } else { - let unwrappedName = TokenSyntax("_\(name)Ptr") + let unwrappedName = TokenSyntax("_\(name.withoutBackticks)Ptr") args[index] = ExprSyntax("\(raw: typeName)(\(unwrappedName))") let call = try base.buildFunctionCall(args) @@ -663,7 +649,7 @@ extension ParamBoundsThunkBuilder { } var name: TokenSyntax { - getParamName(param, index) + param.name } } @@ -796,7 +782,7 @@ struct CountedOrSizedPointerThunkBuilder: ParamBoundsThunkBuilder, PointerBounds } func buildUnwrapCall(_ argOverrides: [Int: ExprSyntax]) throws -> ExprSyntax { - let unwrappedName = TokenSyntax("_\(name)Ptr") + let unwrappedName = TokenSyntax("_\(name.withoutBackticks)Ptr").escapeIfNeeded var args = argOverrides let argExpr = ExprSyntax("\(unwrappedName).baseAddress") assert(args[index] == nil) @@ -809,7 +795,7 @@ struct CountedOrSizedPointerThunkBuilder: ParamBoundsThunkBuilder, PointerBounds } } let call = try base.buildFunctionCall(args) - let ptrRef = unwrapIfNullable(ExprSyntax(DeclReferenceExprSyntax(baseName: name))) + let ptrRef = unwrapIfNullable("\(name)") let funcName = switch (isSizedBy, isMutablePointerType(oldType)) { @@ -1004,7 +990,7 @@ func parseSwiftifyExpr(_ expr: ExprSyntax) throws -> SwiftifyExpr { } func parseCountedByEnum( - _ enumConstructorExpr: FunctionCallExprSyntax, _ signature: FunctionSignatureSyntax + _ enumConstructorExpr: FunctionCallExprSyntax, _ signature: FunctionSignatureSyntax, _ rewriter: CountExprRewriter ) throws -> ParamInfo { let argumentList = enumConstructorExpr.arguments let pointerExprArg = try getArgumentByName(argumentList, "pointer") @@ -1015,7 +1001,8 @@ func parseCountedByEnum( "expected string literal for 'count' parameter, got \(countExprArg)", node: countExprArg) } let unwrappedCountExpr = ExprSyntax(stringLiteral: countExprStringLit.representedLiteralValue!) - if let countVar = unwrappedCountExpr.as(DeclReferenceExprSyntax.self) { + let rewrittenCountExpr = rewriter.visit(unwrappedCountExpr) + if let countVar = rewrittenCountExpr.as(DeclReferenceExprSyntax.self) { // Perform this lookup here so we can override the position to point to the string literal // instead of line 1, column 1 do { @@ -1025,11 +1012,11 @@ func parseCountedByEnum( } } return CountedBy( - pointerIndex: pointerExpr, count: unwrappedCountExpr, sizedBy: false, + pointerIndex: pointerExpr, count: rewrittenCountExpr, sizedBy: false, nonescaping: false, dependencies: [], original: ExprSyntax(enumConstructorExpr)) } -func parseSizedByEnum(_ enumConstructorExpr: FunctionCallExprSyntax) throws -> ParamInfo { +func parseSizedByEnum(_ enumConstructorExpr: FunctionCallExprSyntax, _ rewriter: CountExprRewriter) throws -> ParamInfo { let argumentList = enumConstructorExpr.arguments let pointerExprArg = try getArgumentByName(argumentList, "pointer") let pointerExpr: SwiftifyExpr = try parseSwiftifyExpr(pointerExprArg) @@ -1039,8 +1026,9 @@ func parseSizedByEnum(_ enumConstructorExpr: FunctionCallExprSyntax) throws -> P "expected string literal for 'size' parameter, got \(sizeExprArg)", node: sizeExprArg) } let unwrappedCountExpr = ExprSyntax(stringLiteral: sizeExprStringLit.representedLiteralValue!) + let rewrittenCountExpr = rewriter.visit(unwrappedCountExpr) return CountedBy( - pointerIndex: pointerExpr, count: unwrappedCountExpr, sizedBy: true, nonescaping: false, + pointerIndex: pointerExpr, count: rewrittenCountExpr, sizedBy: true, nonescaping: false, dependencies: [], original: ExprSyntax(enumConstructorExpr)) } @@ -1177,7 +1165,7 @@ func parseCxxSpansInSignature( } func parseMacroParam( - _ paramAST: LabeledExprSyntax, _ signature: FunctionSignatureSyntax, + _ paramAST: LabeledExprSyntax, _ signature: FunctionSignatureSyntax, _ rewriter: CountExprRewriter, nonescapingPointers: inout Set, lifetimeDependencies: inout [SwiftifyExpr: [LifetimeDependence]] ) throws -> ParamInfo? { @@ -1188,8 +1176,8 @@ func parseMacroParam( } let enumName = try parseEnumName(paramExpr) switch enumName { - case "countedBy": return try parseCountedByEnum(enumConstructorExpr, signature) - case "sizedBy": return try parseSizedByEnum(enumConstructorExpr) + case "countedBy": return try parseCountedByEnum(enumConstructorExpr, signature, rewriter) + case "sizedBy": return try parseSizedByEnum(enumConstructorExpr, rewriter) case "endedBy": return try parseEndedByEnum(enumConstructorExpr) case "nonescaping": let index = try parseNonEscaping(enumConstructorExpr) @@ -1438,7 +1426,7 @@ func paramLifetimeAttributes( if !isMutableSpan(param.type) { continue } - let paramName = param.secondName ?? param.firstName + let paramName = param.name if containsLifetimeAttr(oldAttrs, for: paramName) { continue } @@ -1456,6 +1444,61 @@ func paramLifetimeAttributes( return defaultLifetimes } +class CountExprRewriter: SyntaxRewriter { + public let nameMap: [String: String] + + init(_ renamedParams: [String: String]) { + nameMap = renamedParams + } + + override func visit(_ node: DeclReferenceExprSyntax) -> ExprSyntax { + if let newName = nameMap[node.baseName.trimmed.text] { + return ExprSyntax( + node.with( + \.baseName, + .identifier( + newName, leadingTrivia: node.baseName.leadingTrivia, + trailingTrivia: node.baseName.trailingTrivia))) + } + return escapeIfNeeded(node) + } +} + +func renameParameterNamesIfNeeded(_ funcDecl: FunctionDeclSyntax) -> (FunctionDeclSyntax, CountExprRewriter) { + let params = funcDecl.signature.parameterClause.parameters + let funcName = funcDecl.name.withoutBackticks.trimmed.text + let shouldRename = params.contains(where: { param in + let paramName = param.name.trimmed.text + return paramName == "_" || paramName == funcName || "`\(paramName)`" == funcName + }) + var renamedParams: [String: String] = [:] + let newParams = params.enumerated().map { (i, param) in + let secondName = if shouldRename { + // Including funcName in name prevents clash with function name. + // Renaming all parameters if one requires renaming guarantees that other parameters don't clash with the renamed one. + TokenSyntax("_\(raw: funcName)_param\(raw: i)") + } else { + param.secondName?.escapeIfNeeded + } + let firstName = param.firstName.escapeIfNeeded + let newParam = param.with(\.secondName, secondName) + .with(\.firstName, firstName) + let newName = newParam.name.trimmed.text + let oldName = param.name.trimmed.text + if newName != oldName { + renamedParams[oldName] = newName + } + return newParam + } + let newDecl = if renamedParams.count > 0 { + funcDecl.with(\.signature.parameterClause.parameters, FunctionParameterListSyntax(newParams)) + } else { + // Keeps source locations for diagnostics, in the common case where nothing was renamed + funcDecl + } + return (newDecl, CountExprRewriter(renamedParams)) +} + /// 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, @@ -1469,9 +1512,10 @@ public struct SwiftifyImportMacro: PeerMacro { in context: some MacroExpansionContext ) throws -> [DeclSyntax] { do { - guard let funcDecl = declaration.as(FunctionDeclSyntax.self) else { + guard let origFuncDecl = declaration.as(FunctionDeclSyntax.self) else { throw DiagnosticError("@_SwiftifyImport only works on functions", node: declaration) } + let (funcDecl, rewriter) = renameParameterNamesIfNeeded(origFuncDecl) let argumentList = node.arguments!.as(LabeledExprListSyntax.self)! var arguments = [LabeledExprSyntax](argumentList) @@ -1487,7 +1531,7 @@ public struct SwiftifyImportMacro: PeerMacro { var lifetimeDependencies: [SwiftifyExpr: [LifetimeDependence]] = [:] var parsedArgs = try arguments.compactMap { try parseMacroParam( - $0, funcDecl.signature, nonescapingPointers: &nonescapingPointers, + $0, funcDecl.signature, rewriter, nonescapingPointers: &nonescapingPointers, lifetimeDependencies: &lifetimeDependencies) } parsedArgs.append(contentsOf: try parseCxxSpansInSignature(funcDecl.signature, typeMappings)) @@ -1627,3 +1671,33 @@ extension TypeSyntaxProtocol { return false } } + +extension FunctionParameterSyntax { + var name: TokenSyntax { + self.secondName ?? self.firstName + } +} + +extension TokenSyntax { + public var withoutBackticks: TokenSyntax { + return .identifier(self.identifier!.name) + } + + public var escapeIfNeeded: TokenSyntax { + var parser = Parser("let \(self)") + let decl = DeclSyntax.parse(from: &parser) + if !decl.hasError { + return self + } else { + return self.copyTrivia(to: "`\(raw: self.trimmed.text)`") + } + } + + public func copyTrivia(to other: TokenSyntax) -> TokenSyntax { + return .identifier(other.text, leadingTrivia: self.leadingTrivia, trailingTrivia: self.trailingTrivia) + } +} + +func escapeIfNeeded(_ identifier: DeclReferenceExprSyntax) -> ExprSyntax { + return "\(identifier.baseName.escapeIfNeeded)" +} 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 d7d849d3cdd5c..73a48ec5b220f 100644 --- a/test/Interop/C/swiftify-import/Inputs/counted-by-noescape.h +++ b/test/Interop/C/swiftify-import/Inputs/counted-by-noescape.h @@ -24,3 +24,58 @@ int * __counted_by(len) __noescape returnPointer(int len); int * __counted_by(len1) returnLifetimeBound(int len1, int len2, int * __counted_by(len2) p __lifetimebound); void anonymous(int len, int * __counted_by(len) _Nullable __noescape); + +void keyword(int len, int * __counted_by(len) _Nullable func __noescape, + int extension, + int init, + int open, + int var, + int is, + int as, + int in, + int guard, + int where +); + +void pointerName(int len, int * __counted_by(len) _Nullable pointerName __noescape); + +void lenName(int lenName, int size, int * __counted_by(lenName * size) _Nullable p __noescape); + +void func(int len, int * __counted_by(len) _Nullable func __noescape); + +void *funcRenameKeyword(int len, int * __counted_by(len) _Nullable func __noescape, + int extension __lifetimebound, + int init, + int open, + int var, + int is, + int as, + int in, + int guard, + int where) __attribute__((swift_name("funcRenamed(len:func:extension:init:open:var:is:as:in:guard:where:)"))); + +void *funcRenameKeywordAnonymous(int len, int * __counted_by(len) _Nullable __noescape, + int __lifetimebound, + int, + int, + int, + int, + int, + int, + int, + int) __attribute__((swift_name("funcRenamedAnon(len:func:extension:init:open:var:is:as:in:guard:where:)"))); + +void funcRenameClash(int len, int * __counted_by(len) _Nullable func __noescape, int where) + __attribute__((swift_name("clash(len:func:clash:)"))); + +void funcRenameClashKeyword(int len, int * __counted_by(len) _Nullable func __noescape, int where) + __attribute__((swift_name("open(len:func:open:)"))); + +void funcRenameClashAnonymous(int len, int * __counted_by(len) _Nullable func __noescape, int) + __attribute__((swift_name("clash2(len:func:clash2:)"))); + +void funcRenameClashKeywordAnonymous(int len, int * __counted_by(len) _Nullable func __noescape, int) + __attribute__((swift_name("in(len:func:in:)"))); + +typedef struct actor_ *actor; +actor _Nonnull keywordType(int len, actor * __counted_by(len) __noescape p, actor _Nonnull p2); diff --git a/test/Interop/C/swiftify-import/counted-by-noescape.swift b/test/Interop/C/swiftify-import/counted-by-noescape.swift index d230834b58679..46d1102c3670c 100644 --- a/test/Interop/C/swiftify-import/counted-by-noescape.swift +++ b/test/Interop/C/swiftify-import/counted-by-noescape.swift @@ -13,14 +13,61 @@ import CountedByNoEscapeClang // CHECK: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) -// CHECK-NEXT: @lifetime(_param1: copy _param1) -// CHECK-NEXT: @_alwaysEmitIntoClient public func anonymous(_ _param1: inout MutableSpan?) +// CHECK-NEXT: @lifetime(_anonymous_param1: copy _anonymous_param1) +// CHECK-NEXT: @_alwaysEmitIntoClient public func anonymous(_ _anonymous_param1: inout MutableSpan?) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK-NEXT: @lifetime(func: copy func) +// CHECK-NEXT: @_alwaysEmitIntoClient public func clash(func: inout MutableSpan?, clash where: Int32) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK-NEXT: @lifetime(_clash2_param1: copy _clash2_param1) +// CHECK-NEXT: @_alwaysEmitIntoClient public func clash2(func _clash2_param1: inout MutableSpan?, clash2 _clash2_param2: Int32) // CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func complexExpr(_ len: Int32, _ offset: Int32, _ p: inout MutableSpan) +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK-NEXT: @lifetime(_func_param1: copy _func_param1) +// CHECK-NEXT: @_alwaysEmitIntoClient public func `func`(_ _func_param1: inout MutableSpan?) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK-NEXT: @lifetime(borrow extension) +// CHECK-NEXT: @lifetime(func: copy func) +// CHECK-NEXT: @_alwaysEmitIntoClient public func funcRenamed(func: inout MutableSpan?, extension: Int32, init: Int32, open: Int32, var: Int32, is: Int32, as: Int32, in: Int32, guard: Int32, where: Int32) -> UnsafeMutableRawPointer! + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK-NEXT: @lifetime(borrow _funcRenamedAnon_param2) +// CHECK-NEXT: @lifetime(_funcRenamedAnon_param1: copy _funcRenamedAnon_param1) +// CHECK-NEXT: @_alwaysEmitIntoClient public func funcRenamedAnon(func _funcRenamedAnon_param1: inout MutableSpan?, extension _funcRenamedAnon_param2: Int32, init _funcRenamedAnon_param3: Int32, open _funcRenamedAnon_param4: Int32, var _funcRenamedAnon_param5: Int32, is _funcRenamedAnon_param6: Int32, as _funcRenamedAnon_param7: Int32, in _funcRenamedAnon_param8: Int32, guard _funcRenamedAnon_param9: Int32, where _funcRenamedAnon_param10: Int32) -> UnsafeMutableRawPointer! + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK-NEXT: @lifetime(_in_param1: copy _in_param1) +// CHECK-NEXT: @_alwaysEmitIntoClient public func `in`(func _in_param1: inout MutableSpan?, in _in_param2: Int32) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK-NEXT: @lifetime(func: copy func) +// CHECK-NEXT: @_alwaysEmitIntoClient public func keyword(_ func: inout MutableSpan?, _ extension: Int32, _ init: Int32, _ open: Int32, _ var: Int32, _ is: Int32, _ as: Int32, _ in: Int32, _ guard: Int32, _ where: Int32) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK-NEXT: @lifetime(p: copy p) +// CHECK-NEXT: @_alwaysEmitIntoClient public func keywordType(_ p: inout MutableSpan, _ p2: actor) -> actor + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK-NEXT: @lifetime(_lenName_param2: copy _lenName_param2) +// CHECK-NEXT: @_alwaysEmitIntoClient public func lenName(_ _lenName_param0: Int32, _ _lenName_param1: Int32, _ _lenName_param2: inout MutableSpan?) + // CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(p: copy p) @@ -36,6 +83,16 @@ import CountedByNoEscapeClang // CHECK-NEXT: @lifetime(p: copy p) // CHECK-NEXT: @_alwaysEmitIntoClient public func nullable(_ p: inout MutableSpan?) +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK-NEXT: @lifetime(func: copy func) +// CHECK-NEXT: @_alwaysEmitIntoClient public func open(func: inout MutableSpan?, open where: Int32) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK-NEXT: @lifetime(_pointerName_param1: copy _pointerName_param1) +// CHECK-NEXT: @_alwaysEmitIntoClient public func pointerName(_ _pointerName_param1: inout MutableSpan?) + // CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @lifetime(copy p) @@ -125,8 +182,65 @@ public func callSwiftAttr(_ p: inout MutableSpan) { swiftAttr(&p) } +@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) @lifetime(p: copy p) @inlinable public func callAnonymous(_ p: inout MutableSpan?) { anonymous(&p) } + +@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +@lifetime(p: copy p) +@inlinable +public func callKeyword(_ p: inout MutableSpan?) { + keyword(&p, 1, 2, 3, 4, 5, 6, 7, 8, 9) +} + +@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +@lifetime(p: copy p) +@inlinable +public func callFunc(_ p: inout MutableSpan?) { + `func`(&p) +} + +@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +@lifetime(p: copy p) +@inlinable +public func callFuncRenameKeyword(_ p: inout MutableSpan?) { + funcRenamed(func: &p, extension: 1, init: 2, open: 3, var: 4, is: 5, as: 6, in: 7, guard: 8, where: 9) +} + +@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +@lifetime(p: copy p) +@inlinable +public func callFuncRenameClash(_ p: inout MutableSpan?) { + clash(func: &p, clash: 1) +} + +@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +@lifetime(p: copy p) +@inlinable +public func callFuncRenameClashKeyword(_ p: inout MutableSpan?) { + `open`(func: &p, open: 1) +} + +@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +@lifetime(p: copy p) +@inlinable +public func callFuncRenameClashKeywordAnon(_ p: inout MutableSpan?) { + `in`(func: &p, in: 1) +} + +@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +@lifetime(p: copy p) +@inlinable +public func callPointerName(_ p: inout MutableSpan?) { + pointerName(&p) +} + +@available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +@lifetime(p: copy p) +@inlinable +public func callLenName(_ p: inout MutableSpan?) { + lenName(CInt(p?.count ?? 0), 2, &p) +} diff --git a/test/Interop/Cxx/stdlib/Inputs/std-span.h b/test/Interop/Cxx/stdlib/Inputs/std-span.h index b02c869d88cf7..d49773165ccaf 100644 --- a/test/Interop/Cxx/stdlib/Inputs/std-span.h +++ b/test/Interop/Cxx/stdlib/Inputs/std-span.h @@ -170,4 +170,7 @@ struct SpanWithoutTypeAlias { void foo(std::span s [[clang::noescape]]); }; +inline void func(ConstSpanOfInt copy [[clang::noescape]]) {} +inline void mutableKeyword(SpanOfInt copy [[clang::noescape]]) {} + #endif // TEST_INTEROP_CXX_STDLIB_INPUTS_STD_SPAN_H diff --git a/test/Interop/Cxx/stdlib/std-span-interface.swift b/test/Interop/Cxx/stdlib/std-span-interface.swift index 727fbb24646ae..4e7522d853b21 100644 --- a/test/Interop/Cxx/stdlib/std-span-interface.swift +++ b/test/Interop/Cxx/stdlib/std-span-interface.swift @@ -94,9 +94,12 @@ import CxxStdlib // CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func MixedFuncWithMutableSafeWrapper7(_ p: UnsafeMutableBufferPointer) -> SpanOfInt - // CHECK: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK-NEXT: @_alwaysEmitIntoClient public func `func`(_ copy: Span) + +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) // CHECK-NEXT: @_alwaysEmitIntoClient public func funcWithSafeWrapper(_ s: Span) // CHECK-NEXT: /// This is an auto-generated wrapper for safer interop @@ -137,6 +140,11 @@ import CxxStdlib // CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @_alwaysEmitIntoClient public func mixedFuncWithSafeWrapper7(_ p: UnsafeBufferPointer) -> ConstSpanOfInt +// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop +// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) +// CHECK-NEXT: @lifetime(copy: copy copy) +// CHECK-NEXT: @_alwaysEmitIntoClient public func mutableKeyword(_ copy: inout MutableSpan) + func callMethodWithSafeWrapper(_ x: inout X, s: Span) { x.methodWithSafeWrapper(s) } @@ -228,4 +236,9 @@ func callMixedFuncWithSafeWrapper6(_ s: ConstSpanOfInt, _ p: UnsafeMutableBuffer func callMixedFuncWithSafeWrapper7(_ p: UnsafeBufferPointer) { let _: ConstSpanOfInt = unsafe mixedFuncWithSafeWrapper7(p) -} \ No newline at end of file +} + +@lifetime(span: copy span) +func callMutableKeyword(_ span: inout MutableSpan) { + mutableKeyword(&span) +} diff --git a/test/Macros/SwiftifyImport/CountedBy/Anonymous.swift b/test/Macros/SwiftifyImport/CountedBy/Anonymous.swift index 8ee47af046761..dbdaa81e59e19 100644 --- a/test/Macros/SwiftifyImport/CountedBy/Anonymous.swift +++ b/test/Macros/SwiftifyImport/CountedBy/Anonymous.swift @@ -19,25 +19,25 @@ public func myFunc4(_: UnsafeMutablePointer, _ len: CInt) { } // CHECK: @_alwaysEmitIntoClient -// CHECK-NEXT: public func myFunc(_ _param0: UnsafeBufferPointer) { -// CHECK-NEXT: return unsafe myFunc(_param0.baseAddress!, CInt(exactly: _param0.count)!) +// CHECK-NEXT: public func myFunc(_ _myFunc_param0: UnsafeBufferPointer) { +// CHECK-NEXT: return unsafe myFunc(_myFunc_param0.baseAddress!, CInt(exactly: _myFunc_param0.count)!) // CHECK-NEXT: } // CHECK: @_alwaysEmitIntoClient -// CHECK-NEXT: public func myFunc2(_ p: UnsafeBufferPointer, _ _param2: CInt) { -// CHECK-NEXT: return unsafe myFunc2(p.baseAddress!, CInt(exactly: p.count)!, _param2) +// CHECK-NEXT: public func myFunc2(_ _myFunc2_param0: UnsafeBufferPointer, _ _myFunc2_param2: CInt) { +// CHECK-NEXT: return unsafe myFunc2(_myFunc2_param0.baseAddress!, CInt(exactly: _myFunc2_param0.count)!, _myFunc2_param2) // CHECK-NEXT: } // CHECK: @_alwaysEmitIntoClient -// CHECK-NEXT: public func myFunc3(_ _param0: Span) { -// CHECK-NEXT: return unsafe _param0.withUnsafeBufferPointer { __param0Ptr in -// CHECK-NEXT: return unsafe myFunc3(__param0Ptr.baseAddress!, CInt(exactly: __param0Ptr.count)!) -// CHECK-NEXT: } +// CHECK-NEXT: public func myFunc3(_ _myFunc3_param0: Span) { +// CHECK-NEXT: return unsafe _myFunc3_param0.withUnsafeBufferPointer { __myFunc3_param0Ptr in +// CHECK-NEXT: return unsafe myFunc3(__myFunc3_param0Ptr.baseAddress!, CInt(exactly: __myFunc3_param0Ptr.count)!) +// CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @lifetime(_param0: copy _param0) -// CHECK-NEXT: public func myFunc4(_ _param0: inout MutableSpan) { -// CHECK-NEXT: return unsafe _param0.withUnsafeMutableBufferPointer { __param0Ptr in -// CHECK-NEXT: return unsafe myFunc4(__param0Ptr.baseAddress!, CInt(exactly: __param0Ptr.count)!) -// CHECK-NEXT: } -// CHECK-NEXT: } \ No newline at end of file +// CHECK: @_alwaysEmitIntoClient @lifetime(_myFunc4_param0: copy _myFunc4_param0) +// CHECK-NEXT: public func myFunc4(_ _myFunc4_param0: inout MutableSpan) { +// CHECK-NEXT: return unsafe _myFunc4_param0.withUnsafeMutableBufferPointer { __myFunc4_param0Ptr in +// CHECK-NEXT: return unsafe myFunc4(__myFunc4_param0Ptr.baseAddress!, CInt(exactly: __myFunc4_param0Ptr.count)!) +// CHECK-NEXT: } +// CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/CountedBy/CountExpr.swift b/test/Macros/SwiftifyImport/CountedBy/CountExpr.swift index 92fe4889bdad1..2f763a2fbd31f 100644 --- a/test/Macros/SwiftifyImport/CountedBy/CountExpr.swift +++ b/test/Macros/SwiftifyImport/CountedBy/CountExpr.swift @@ -14,4 +14,3 @@ func myFunc(_ ptr: UnsafePointer, _ size: CInt, _ count: CInt) { // CHECK-NEXT: } // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, size, count) // CHECK-NEXT: } - diff --git a/test/Macros/SwiftifyImport/CountedBy/Mutable.swift b/test/Macros/SwiftifyImport/CountedBy/Mutable.swift index 1df1df1329115..0ad33e3b84c9d 100644 --- a/test/Macros/SwiftifyImport/CountedBy/Mutable.swift +++ b/test/Macros/SwiftifyImport/CountedBy/Mutable.swift @@ -10,4 +10,3 @@ func myFunc(_ ptr: UnsafeMutablePointer, _ len: CInt) { // 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 62d4612f10fbc..b648d9213cad9 100644 --- a/test/Macros/SwiftifyImport/CountedBy/MutableSpan.swift +++ b/test/Macros/SwiftifyImport/CountedBy/MutableSpan.swift @@ -9,7 +9,7 @@ func myFunc(_ ptr: UnsafeMutablePointer, _ len: CInt) { // CHECK: @_alwaysEmitIntoClient @lifetime(ptr: copy ptr) // CHECK-NEXT: func myFunc(_ ptr: inout MutableSpan) { -// CHECK-NEXT: return unsafe ptr.withUnsafeMutableBufferPointer { _ptrPtr in +// CHECK-NEXT: return unsafe ptr.withUnsafeMutableBufferPointer { _ptrPtr in // 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 6e450b8afa124..23a7ad317836c 100644 --- a/test/Macros/SwiftifyImport/CountedBy/NamedParams.swift +++ b/test/Macros/SwiftifyImport/CountedBy/NamedParams.swift @@ -55,4 +55,3 @@ func allNamedOther(buf ptr: UnsafePointer, count len: CInt) { // 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/PointerReturn.swift b/test/Macros/SwiftifyImport/CountedBy/PointerReturn.swift index 260486de4e785..01d98a30442b8 100644 --- a/test/Macros/SwiftifyImport/CountedBy/PointerReturn.swift +++ b/test/Macros/SwiftifyImport/CountedBy/PointerReturn.swift @@ -39,4 +39,3 @@ func lifetimeDependentBorrow(_ p: borrowing UnsafePointer, _ len1: CInt, _ // CHECK-NEXT: 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/QualifiedTypes.swift b/test/Macros/SwiftifyImport/CountedBy/QualifiedTypes.swift index 3a7139e92f133..0cc61c3d14eba 100644 --- a/test/Macros/SwiftifyImport/CountedBy/QualifiedTypes.swift +++ b/test/Macros/SwiftifyImport/CountedBy/QualifiedTypes.swift @@ -19,5 +19,3 @@ func bar(_ ptr: Swift.UnsafePointer, _ len: Swift.Int) -> () { // 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/SpanAndUnsafeBuffer.swift b/test/Macros/SwiftifyImport/CountedBy/SpanAndUnsafeBuffer.swift index 09fa7f41de45c..1e2168fac5446 100644 --- a/test/Macros/SwiftifyImport/CountedBy/SpanAndUnsafeBuffer.swift +++ b/test/Macros/SwiftifyImport/CountedBy/SpanAndUnsafeBuffer.swift @@ -14,4 +14,3 @@ func myFunc(_ ptr1: UnsafePointer, _ len1: CInt, _ ptr2: UnsafePointer!, _ len: CInt) { // 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 5c680129eb306..ecdba57608567 100644 --- a/test/Macros/SwiftifyImport/CxxSpan/LifetimeboundSpan.swift +++ b/test/Macros/SwiftifyImport/CxxSpan/LifetimeboundSpan.swift @@ -57,6 +57,10 @@ func myFunc8(_ ptr: UnsafeRawPointer, _ span: SpanOfInt, _ count: CInt, _ size: func myFunc9(_ span: MutableSpanOfInt) -> MutableSpanOfInt { } +@_SwiftifyImport(.lifetimeDependence(dependsOn: .param(1), pointer: .return, type: .copy), typeMappings: ["MutableSpanOfInt" : "std.span"]) +func myFunc10(_ self: MutableSpanOfInt) -> MutableSpanOfInt { +} + // CHECK: @_alwaysEmitIntoClient @lifetime(copy span) // CHECK-NEXT: func myFunc(_ span: Span) -> Span { // CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(Span(_unsafeCxxSpan: unsafe myFunc(SpanOfInt(span))), copying: ()) @@ -121,3 +125,10 @@ func myFunc9(_ span: MutableSpanOfInt) -> MutableSpanOfInt { // CHECK-NEXT: return unsafe myFunc9(MutableSpanOfInt(_spanPtr)) // CHECK-NEXT: }), copying: ()) // CHECK-NEXT: } + +// CHECK: @_alwaysEmitIntoClient @lifetime(copy `self`) @lifetime(`self`: copy `self`) +// CHECK-NEXT: func myFunc10(_ `self`: inout MutableSpan) -> MutableSpan { +// CHECK-NEXT: return unsafe _swiftifyOverrideLifetime(MutableSpan(_unsafeCxxSpan: unsafe `self`.withUnsafeMutableBufferPointer { _selfPtr in +// CHECK-NEXT: return unsafe myFunc10(MutableSpanOfInt(_selfPtr)) +// CHECK-NEXT: }), copying: ()) +// CHECK-NEXT: } diff --git a/test/Macros/SwiftifyImport/SizedBy/Opaque.swift b/test/Macros/SwiftifyImport/SizedBy/Opaque.swift index f4067cc321b83..957c147de4a2f 100644 --- a/test/Macros/SwiftifyImport/SizedBy/Opaque.swift +++ b/test/Macros/SwiftifyImport/SizedBy/Opaque.swift @@ -67,4 +67,3 @@ func impNullableSpan(_ ptr: OpaquePointer!, _ size: CInt) { // CHECK-NEXT: return unsafe impNullableSpan(OpaquePointer(_ptrPtr.baseAddress!), CInt(exactly: _ptrPtr.count)!) // CHECK-NEXT: } // CHECK-NEXT: } - diff --git a/test/Macros/SwiftifyImport/SizedBy/Unwrapped.swift b/test/Macros/SwiftifyImport/SizedBy/Unwrapped.swift index c18be3ae42f62..852d4a4ba116f 100644 --- a/test/Macros/SwiftifyImport/SizedBy/Unwrapped.swift +++ b/test/Macros/SwiftifyImport/SizedBy/Unwrapped.swift @@ -10,4 +10,3 @@ func myFunc(_ ptr: UnsafeRawPointer!, _ len: CInt) { // CHECK-NEXT: func myFunc(_ ptr: UnsafeRawBufferPointer) { // CHECK-NEXT: return unsafe myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!) // CHECK-NEXT: } -