Skip to content

Commit 55744d9

Browse files
committed
Add @PointerBounds macro
@PointerBounds is a macro intended to be applied by ClangImporter when importing functions with pointer parameters from C headers. By leveraging C attributes we can get insight into bounds, esapability, and (eventually) lifetimes of pointers, allowing us to map them to safe(r) and more ergonomic types than UnsafePointer. This initial macro implementation supports CountedBy and Sizedby, but not yet EndedBy. It can generate function overloads with and without an explicit count parameter, as well as with UnsafeBufferPointer or Span (if marked nonescaping), and any of their combinations. It supports nullable/optional pointers, and both mutable and immutable pointers. It supports arbitrary count expressions. These are passed to the macro as a string literal since any parameters referred to in the count expression will not have been declared yet when parsing the macro. It does not support indirect pointers or inout parameters. It supports functions with return values, but returned pointers can not be bounds checked yet. Bounds checked pointers must be of type Unsafe[Mutable]Pointer[?]<T>. Count expressions must conform to the BinaryInteger protocol, and have an initializer with signature "init(exactly: Int) -> T?" (or accept a supertype of Int). rdar://137628612
1 parent 4e3f665 commit 55744d9

36 files changed

+1142
-0
lines changed

lib/Macros/Sources/SwiftMacros/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ add_swift_macro_library(SwiftMacros
1616
DistributedResolvableMacro.swift
1717
SyntaxExtensions.swift
1818
TaskLocalMacro.swift
19+
PointerBoundsMacro.swift
1920
SWIFT_DEPENDENCIES
2021
SwiftDiagnostics
2122
SwiftSyntax

stdlib/public/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ if(SWIFT_BUILD_STDLIB)
265265
add_subdirectory(stubs)
266266
add_subdirectory(core)
267267
add_subdirectory(SwiftOnoneSupport)
268+
add_subdirectory(PointerBounds)
268269

269270
if(SWIFT_BUILD_CLANG_OVERLAYS OR SWIFT_BUILD_TEST_SUPPORT_MODULES)
270271
add_subdirectory(ClangOverlays)
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
add_swift_target_library(swift_PointerBounds ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB
2+
PointerBounds.swift
3+
SWIFT_COMPILE_FLAGS
4+
${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS}
5+
-parse-stdlib
6+
7+
LINK_FLAGS
8+
"${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
9+
10+
INSTALL_IN_COMPONENT stdlib
11+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public enum PointerParam {
2+
case countedBy(pointer: Int, count: String)
3+
case sizedBy(pointer: Int, size: String)
4+
case endedBy(start: Int, end: Int)
5+
case nonescaping(pointer: Int)
6+
}
7+
8+
@attached(peer, names: overloaded)
9+
public macro PointerBounds(_ paramInfo: PointerParam...) =
10+
#externalMacro(module: "SwiftMacros", type: "PointerBoundsMacro")
11+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -dump-macro-expansions > %t/expansions-dump.txt | %FileCheck %s
4+
5+
@PointerBounds(.countedBy(pointer: 1, count: "size * count"))
6+
func myFunc(_ ptr: UnsafePointer<CInt>, _ size: CInt, _ count: CInt) {
7+
}
8+
9+
// CHECK-NOT: @PointerBounds
10+
// CHECK: func myFunc(_ ptr: UnsafePointer<CInt>, _ size: CInt, _ count: CInt) {
11+
// CHECK-NEXT: }
12+
// CHECK-NEXT:
13+
// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer<CInt>, _ size: CInt, _ count: CInt) {
14+
// CHECK-NEXT: let _ptrCount: some BinaryInteger = size * count
15+
// CHECK-NEXT: if ptr.count < _ptrCount || _ptrCount < 0 {
16+
// CHECK-NEXT: fatalError("bounds check failure when calling unsafe function")
17+
// CHECK-NEXT: }
18+
// CHECK-NEXT: myFunc(ptr.baseAddress!, size, count)
19+
// CHECK-NEXT: }
20+
// CHECK-NOT: func
21+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -dump-macro-expansions > %t/expansions-dump.txt | %FileCheck %s
4+
5+
@PointerBounds(.countedBy(pointer: 1, count: "len"), .countedBy(pointer: 3, count: "len2"))
6+
func myFunc(_ ptr: UnsafePointer<CInt>, _ len: CInt, _ ptr2: UnsafePointer<CInt>, _ len2: CInt) {
7+
}
8+
9+
// CHECK-NOT: @PointerBounds
10+
// CHECK: func myFunc(_ ptr: UnsafePointer<CInt>, _ len: CInt, _ ptr2: UnsafePointer<CInt>, _ len2: CInt) {
11+
// CHECK-NEXT: }
12+
// CHECK-NEXT:
13+
// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer<CInt>, _ ptr2: UnsafeBufferPointer<CInt>) {
14+
// CHECK-NEXT: myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!, ptr2.baseAddress!, CInt(exactly: ptr2.count)!)
15+
// CHECK-NEXT: }
16+
// CHECK-NOT: func
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -dump-macro-expansions > %t/expansions-dump.txt | %FileCheck %s
4+
5+
@PointerBounds(.countedBy(count: "len", pointer: 1))
6+
func myFunc(_ ptr: UnsafeMutablePointer<CInt>, _ len: CInt) {
7+
}
8+
9+
// CHECK-NOT: @PointerBounds
10+
// CHECK: func myFunc(_ ptr: UnsafeMutablePointer<CInt>, _ len: CInt) {
11+
// CHECK-NEXT: }
12+
// CHECK-NEXT:
13+
// CHECK-NEXT: func myFunc(_ ptr: UnsafeMutableBufferPointer<CInt>) {
14+
// CHECK-NEXT: myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!)
15+
// CHECK-NEXT: }
16+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -dump-macro-expansions > %t/expansions-dump.txt | %FileCheck %s
4+
5+
@PointerBounds(.countedBy(pointer: 1, count: "len"), .nonescaping(pointer: 1))
6+
func myFunc(_ ptr: UnsafeMutablePointer<CInt>, _ len: CInt) {
7+
}
8+
9+
// CHECK-NOT: @PointerBounds
10+
// CHECK-NEXT: func myFunc(_ ptr: UnsafeMutablePointer<CInt>, _ len: CInt) {
11+
// CHECK-NEXT: }
12+
// CHECK-NEXT:
13+
// CHECK-NEXT: func myFunc(_ ptr: MutableSpan<CInt>) {
14+
// CHECK-NEXT: ptr.withUnsafeBufferPointer { _ptrPtr in
15+
// CHECK-NEXT: myFunc(_ptrPtr.baseAddress!, CInt(exactly: ptr.count)!)
16+
// CHECK-NEXT: }
17+
// CHECK-NEXT: }
18+
// CHECK-NOT: func
19+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -dump-macro-expansions > %t/expansions-dump.txt | %FileCheck %s
4+
5+
@PointerBounds(.countedBy(count: "len", pointer: 1))
6+
func myFunc(_ ptr: UnsafePointer<CInt>?, _ len: CInt) {
7+
}
8+
9+
// CHECK-NOT: @PointerBounds
10+
// CHECK: func myFunc(_ ptr: UnsafePointer<CInt>, _ len: CInt) {
11+
// CHECK-NEXT: }
12+
// CHECK-NEXT:
13+
// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer<CInt>?) {
14+
// CHECK-NEXT: myFunc(ptr?.baseAddress, CInt(exactly: ptr?.count ?? 0)!)
15+
// CHECK-NEXT: }
16+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -dump-macro-expansions > %t/expansions-dump.txt | %FileCheck %s
4+
5+
@PointerBounds(.countedBy(count: "len", pointer: 1))
6+
func myFunc(_ ptr: UnsafePointer<CInt>, _ len: CInt) -> CInt {
7+
}
8+
9+
// CHECK-NOT: @PointerBounds
10+
// CHECK: func myFunc(_ ptr: UnsafePointer<CInt>, _ len: CInt) -> CInt {
11+
// CHECK-NEXT: }
12+
// CHECK-NEXT:
13+
// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer<CInt>) -> CInt {
14+
// CHECK-NEXT: return myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!)
15+
// CHECK-NEXT: }
16+
// CHECK-NOT: func
17+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -dump-macro-expansions > %t/expansions-dump.txt | %FileCheck %s
4+
5+
@PointerBounds(.countedBy(pointer: 1, count: "len"), .countedBy(pointer: 2, count: "len"))
6+
func myFunc(_ ptr: UnsafePointer<CInt>, _ ptr2: UnsafePointer<CInt>, _ len: CInt) {
7+
}
8+
9+
// CHECK-NOT: @PointerBounds
10+
// CHECK: func myFunc(_ ptr: UnsafePointer<CInt>, _ ptr2: UnsafePointer<CInt>, _ len: CInt) {
11+
// CHECK-NEXT: }
12+
// CHECK-NEXT:
13+
// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer<CInt>, _ ptr2: UnsafeBufferPointer<CInt>, _ len: CInt) {
14+
// CHECK-NEXT: let _ptrCount: some BinaryInteger = len
15+
// CHECK-NEXT: if ptr.count < _ptrCount || _ptrCount < 0 {
16+
// CHECK-NEXT: fatalError("bounds check failure when calling unsafe function")
17+
// CHECK-NEXT: }
18+
// CHECK-NEXT: let _ptr2Count: some BinaryInteger = len
19+
// CHECK-NEXT: if ptr2.count < _ptr2Count || _ptr2Count < 0 {
20+
// CHECK-NEXT: fatalError("bounds check failure when calling unsafe function")
21+
// CHECK-NEXT: }
22+
// CHECK-NEXT: myFunc(ptr.baseAddress!, ptr2.baseAddress!, len)
23+
// CHECK-NEXT: }
24+
// CHECK-NOT: func
25+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -dump-macro-expansions > %t/expansions-dump.txt | %FileCheck %s
4+
5+
@PointerBounds(.countedBy(count: "len", pointer: 1))
6+
func myFunc(_ ptr: UnsafePointer<CInt>, _ len: CInt) {
7+
}
8+
9+
// CHECK-NOT: @PointerBounds
10+
// CHECK: func myFunc(_ ptr: UnsafePointer<CInt>, _ len: CInt) {
11+
// CHECK-NEXT: }
12+
// CHECK-NEXT:
13+
// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer<CInt>) {
14+
// CHECK-NEXT: myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!)
15+
// CHECK-NEXT: }
16+
// CHECK-NOT: func
17+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -dump-macro-expansions > %t/expansions-dump.txt | %FileCheck %s
4+
5+
@PointerBounds(.countedBy(pointer: 1, count: "len"), .nonescaping(pointer: 1))
6+
func myFunc(_ ptr: UnsafePointer<CInt>, _ len: CInt) {
7+
}
8+
9+
// CHECK-NOT: @PointerBounds
10+
// CHECK: func myFunc(_ ptr: UnsafePointer<CInt>, _ len: CInt) {
11+
// CHECK-NEXT: }
12+
// CHECK-NEXT:
13+
// CHECK-NEXT: func myFunc(_ ptr: Span<CInt>) {
14+
// CHECK-NEXT: ptr.withUnsafeBufferPointer { _ptrPtr in
15+
// CHECK-NEXT: myFunc(_ptrPtr.baseAddress!, CInt(exactly: ptr.count)!)
16+
// CHECK-NEXT: }
17+
// CHECK-NEXT: }
18+
// CHECK-NOT: func
19+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -dump-macro-expansions > %t/expansions-dump.txt | %FileCheck %s
4+
5+
@PointerBounds(.countedBy(pointer: 1, count: "len"), .nonescaping(pointer: 1))
6+
func myFunc(_ ptr: UnsafePointer<CInt>, _ len: CInt) -> CInt {
7+
}
8+
9+
// CHECK-NOT: @PointerBounds
10+
// CHECK: func myFunc(_ ptr: UnsafePointer<CInt>, _ len: CInt) -> CInt {
11+
// CHECK-NEXT: }
12+
// CHECK-NEXT:
13+
// CHECK-NEXT: func myFunc(_ ptr: Span<CInt>) -> CInt {
14+
// CHECK-NEXT: return ptr.withUnsafeBufferPointer { _ptrPtr in
15+
// CHECK-NEXT: return myFunc(_ptrPtr.baseAddress!, CInt(exactly: ptr.count)!)
16+
// CHECK-NEXT: }
17+
// CHECK-NEXT: }
18+
// CHECK-NOT: func
19+
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-typecheck-verify-swift %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -verify
4+
5+
@PointerBounds(.countedBy(pointer: 1, count: "len"))
6+
// expected-error@+1{{expected pointer type, got [CInt] with kind arrayType}}
7+
func myFunc(_ ptr: [CInt], _ len: String) {
8+
}
9+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-typecheck-verify-swift %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -verify
4+
5+
let countString = "len"
6+
// expected-error@+1{{expected string literal for 'count' parameter, got countString}}
7+
@PointerBounds(.countedBy(pointer: 1, count: countString))
8+
func myFunc(_ ptr: UnsafePointer<CInt>, _ len: String) {
9+
}
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-typecheck-verify-swift %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -verify
4+
5+
let countedBy = PointerBounds.countedBy(pointer: 1, count: "len")
6+
// expected-error@+1{{expected PointerParam enum literal as argument, got 'countedBy'}}
7+
@PointerBounds(countedBy)
8+
func myFunc(_ ptr: UnsafePointer<CInt>, _ len: String) {
9+
}
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-typecheck-verify-swift %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -verify
4+
5+
let pointerIndex = 1
6+
// expected-error@+1{{expected integer literal, got 'pointerIndex'}}
7+
@PointerBounds(.countedBy(pointer: pointerIndex, count: "len"))
8+
func myFunc(_ ptr: UnsafePointer<CInt>, _ len: String) {
9+
}
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-typecheck-verify-swift %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -verify
4+
5+
// expected-error@+1{{no parameter with name 'foo' in '_ ptr: UnsafePointer<CInt>, _ len: CInt'}}
6+
@PointerBounds(.countedBy(pointer: 1, count: "foo"))
7+
func myFunc(_ ptr: UnsafePointer<CInt>, _ len: CInt) {
8+
}
9+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-typecheck-verify-swift %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -verify
4+
5+
// expected-error@+1{{pointer index out of bounds}}
6+
@PointerBounds(.countedBy(pointer: 3, count: "len"))
7+
// expected-note@+1{{function myFunc has parameter indices 1..2}}
8+
func myFunc(_ ptr: UnsafePointer<CInt>, _ len: CInt) {
9+
}
10+
// expected-error@+1{{pointer index out of bounds}}
11+
@PointerBounds(.countedBy(pointer: 0, count: "len"))
12+
// expected-note@+1{{function myFunc2 has parameter indices 1..2}}
13+
func myFunc2(_ ptr: UnsafePointer<CInt>, _ len: CInt) {
14+
}
15+
// expected-error@+1{{pointer index out of bounds}}
16+
@PointerBounds(.countedBy(pointer: 0, count: "1"))
17+
// expected-note@+1{{function myFunc3 has no parameters}}
18+
func myFunc3() {
19+
}
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-typecheck-verify-swift %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -verify
4+
5+
// expected-error@+3{{multiple PointerParams referring to parameter with index 1:\
6+
// .countedBy(pointer: 1, count: "dummy", nonescaping: false) and\
7+
// .countedBy(pointer: 1, count: "len", nonescaping: false)}}
8+
@PointerBounds(.countedBy(pointer: 1, count: "len"), .countedBy(pointer: 1, count: "dummy"))
9+
func myFunc(_ ptr: UnsafePointer<CInt>, _ len: CInt, _ dummy: CInt) {
10+
}
11+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-typecheck-verify-swift %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -verify
4+
5+
// expected-error@+1{{expected string literal for 'count' parameter, got 2}}
6+
@PointerBounds(.countedBy(pointer: 1, count: 2))
7+
func myFunc(_ ptr: UnsafePointer<CInt>, _ len: String) {
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -dump-macro-expansions > %t/expansions-dump.txt | %FileCheck %s
4+
// RUN: %target-typecheck-verify-swift %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -verify
5+
6+
@PointerBounds(.countedBy(pointer: 1, count: "len"))
7+
func myFunc(_ ptr: UnsafePointer<CInt>, _ len: String) {
8+
}
9+
10+
// CHECK: func myFunc(_ ptr: UnsafePointer<CInt>, _ len: String) {
11+
// CHECK-NEXT: }
12+
// CHECK-NEXT:
13+
// CHECK-NEXT: func myFunc(_ ptr: UnsafeBufferPointer<CInt>) {
14+
// CHECK-NEXT: myFunc(ptr.baseAddress!, String(exactly: ptr.count)!)
15+
// CHECK-NEXT: }
16+
17+
// expected-error{{TODO: check error message}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-typecheck-verify-swift %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -verify
4+
5+
// expected-error@+1{{expected Unsafe[Mutable]Pointer type for type CInt - first type token is 'CInt'}}
6+
@PointerBounds(.countedBy(pointer: 1, count: "len"))
7+
func myFunc(_ ptr: CInt, _ len: CInt) {
8+
}
9+
// expected-error@+1{{expected Unsafe[Mutable]Pointer type for type UnsafeBufferPointer<CInt> - first type token is 'UnsafeBufferPointer'}}
10+
@PointerBounds(.countedBy(pointer: 1, count: "len"))
11+
func myFunc2(_ ptr: UnsafeBufferPointer<CInt>, _ len: CInt) {
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -dump-macro-expansions > %t/expansions-dump.txt | %FileCheck %s
4+
5+
@PointerBounds(.sizedBy(pointer: 1, size: "size"), .sizedBy(pointer: 3, size: "size2"))
6+
func myFunc(_ ptr: UnsafePointer<CInt>, _ size: CInt, _ ptr2: UnsafePointer<CInt>, _ size2: CInt) {
7+
}
8+
9+
// CHECK-NOT: @PointerBounds
10+
// CHECK: func myFunc(_ ptr: UnsafePointer<CInt>, _ size: CInt, _ ptr2: UnsafePointer<CInt>, _ size2: CInt) {
11+
// CHECK-NEXT: }
12+
// CHECK-NEXT:
13+
// CHECK-NEXT: func myFunc(_ ptr: UnsafeRawBufferPointer, _ ptr2: UnsafeRawBufferPointer) {
14+
// CHECK-NEXT: myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!, ptr2.baseAddress!, CInt(exactly: ptr2.count)!)
15+
// CHECK-NEXT: }
16+
// CHECK-NOT: func
17+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-swift-frontend %s -swift-version 5 -module-name main -disable-availability-checking -typecheck -enable-experimental-feature SymbolLinkageMarkers -plugin-path %swift-plugin-dir -dump-macro-expansions > %t/expansions-dump.txt | %FileCheck %s
4+
5+
@PointerBounds(.sizedBy(size: "size", pointer: 1))
6+
func myFunc(_ ptr: UnsafeMutablePointer<CInt>, _ size: CInt) {
7+
}
8+
9+
// CHECK-NOT: @PointerBounds
10+
// CHECK: func myFunc(_ ptr: UnsafeMutablePointer<CInt>, _ size: CInt) {
11+
// CHECK-NEXT: }
12+
// CHECK-NEXT:
13+
// CHECK-NEXT: func myFunc(_ ptr: UnsafeMutableRawBufferPointer) {
14+
// CHECK-NEXT: myFunc(ptr.baseAddress!, CInt(exactly: ptr.count)!)
15+
// CHECK-NEXT: }
16+
// CHECK-NOT: func
17+

0 commit comments

Comments
 (0)