Skip to content

Commit a62b005

Browse files
committed
[Swiftify] Cast OpaquePointer to UnsafeRawPointer before RawSpan
The initializers for RawSpan and UnsafeRawBufferPointer take an UnsafeRawPointer, so when the underlying function returns an OpaquePointer we need to cast it first. rdar://162091516
1 parent d653b0c commit a62b005

File tree

2 files changed

+126
-12
lines changed

2 files changed

+126
-12
lines changed

lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,16 @@ func transformType(
349349
return mainType
350350
}
351351

352+
func peelOptionalType(_ type: TypeSyntax) -> TypeSyntax {
353+
if let optType = type.as(OptionalTypeSyntax.self) {
354+
return optType.wrappedType
355+
}
356+
if let impOptType = type.as(ImplicitlyUnwrappedOptionalTypeSyntax.self) {
357+
return impOptType.wrappedType
358+
}
359+
return type
360+
}
361+
352362
func isMutablePointerType(_ type: TypeSyntax) -> Bool {
353363
if let optType = type.as(OptionalTypeSyntax.self) {
354364
return isMutablePointerType(optType.wrappedType)
@@ -757,21 +767,30 @@ struct CountedOrSizedReturnPointerThunkBuilder: PointerBoundsThunkBuilder {
757767
if unsafe _resultValue == nil {
758768
return nil
759769
} else {
760-
return unsafe _swiftifyOverrideLifetime(\(raw: cast)(\(raw: startLabel): _resultValue!, \(raw: countLabel): Int(\(countExpr))), copying: ())
770+
return unsafe _swiftifyOverrideLifetime(\(raw: cast)(\(raw: startLabel): \(raw: castOpaquePointerToRawPointer("_resultValue!")), \(raw: countLabel): Int(\(countExpr))), copying: ())
761771
}
762772
}()
763773
"""
764774
} else {
765775
expr =
766776
"""
767-
\(raw: cast)(\(raw: startLabel): \(call), \(raw: countLabel): Int(\(countExpr)))
777+
\(raw: cast)(\(raw: startLabel): \(castOpaquePointerToRawPointer(call)), \(raw: countLabel): Int(\(countExpr)))
768778
"""
769779
}
770780
if generateSpan {
771781
expr = "_swiftifyOverrideLifetime(\(expr), copying: ())"
772782
}
773783
return "unsafe \(expr)"
774784
}
785+
786+
func castOpaquePointerToRawPointer(_ expr: ExprSyntax) -> ExprSyntax {
787+
let type = peelOptionalType(oldType)
788+
if type.canRepresentBasicType(type: OpaquePointer.self) {
789+
return ExprSyntax("unsafe UnsafeRawPointer(\(expr))")
790+
}
791+
return expr
792+
}
793+
775794
}
776795

777796
struct CountedOrSizedPointerThunkBuilder: ParamBoundsThunkBuilder, PointerBoundsThunkBuilder {
@@ -896,16 +915,6 @@ struct CountedOrSizedPointerThunkBuilder: ParamBoundsThunkBuilder, PointerBounds
896915
return "_\(raw: name)Count"
897916
}
898917

899-
func peelOptionalType(_ type: TypeSyntax) -> TypeSyntax {
900-
if let optType = type.as(OptionalTypeSyntax.self) {
901-
return optType.wrappedType
902-
}
903-
if let impOptType = type.as(ImplicitlyUnwrappedOptionalTypeSyntax.self) {
904-
return impOptType.wrappedType
905-
}
906-
return type
907-
}
908-
909918
func castPointerToTargetType(_ baseAddress: ExprSyntax) throws -> ExprSyntax {
910919
let type = peelOptionalType(getParam(signature, index).type)
911920
if type.canRepresentBasicType(type: OpaquePointer.self) {
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: split-file %s %t
5+
// RUN: %target-swift-frontend %t/test.swift -typecheck -plugin-path %swift-plugin-dir -strict-memory-safety -verify
6+
// RUN: %target-swift-frontend %t/test.swift -typecheck -plugin-path %swift-plugin-dir -strict-memory-safety -dump-macro-expansions 2> %t/expansions.txt
7+
// RUN: diff %t/expansions.txt %t/expansions.txt.expected
8+
9+
//--- test.swift
10+
@_SwiftifyImport(.sizedBy(pointer: .return, size: "size"))
11+
public func nonnullUnsafeRawBufferPointer(_ size: CInt) -> OpaquePointer {}
12+
13+
@_SwiftifyImport(.sizedBy(pointer: .return, size: "size"))
14+
public func nullableUnsafeRawBufferPointer(_ size: CInt) -> OpaquePointer? {}
15+
16+
@_SwiftifyImport(.sizedBy(pointer: .return, size: "size"))
17+
public func impNullableUnsafeRawBufferPointer(_ size: CInt) -> OpaquePointer! {}
18+
19+
@_SwiftifyImport(.sizedBy(pointer: .return, size: "size"), .sizedBy(pointer: .param(1), size: "size"), .lifetimeDependence(dependsOn: .param(1), pointer: .return, type: .copy))
20+
public func nonnullSpan(p: OpaquePointer, size: CInt) -> OpaquePointer {}
21+
22+
@_SwiftifyImport(.sizedBy(pointer: .return, size: "size"), .sizedBy(pointer: .param(1), size: "size"), .lifetimeDependence(dependsOn: .param(1), pointer: .return, type: .copy))
23+
public func nullableSpan(p: OpaquePointer?, _ size: CInt) -> OpaquePointer? {}
24+
25+
@_SwiftifyImport(.sizedBy(pointer: .return, size: "size"), .sizedBy(pointer: .param(1), size: "size"), .lifetimeDependence(dependsOn: .param(1), pointer: .return, type: .copy))
26+
public func impNullableSpan(p: OpaquePointer!, _ size: CInt) -> OpaquePointer! {}
27+
28+
//--- expansions.txt.expected
29+
@__swiftmacro_4test29nonnullUnsafeRawBufferPointer15_SwiftifyImportfMp_.swift
30+
------------------------------
31+
/// This is an auto-generated wrapper for safer interop
32+
@_alwaysEmitIntoClient @_disfavoredOverload
33+
public func nonnullUnsafeRawBufferPointer(_ size: CInt) -> UnsafeRawBufferPointer {
34+
return unsafe UnsafeRawBufferPointer(start: unsafe UnsafeRawPointer(unsafe nonnullUnsafeRawBufferPointer(size)), count: Int(size))
35+
}
36+
------------------------------
37+
@__swiftmacro_4test30nullableUnsafeRawBufferPointer15_SwiftifyImportfMp_.swift
38+
------------------------------
39+
/// This is an auto-generated wrapper for safer interop
40+
@_alwaysEmitIntoClient @_disfavoredOverload
41+
public func nullableUnsafeRawBufferPointer(_ size: CInt) -> UnsafeRawBufferPointer? {
42+
return unsafe { () in
43+
let _resultValue = unsafe nullableUnsafeRawBufferPointer(size)
44+
if unsafe _resultValue == nil {
45+
return nil
46+
} else {
47+
return unsafe _swiftifyOverrideLifetime(UnsafeRawBufferPointer(start: unsafe UnsafeRawPointer(_resultValue!), count: Int(size)), copying: ())
48+
}
49+
}()
50+
}
51+
------------------------------
52+
@__swiftmacro_4test33impNullableUnsafeRawBufferPointer15_SwiftifyImportfMp_.swift
53+
------------------------------
54+
/// This is an auto-generated wrapper for safer interop
55+
@_alwaysEmitIntoClient @_disfavoredOverload
56+
public func impNullableUnsafeRawBufferPointer(_ size: CInt) -> UnsafeRawBufferPointer {
57+
return unsafe UnsafeRawBufferPointer(start: unsafe UnsafeRawPointer(unsafe impNullableUnsafeRawBufferPointer(size)), count: Int(size))
58+
}
59+
------------------------------
60+
@__swiftmacro_4test11nonnullSpan15_SwiftifyImportfMp_.swift
61+
------------------------------
62+
/// This is an auto-generated wrapper for safer interop
63+
@_alwaysEmitIntoClient @_lifetime(copy p) @_disfavoredOverload
64+
public func nonnullSpan(p: RawSpan) -> RawSpan {
65+
let size = CInt(exactly: p.byteCount)!
66+
return unsafe _swiftifyOverrideLifetime(RawSpan(_unsafeStart: unsafe UnsafeRawPointer(unsafe p.withUnsafeBytes { _pPtr in
67+
return unsafe nonnullSpan(p: OpaquePointer(_pPtr.baseAddress!), size: size)
68+
}), byteCount: Int(size)), copying: ())
69+
}
70+
------------------------------
71+
@__swiftmacro_4test12nullableSpan15_SwiftifyImportfMp_.swift
72+
------------------------------
73+
/// This is an auto-generated wrapper for safer interop
74+
@_alwaysEmitIntoClient @_lifetime(copy p) @_disfavoredOverload
75+
public func nullableSpan(p: RawSpan?) -> RawSpan? {
76+
let size = CInt(exactly: p?.byteCount ?? 0)!
77+
return unsafe _swiftifyOverrideLifetime({ () in
78+
let _resultValue = { () in
79+
return if p == nil {
80+
unsafe nullableSpan(p: nil, size)
81+
} else {
82+
unsafe p!.withUnsafeBytes { _pPtr in
83+
return unsafe nullableSpan(p: OpaquePointer(_pPtr.baseAddress), size)
84+
}
85+
}
86+
}()
87+
if unsafe _resultValue == nil {
88+
return nil
89+
} else {
90+
return unsafe _swiftifyOverrideLifetime(RawSpan(_unsafeStart: unsafe UnsafeRawPointer(_resultValue!), byteCount: Int(size)), copying: ())
91+
}
92+
}(), copying: ())
93+
}
94+
------------------------------
95+
@__swiftmacro_4test15impNullableSpan15_SwiftifyImportfMp_.swift
96+
------------------------------
97+
/// This is an auto-generated wrapper for safer interop
98+
@_alwaysEmitIntoClient @_lifetime(copy p) @_disfavoredOverload
99+
public func impNullableSpan(p: RawSpan) -> RawSpan {
100+
let size = CInt(exactly: p.byteCount)!
101+
return unsafe _swiftifyOverrideLifetime(RawSpan(_unsafeStart: unsafe UnsafeRawPointer(unsafe p.withUnsafeBytes { _pPtr in
102+
return unsafe impNullableSpan(p: OpaquePointer(_pPtr.baseAddress!), size)
103+
}), byteCount: Int(size)), copying: ())
104+
}
105+
------------------------------

0 commit comments

Comments
 (0)