Skip to content

Commit ec72add

Browse files
committed
Add unit tests for implicit inout to raw pointer diagnostics.
1 parent 778b773 commit ec72add

File tree

3 files changed

+167
-0
lines changed

3 files changed

+167
-0
lines changed

test/SILGen/Inputs/readbytes.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
void read_char(const char *input);
2+
void read_uchar(const unsigned char *input);
3+
void read_void(const void *input);
4+
void write_char(char *input);
5+
void write_uchar(unsigned char *input);
6+
void write_void(void *input);
7+
8+
void take_opaque_pointer(const void *);
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// RUN: %target-swift-emit-silgen -import-objc-header %S/Inputs/readbytes.h %s -o /dev/null -verify
2+
//
3+
// Diagnose invalid conversion from an inout argument to a raw pointer.
4+
5+
import Foundation
6+
7+
func readBytes(_ pointer: UnsafeRawPointer) {}
8+
func writeBytes(_ pointer: UnsafeMutableRawPointer) {}
9+
func readInt8(_ pointer: UnsafePointer<Int8>) {}
10+
func writeInt8(_ pointer: UnsafeMutablePointer<Int8>) {}
11+
func readUInt8(_ pointer: UnsafePointer<UInt8>) {}
12+
func writeUInt8(_ pointer: UnsafeMutablePointer<UInt8>) {}
13+
14+
// SILGen diagnostics prohibits these implicit casts:
15+
func test_errors<T>(arg: T, sarg: String, darg: Data) {
16+
var t: T = arg
17+
readBytes(&t) // expected-error {{cannot implicitly convert an inout value of type 'T' to expected argument type 'UnsafeRawPointer' because 'T' may contain an object reference.}}
18+
writeBytes(&t) // expected-error {{cannot implicitly convert an inout value of type 'T' to expected argument type 'UnsafeMutableRawPointer' because 'T' may contain an object reference.}}
19+
read_char(&t) // expected-error {{cannot implicitly convert an inout value of type 'T' to expected argument type 'UnsafePointer<Int8>' because 'T' may contain an object reference.}}
20+
write_char(&t) // expected-error {{cannot implicitly convert an inout value of type 'T' to expected argument type 'UnsafeMutablePointer<Int8>' because 'T' may contain an object reference.}}
21+
read_uchar(&t) // expected-error {{cannot implicitly convert an inout value of type 'T' to expected argument type 'UnsafePointer<UInt8>' because 'T' may contain an object reference.}}
22+
write_uchar(&t) // expected-error {{cannot implicitly convert an inout value of type 'T' to expected argument type 'UnsafeMutablePointer<UInt8>' because 'T' may contain an object reference.}}
23+
24+
var array: [T] = [arg]
25+
readBytes(&array) // expected-error {{cannot implicitly convert an inout value of type '[T]' to expected argument type 'UnsafeRawPointer' because 'T' may contain an object reference.}}
26+
writeBytes(&array) // expected-error {{cannot implicitly convert an inout value of type '[T]' to expected argument type 'UnsafeMutableRawPointer' because 'T' may contain an object reference.}}
27+
28+
read_char(&array) // expected-error {{cannot implicitly convert an inout value of type 'Array<T>' to expected argument type 'UnsafePointer<Int8>' because 'T' may contain an object reference.}}
29+
write_char(&array) // expected-error {{cannot implicitly convert an inout value of type 'Array<T>' to expected argument type 'UnsafeMutablePointer<Int8>' because 'T' may contain an object reference.}}
30+
read_uchar(&array) // expected-error {{cannot implicitly convert an inout value of type 'Array<T>' to expected argument type 'UnsafePointer<UInt8>' because 'T' may contain an object reference.}}
31+
write_uchar(&array) // expected-error {{cannot implicitly convert an inout value of type 'Array<T>' to expected argument type 'UnsafeMutablePointer<UInt8>' because 'T' may contain an object reference.}}
32+
33+
var string: String = sarg
34+
readBytes(&string) // expected-error {{cannot implicitly convert an inout String to expected argument type 'UnsafeRawPointer'.}}
35+
writeBytes(&string) // expected-error {{cannot implicitly convert an inout String to expected argument type 'UnsafeMutableRawPointer'.}}
36+
read_char(&string) // expected-error {{cannot implicitly convert an inout String to expected argument type 'UnsafePointer<Int8>'.}}
37+
write_char(&string) // expected-error {{cannot implicitly convert an inout String to expected argument type 'UnsafeMutablePointer<Int8>'.}}
38+
read_uchar(&string) // expected-error {{cannot implicitly convert an inout String to expected argument type 'UnsafePointer<UInt8>'.}}
39+
write_uchar(&string) // expected-error {{cannot implicitly convert an inout String to expected argument type 'UnsafeMutablePointer<UInt8>'.}}
40+
41+
var data: Data = darg
42+
readBytes(&data) // expected-error {{cannot implicitly convert an inout value of type 'Data' to expected argument type 'UnsafeRawPointer' because 'Data' may contain an object reference.}}
43+
writeBytes(&data) // expected-error {{cannot implicitly convert an inout value of type 'Data' to expected argument type 'UnsafeMutableRawPointer' because 'Data' may contain an object reference.}}
44+
read_char(&data) // expected-error {{cannot implicitly convert an inout value of type 'Data' to expected argument type 'UnsafePointer<Int8>' because 'Data' may contain an object reference.}}
45+
write_char(&data) // expected-error {{cannot implicitly convert an inout value of type 'Data' to expected argument type 'UnsafeMutablePointer<Int8>' because 'Data' may contain an object reference.}}
46+
read_uchar(&data) // expected-error {{cannot implicitly convert an inout value of type 'Data' to expected argument type 'UnsafePointer<UInt8>' because 'Data' may contain an object reference.}}
47+
write_uchar(&data) // expected-error {{cannot implicitly convert an inout value of type 'Data' to expected argument type 'UnsafeMutablePointer<UInt8>' because 'Data' may contain an object reference.}}
48+
}
49+
50+
// SILGen diagnostics accepts these implicit casts:
51+
func test_accepted<I: FixedWidthInteger>(intArg: I, sarg: String, darg: Data) {
52+
var int: I = intArg
53+
readBytes(&int)
54+
writeBytes(&int)
55+
read_char(&int)
56+
write_char(&int)
57+
read_uchar(&int)
58+
write_uchar(&int)
59+
60+
let constArray: [I] = [intArg]
61+
readBytes(constArray)
62+
// read_char(constArray) - this case never worked because of a bug in SE-0324
63+
// read_uchar(constArray) - this case never worked because of a bug in SE-0324
64+
65+
var intArray: [I] = [intArg]
66+
readBytes(&intArray)
67+
writeBytes(&intArray)
68+
read_char(&intArray)
69+
write_char(&intArray)
70+
read_uchar(&intArray)
71+
write_uchar(&intArray)
72+
73+
var byteArray: [UInt8] = [0]
74+
readBytes(byteArray)
75+
writeBytes(&byteArray)
76+
// readInt8(&byteArray) - this case never worked because of a bug in SE-0324
77+
// writeInt8(&byteArray) - this case never worked because of a bug in SE-0324
78+
readUInt8(&byteArray)
79+
writeUInt8(&byteArray)
80+
write_char(&byteArray)
81+
read_uchar(byteArray)
82+
write_uchar(&byteArray)
83+
84+
let string: String = sarg
85+
readBytes(string)
86+
readUInt8(string)
87+
read_char(string)
88+
read_uchar(string)
89+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// RUN: %target-swift-emit-silgen -import-objc-header %S/Inputs/readbytes.h %s -o /dev/null -verify
2+
//
3+
// Diagnose invalid conversion from an inout argument to a raw pointer.
4+
//
5+
// These cases are caught early during Sema, so they are never seen by SILGen's implicit conversion diagnostics.
6+
7+
import Foundation
8+
9+
func readBytes(_ pointer: UnsafeRawPointer) {}
10+
func writeBytes(_ pointer: UnsafeMutableRawPointer) {}
11+
func readInt8(_ pointer: UnsafePointer<Int8>) {}
12+
func writeInt8(_ pointer: UnsafeMutablePointer<Int8>) {}
13+
func readUInt8(_ pointer: UnsafePointer<UInt8>) {}
14+
func writeUInt8(_ pointer: UnsafeMutablePointer<UInt8>) {}
15+
16+
// These implicit casts never worked and will continue to be unsupported.
17+
func test_unsupported<T>(arg: T, sarg: String, darg: Data) {
18+
var t: T = arg
19+
readInt8(&t) // expected-error {{cannot convert value of type 'UnsafePointer<T>' to expected argument type 'UnsafePointer<Int8>'}}
20+
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('T' and 'Int8') are expected to be equal}}
21+
writeInt8(&t) // expected-error {{cannot convert value of type 'UnsafeMutablePointer<T>' to expected argument type 'UnsafeMutablePointer<Int8>'}}
22+
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('T' and 'Int8') are expected to be equal}}
23+
readUInt8(&t) // expected-error {{cannot convert value of type 'UnsafePointer<T>' to expected argument type 'UnsafePointer<UInt8>'}}
24+
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('T' and 'UInt8') are expected to be equal}}
25+
writeUInt8(&t) // expected-error {{cannot convert value of type 'UnsafeMutablePointer<T>' to expected argument type 'UnsafeMutablePointer<UInt8>'}}
26+
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('T' and 'UInt8') are expected to be equal}}
27+
28+
let constArray: [UInt8] = [0]
29+
readInt8(constArray) // expected-error {{cannot convert value of type 'UnsafePointer<UInt8>' to expected argument type 'UnsafePointer<Int8>'}}
30+
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('UInt8' and 'Int8') are expected to be equal}}
31+
32+
// Mutating a const array obviously does not work, no need to show these
33+
// in the proposal
34+
writeBytes(constArray) // expected-error {{cannot convert value of type '[UInt8]' to expected argument type 'UnsafeMutableRawPointer'}}
35+
writeInt8(constArray) // expected-error {{cannot convert value of type '[UInt8]' to expected argument type 'UnsafeMutablePointer<Int8>'}}
36+
writeUInt8(constArray) // expected-error {{cannot convert value of type '[UInt8]' to expected argument type 'UnsafeMutablePointer<UInt8>'}}
37+
38+
var byteArray: [UInt8] = [0]
39+
readInt8(&byteArray) // expected-error {{cannot convert value of type 'UnsafePointer<UInt8>' to expected argument type 'UnsafePointer<Int8>'}}
40+
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('UInt8' and 'Int8') are expected to be equal}}
41+
writeInt8(&byteArray) // expected-error {{cannot convert value of type 'UnsafeMutablePointer<UInt8>' to expected argument type 'UnsafeMutablePointer<Int8>'}}
42+
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('UInt8' and 'Int8') are expected to be equal}}
43+
}
44+
45+
// These implicit casts should work according to
46+
// [SE-0324: Relax diagnostics for pointer arguments to C functions]
47+
// (https://github.com/apple/swift-evolution/blob/main/proposals/0324-c-lang-pointer-arg-conversion.md)
48+
// They currently raise a "cannot convert value" error because of
49+
// the `UInt8` vs. `Int8` mismatch.
50+
//
51+
// If we decide to support these as bug-fixes for SE-0324, then the
52+
// proposed diagnostic will also accept them.
53+
func test_se0324_bug(sarg: String, darg: Data) {
54+
let constIntArray: [Int8] = [0]
55+
read_uchar(constIntArray) // expected-error {{cannot convert value of type 'UnsafePointer<Int8>' to expected argument type 'UnsafePointer<UInt8>'}}
56+
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('Int8' and 'UInt8') are expected to be equal}}
57+
58+
let constUIntArray: [UInt8] = [0]
59+
read_char(constUIntArray) // expected-error {{cannot convert value of type 'UnsafePointer<UInt8>' to expected argument type 'UnsafePointer<CChar>' (aka 'UnsafePointer<Int8>')}}
60+
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('UInt8' and 'CChar' (aka 'Int8')) are expected to be equal}}
61+
62+
var intArray: [Int8] = [0]
63+
read_uchar(intArray) // expected-error {{cannot convert value of type 'UnsafePointer<Int8>' to expected argument type 'UnsafePointer<UInt8>'}}
64+
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('Int8' and 'UInt8') are expected to be equal}}
65+
66+
var uintArray: [UInt8] = [0]
67+
read_char(uintArray) // expected-error {{cannot convert value of type 'UnsafePointer<UInt8>' to expected argument type 'UnsafePointer<CChar>' (aka 'UnsafePointer<Int8>')}}
68+
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('UInt8' and 'CChar' (aka 'Int8')) are expected to be equal}}
69+
70+
}

0 commit comments

Comments
 (0)