Files
swift-mirror/test/SILGen/diagnose_implicit_raw_conversion.swift
Pavel Yaskevich 29b04f4a63 [CSSimplify] SE-0324: Use correct conversion when converting array types
If the argument type is an array and it's passed to an imported declaration
that accepts a raw pointer, the solver should use an "array-to-c-pointer"
conversion instead of the one for pointers.

Resolves: rdar://158629300
2025-08-21 15:38:17 -07:00

223 lines
12 KiB
Swift

// RUN: %target-swift-emit-silgen -import-objc-header %S/Inputs/readbytes.h %s -o /dev/null -verify
//
// Diagnose invalid conversion from an inout argument to a raw pointer.
func readBytes(_ pointer: UnsafeRawPointer) {}
func writeBytes(_ pointer: UnsafeMutableRawPointer) {}
func readInt8(_ pointer: UnsafePointer<Int8>) {}
func writeInt8(_ pointer: UnsafeMutablePointer<Int8>) {}
func readUInt8(_ pointer: UnsafePointer<UInt8>) {}
func writeUInt8(_ pointer: UnsafeMutablePointer<UInt8>) {}
struct Aggregate {
var pointer: UnsafeRawPointer?
var value: Int32
}
class C {
init() {}
}
struct NonTrivial {
var c: C
}
// SILGen diagnostics prohibits these implicit casts:
func test_errors<T>(arg: T, sarg: String, anyBCArg: BitwiseCopyable) {
var nonTrivial = NonTrivial(c: C())
readBytes(&nonTrivial) // expected-warning {{forming 'UnsafeRawPointer' to a variable of type 'NonTrivial'; this is likely incorrect because 'NonTrivial' may contain an object reference.}}
writeBytes(&nonTrivial) // expected-warning {{forming 'UnsafeMutableRawPointer' to a variable of type 'NonTrivial'; this is likely incorrect because 'NonTrivial' may contain an object reference.}}
var t: T = arg
readBytes(&t) // expected-warning {{forming 'UnsafeRawPointer' to a variable of type 'T'; this is likely incorrect because 'T' may contain an object reference.}}
writeBytes(&t) // expected-warning {{forming 'UnsafeMutableRawPointer' to a variable of type 'T'; this is likely incorrect because 'T' may contain an object reference.}}
read_char(&t) // expected-warning {{forming 'UnsafePointer<Int8>' to a variable of type 'T'; this is likely incorrect because 'T' may contain an object reference.}}
write_char(&t) // expected-warning {{forming 'UnsafeMutablePointer<Int8>' to a variable of type 'T'; this is likely incorrect because 'T' may contain an object reference.}}
read_uchar(&t) // expected-warning {{forming 'UnsafePointer<UInt8>' to a variable of type 'T'; this is likely incorrect because 'T' may contain an object reference.}}
write_uchar(&t) // expected-warning {{forming 'UnsafeMutablePointer<UInt8>' to a variable of type 'T'; this is likely incorrect because 'T' may contain an object reference.}}
let constArray: [T] = [arg]
readBytes(constArray) // expected-warning {{forming 'UnsafeRawPointer' to a variable of type '[T]'; this is likely incorrect because 'T' may contain an object reference.}}
read_char(constArray) // expected-warning {{forming 'UnsafePointer<CChar>' (aka 'UnsafePointer<Int8>') to a variable of type '[T]'; this is likely incorrect because 'T' may contain an object reference.}}
read_uchar(constArray) // expected-warning {{forming 'UnsafePointer<UInt8>' to a variable of type '[T]'; this is likely incorrect because 'T' may contain an object reference.}}
var array: [T] = [arg]
readBytes(&array) // expected-warning {{forming 'UnsafeRawPointer' to a variable of type '[T]'; this is likely incorrect because 'T' may contain an object reference.}}
writeBytes(&array) // expected-warning {{forming 'UnsafeMutableRawPointer' to a variable of type '[T]'; this is likely incorrect because 'T' may contain an object reference.}}
read_char(&array) // expected-warning {{forming 'UnsafePointer<CChar>' (aka 'UnsafePointer<Int8>') to a variable of type '[T]'; this is likely incorrect because 'T' may contain an object reference.}}
write_char(&array) // expected-warning {{forming 'UnsafeMutablePointer<CChar>' (aka 'UnsafeMutablePointer<Int8>') to a variable of type '[T]'; this is likely incorrect because 'T' may contain an object reference.}}
read_uchar(&array) // expected-warning {{forming 'UnsafePointer<UInt8>' to a variable of type '[T]'; this is likely incorrect because 'T' may contain an object reference.}}
write_uchar(&array) // expected-warning {{forming 'UnsafeMutablePointer<UInt8>' to a variable of type '[T]'; this is likely incorrect because 'T' may contain an object reference.}}
var anyBC: BitwiseCopyable = anyBCArg
readBytes(&anyBC) // expected-warning {{forming 'UnsafeRawPointer' to a variable of type 'any BitwiseCopyable'; this is likely incorrect because 'any BitwiseCopyable' may contain an object reference.}}
writeBytes(&anyBC) // expected-warning {{forming 'UnsafeMutableRawPointer' to a variable of type 'any BitwiseCopyable'; this is likely incorrect because 'any BitwiseCopyable' may contain an object reference.}}
read_char(&anyBC) // expected-warning {{forming 'UnsafePointer<Int8>' to a variable of type 'any BitwiseCopyable'; this is likely incorrect because 'any BitwiseCopyable' may contain an object reference.}}
write_char(&anyBC) // expected-warning {{forming 'UnsafeMutablePointer<Int8>' to a variable of type 'any BitwiseCopyable'; this is likely incorrect because 'any BitwiseCopyable' may contain an object reference.}}
read_uchar(&anyBC) // expected-warning {{forming 'UnsafePointer<UInt8>' to a variable of type 'any BitwiseCopyable'; this is likely incorrect because 'any BitwiseCopyable' may contain an object reference.}}
write_uchar(&anyBC) // expected-warning {{forming 'UnsafeMutablePointer<UInt8>' to a variable of type 'any BitwiseCopyable'; this is likely incorrect because 'any BitwiseCopyable' may contain an object reference.}}
let constBCArray: [BitwiseCopyable] = [anyBCArg]
readBytes(constBCArray) // expected-warning {{forming 'UnsafeRawPointer' to a variable of type '[any BitwiseCopyable]'; this is likely incorrect because 'any BitwiseCopyable' may contain an object reference.}}
read_char(constBCArray) // expected-warning {{forming 'UnsafePointer<CChar>' (aka 'UnsafePointer<Int8>') to a variable of type '[any BitwiseCopyable]'; this is likely incorrect because 'any BitwiseCopyable' may contain an object reference.}}
read_uchar(constBCArray) // expected-warning {{forming 'UnsafePointer<UInt8>' to a variable of type '[any BitwiseCopyable]'; this is likely incorrect because 'any BitwiseCopyable' may contain an object reference.}}
var bcArray: [BitwiseCopyable] = [anyBCArg]
readBytes(&bcArray) // expected-warning {{forming 'UnsafeRawPointer' to a variable of type '[any BitwiseCopyable]'; this is likely incorrect because 'any BitwiseCopyable' may contain an object reference.}}
writeBytes(&bcArray) // expected-warning {{forming 'UnsafeMutableRawPointer' to a variable of type '[any BitwiseCopyable]'; this is likely incorrect because 'any BitwiseCopyable' may contain an object reference.}}
read_char(&bcArray) // expected-warning {{forming 'UnsafePointer<CChar>' (aka 'UnsafePointer<Int8>') to a variable of type '[any BitwiseCopyable]'; this is likely incorrect because 'any BitwiseCopyable' may contain an object reference.}}
write_char(&bcArray) // expected-warning {{forming 'UnsafeMutablePointer<CChar>' (aka 'UnsafeMutablePointer<Int8>') to a variable of type '[any BitwiseCopyable]'; this is likely incorrect because 'any BitwiseCopyable' may contain an object reference.}}
read_uchar(&bcArray) // expected-warning {{forming 'UnsafePointer<UInt8>' to a variable of type '[any BitwiseCopyable]'; this is likely incorrect because 'any BitwiseCopyable' may contain an object reference.}}
write_uchar(&bcArray) // expected-warning {{forming 'UnsafeMutablePointer<UInt8>' to a variable of type '[any BitwiseCopyable]'; this is likely incorrect because 'any BitwiseCopyable' may contain an object reference.}}
var string: String = sarg
readBytes(&string) // expected-warning {{forming 'UnsafeRawPointer' to an inout variable of type String exposes the internal representation rather than the string contents.}}
writeBytes(&string) // expected-warning {{forming 'UnsafeMutableRawPointer' to an inout variable of type String exposes the internal representation rather than the string contents.}}
read_char(&string) // expected-warning {{forming 'UnsafePointer<Int8>' to an inout variable of type String exposes the internal representation rather than the string contents.}}
write_char(&string) // expected-warning {{forming 'UnsafeMutablePointer<Int8>' to an inout variable of type String exposes the internal representation rather than the string contents.}}
read_uchar(&string) // expected-warning {{forming 'UnsafePointer<UInt8>' to an inout variable of type String exposes the internal representation rather than the string contents.}}
write_uchar(&string) // expected-warning {{forming 'UnsafeMutablePointer<UInt8>' to an inout variable of type String exposes the internal representation rather than the string contents.}}
}
// Test the explicit cast workaround for all of the above errors
func test_explicit<T>(arg: T, sarg: String) {
var nonTrivial = NonTrivial(c: C())
withUnsafeBytes(of: &nonTrivial) {
readBytes($0.baseAddress!)
}
withUnsafeMutableBytes(of: &nonTrivial) {
writeBytes($0.baseAddress!)
}
var t: T = arg
withUnsafeBytes(of: &t) {
readBytes($0.baseAddress!)
read_char($0.baseAddress!)
read_uchar($0.baseAddress!)
}
withUnsafeMutableBytes(of: &t) {
writeBytes($0.baseAddress!)
write_char($0.baseAddress!)
write_uchar($0.baseAddress!)
}
let constArray: [T] = [arg]
constArray.withUnsafeBytes() {
readBytes($0.baseAddress!)
read_char($0.baseAddress!)
read_uchar($0.baseAddress!)
}
var array: [T] = [arg]
array.withUnsafeBytes() {
readBytes($0.baseAddress!)
read_char($0.baseAddress!)
read_uchar($0.baseAddress!)
}
array.withUnsafeMutableBytes() {
writeBytes($0.baseAddress!)
write_char($0.baseAddress!)
write_uchar($0.baseAddress!)
}
let string: String = sarg
readBytes(string)
read_char(string)
read_uchar(string)
}
// SILGen diagnostics accepts these implicit casts:
func test_accepted<I: FixedWidthInteger, BC: BitwiseCopyable>(intArg: I, bcArg: BC,
sarg: String, simdArg: SIMD4<Float>) {
var aggregate = Aggregate(pointer: UnsafeRawPointer(bitPattern: 0), value: 0)
readBytes(&aggregate)
writeBytes(&aggregate)
read_char(&aggregate)
write_char(&aggregate)
read_uchar(&aggregate)
write_uchar(&aggregate)
var int: I = intArg
readBytes(&int)
writeBytes(&int)
read_char(&int)
write_char(&int)
read_uchar(&int)
write_uchar(&int)
let constIntArray: [I] = [intArg]
readBytes(constIntArray)
read_char(constIntArray)
read_uchar(constIntArray)
var intArray: [I] = [intArg]
readBytes(&intArray)
writeBytes(&intArray)
read_char(&intArray)
write_char(&intArray)
read_uchar(&intArray)
write_uchar(&intArray)
var bc: BC = bcArg
readBytes(&bc)
writeBytes(&bc)
read_char(&bc)
write_char(&bc)
read_uchar(&bc)
write_uchar(&bc)
let constBCArray: [BC] = [bcArg]
readBytes(constBCArray)
read_char(constBCArray)
read_uchar(constBCArray)
var bcArray: [BC] = [bcArg]
readBytes(&bcArray)
writeBytes(&bcArray)
read_char(&bcArray)
write_char(&bcArray)
read_uchar(&bcArray)
write_uchar(&bcArray)
let constByteArray: [UInt8] = [0]
readBytes(constByteArray)
read_char(constByteArray)
read_uchar(constByteArray)
var byteArray: [UInt8] = [0]
readBytes(&byteArray)
writeBytes(&byteArray)
readUInt8(&byteArray)
writeUInt8(&byteArray)
write_char(&byteArray)
read_uchar(byteArray)
write_uchar(&byteArray)
let constInt8Array: [Int8] = [0]
readBytes(constInt8Array)
read_char(constInt8Array)
read_uchar(constInt8Array)
var int8Array: [Int8] = [0]
readBytes(&int8Array)
writeBytes(&int8Array)
read_char(&int8Array)
write_char(&int8Array)
read_uchar(&int8Array)
write_uchar(&int8Array)
let string: String = sarg
readBytes(string)
readUInt8(string)
read_char(string)
read_uchar(string)
var simd: SIMD4<Float> = simdArg
readBytes(&simd)
writeBytes(&simd)
read_char(&simd)
write_char(&simd)
read_uchar(&simd)
write_uchar(&simd)
}