| // RUN: %empty-directory(%t) |
| |
| // RUN: %gyb -DOPT_KIND=None %s -o %t/pointer_conversion.swift |
| // RUN: %line-directive %t/pointer_conversion.swift -- %target-swift-frontend -typecheck -verify %t/pointer_conversion.swift |
| |
| // RUN: %gyb -DOPT_KIND=Optional %s -o %t/pointer_conversion_opt.swift |
| // RUN: %line-directive %t/pointer_conversion_opt.swift -- %target-swift-frontend -typecheck -verify %t/pointer_conversion_opt.swift |
| |
| // RUN: %gyb -DOPT_KIND=ImplicitlyUnwrappedOptional %s -o %t/pointer_conversion_iuo.swift |
| // RUN: %line-directive %t/pointer_conversion_iuo.swift -- %target-swift-frontend -typecheck -verify %t/pointer_conversion_iuo.swift |
| |
| %{ |
| if OPT_KIND == 'Optional': |
| suffix='?' |
| elif OPT_KIND == 'ImplicitlyUnwrappedOptional': |
| suffix='!' |
| else: |
| suffix='' |
| }% |
| |
| class C {} |
| class D {} |
| |
| func takesMutablePointer(_ x: UnsafeMutablePointer<Int>${suffix}) {} |
| func takesMutableVoidPointer(_ x: UnsafeMutableRawPointer${suffix}) {} |
| func takesMutableRawPointer(_ x: UnsafeMutableRawPointer${suffix}) {} |
| func takesMutableInt8Pointer(_ x: UnsafeMutablePointer<Int8>${suffix}) {} |
| func takesMutableArrayPointer(_ x: UnsafeMutablePointer<[Int]>${suffix}) {} |
| @discardableResult |
| func takesConstPointer(_ x: UnsafePointer<Int>${suffix}) -> Character { return "x" } |
| func takesConstInt8Pointer(_ x: UnsafePointer<Int8>${suffix}) {} |
| func takesConstUInt8Pointer(_ x: UnsafePointer<UInt8>${suffix}) {} |
| func takesConstVoidPointer(_ x: UnsafeRawPointer${suffix}) {} |
| func takesConstRawPointer(_ x: UnsafeRawPointer${suffix}) {} |
| |
| func mutablePointerArguments(_ p: UnsafeMutablePointer<Int>, |
| cp: UnsafePointer<Int>) { |
| takesMutablePointer(nil) |
| % if not suffix: |
| // expected-error@-2 {{nil is not compatible with expected argument type}} |
| % end |
| |
| takesMutablePointer(p) |
| takesMutablePointer(cp) // expected-error{{cannot convert value of type 'UnsafePointer<Int>' to expected argument type 'UnsafeMutablePointer<Int>${suffix}'}} |
| var i: Int = 0 |
| var f: Float = 0 |
| takesMutablePointer(&i) |
| takesMutablePointer(&f) // expected-error{{cannot convert value of type 'Float' to expected argument type 'Int'}} |
| takesMutablePointer(i) // expected-error{{cannot convert value of type 'Int' to expected argument type 'UnsafeMutablePointer<Int>${suffix}'}} |
| takesMutablePointer(f) // expected-error{{cannot convert value of type 'Float' to expected argument type 'UnsafeMutablePointer<Int>${suffix}'}} |
| var ii: [Int] = [0, 1, 2] |
| var ff: [Float] = [0, 1, 2] |
| takesMutablePointer(&ii) |
| takesMutablePointer(&ff) // expected-error{{cannot convert value of type '[Float]' to expected argument type 'Int'}} |
| takesMutablePointer(ii) // expected-error{{cannot convert value of type '[Int]' to expected argument type 'UnsafeMutablePointer<Int>${suffix}'}} |
| takesMutablePointer(ff) // expected-error{{cannot convert value of type '[Float]' to expected argument type 'UnsafeMutablePointer<Int>${suffix}'}} |
| |
| takesMutableArrayPointer(&i) // expected-error{{cannot convert value of type 'Int' to expected argument type '[Int]'}} |
| takesMutableArrayPointer(&ii) |
| |
| // We don't allow these conversions outside of function arguments. |
| var x: UnsafeMutablePointer<Int> = &i // expected-error{{cannot pass immutable value as inout argument: 'i' is immutable}} |
| x = &ii // expected-error{{cannot assign value of type 'inout [Int]' to type 'UnsafeMutablePointer<Int>'}} |
| _ = x |
| } |
| |
| func mutableVoidPointerArguments(_ p: UnsafeMutablePointer<Int>, |
| cp: UnsafePointer<Int>, |
| fp: UnsafeMutablePointer<Float>) { |
| takesMutableVoidPointer(nil) |
| % if not suffix: |
| // expected-error@-2 {{nil is not compatible with expected argument type}} |
| % end |
| |
| takesMutableVoidPointer(p) |
| takesMutableVoidPointer(fp) |
| takesMutableVoidPointer(cp) // expected-error{{cannot convert value of type 'UnsafePointer<Int>' to expected argument type 'UnsafeMutableRawPointer${suffix}'}} |
| var i: Int = 0 |
| var f: Float = 0 |
| takesMutableVoidPointer(&i) |
| takesMutableVoidPointer(&f) |
| takesMutableVoidPointer(i) // expected-error{{cannot convert value of type 'Int' to expected argument type 'UnsafeMutableRawPointer${suffix}'}} |
| takesMutableVoidPointer(f) // expected-error{{cannot convert value of type 'Float' to expected argument type 'UnsafeMutableRawPointer${suffix}'}} |
| var ii: [Int] = [0, 1, 2] |
| var dd: [CInt] = [1, 2, 3] |
| var ff: [Int] = [0, 1, 2] |
| takesMutableVoidPointer(&ii) |
| takesMutableVoidPointer(&dd) |
| takesMutableVoidPointer(&ff) |
| takesMutableVoidPointer(ii) // expected-error{{cannot convert value of type '[Int]' to expected argument type 'UnsafeMutableRawPointer${suffix}'}} |
| takesMutableVoidPointer(ff) // expected-error{{cannot convert value of type '[Int]' to expected argument type 'UnsafeMutableRawPointer${suffix}'}} |
| |
| // We don't allow these conversions outside of function arguments. |
| var x: UnsafeMutableRawPointer = &i // expected-error{{cannot convert value of type 'inout Int' to specified type 'UnsafeMutableRawPointer'}} |
| x = p // expected-error{{cannot assign value of type 'UnsafeMutablePointer<Int>' to type 'UnsafeMutableRawPointer'}} |
| x = &ii // expected-error{{cannot assign value of type 'inout [Int]' to type 'UnsafeMutableRawPointer'}} |
| _ = x |
| } |
| |
| func mutableRawPointerArguments(_ p: UnsafeMutablePointer<Int>, |
| cp: UnsafePointer<Int>, |
| fp: UnsafeMutablePointer<Float>, |
| rp: UnsafeRawPointer) { |
| takesMutableRawPointer(nil) |
| % if not suffix: |
| // expected-error@-2 {{nil is not compatible with expected argument type}} |
| % end |
| |
| takesMutableRawPointer(p) |
| takesMutableRawPointer(fp) |
| takesMutableRawPointer(cp) // expected-error{{cannot convert value of type 'UnsafePointer<Int>' to expected argument type 'UnsafeMutableRawPointer${suffix}'}} |
| takesMutableRawPointer(rp) // expected-error{{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutableRawPointer${suffix}'}} |
| var i: Int = 0 |
| var f: Float = 0 |
| takesMutableRawPointer(&i) |
| takesMutableRawPointer(&f) |
| takesMutableRawPointer(i) // expected-error{{cannot convert value of type 'Int' to expected argument type 'UnsafeMutableRawPointer${suffix}'}} |
| takesMutableRawPointer(f) // expected-error{{cannot convert value of type 'Float' to expected argument type 'UnsafeMutableRawPointer${suffix}'}} |
| var ii: [Int] = [0, 1, 2] |
| var dd: [CInt] = [1, 2, 3] |
| var ff: [Int] = [0, 1, 2] |
| takesMutableRawPointer(&ii) |
| takesMutableRawPointer(&dd) |
| takesMutableRawPointer(&ff) |
| takesMutableRawPointer(ii) // expected-error{{cannot convert value of type '[Int]' to expected argument type 'UnsafeMutableRawPointer${suffix}'}} |
| takesMutableRawPointer(ff) // expected-error{{cannot convert value of type '[Int]' to expected argument type 'UnsafeMutableRawPointer${suffix}'}} |
| |
| // We don't allow these conversions outside of function arguments. |
| var x: UnsafeMutableRawPointer = &i // expected-error{{cannot convert value of type 'inout Int' to specified type 'UnsafeMutableRawPointer'}} |
| x = p // expected-error{{cannot assign value of type 'UnsafeMutablePointer<Int>' to type 'UnsafeMutableRawPointer'}} |
| x = &ii // expected-error{{cannot assign value of type 'inout [Int]' to type 'UnsafeMutableRawPointer'}} |
| _ = x |
| } |
| |
| func constPointerArguments(_ p: UnsafeMutablePointer<Int>, |
| cp: UnsafePointer<Int>) { |
| takesConstPointer(nil) |
| % if not suffix: |
| // expected-error@-2 {{nil is not compatible with expected argument type}} |
| % end |
| |
| takesConstPointer(p) |
| takesConstPointer(cp) |
| |
| var i: Int = 0 |
| var f: Float = 0 |
| takesConstPointer(&i) |
| takesConstPointer(&f) // expected-error{{cannot convert value of type 'Float' to expected argument type 'Int'}} |
| var ii: [Int] = [0, 1, 2] |
| var ff: [Float] = [0, 1, 2] |
| takesConstPointer(&ii) |
| takesConstPointer(&ff) // expected-error{{cannot convert value of type '[Float]' to expected argument type 'Int'}} |
| takesConstPointer(ii) |
| takesConstPointer(ff) // expected-error{{cannot convert value of type '[Float]' to expected argument type 'UnsafePointer<Int>${suffix}'}} |
| takesConstPointer([0, 1, 2]) |
| // <rdar://problem/22308330> QoI: CSDiags doesn't handle array -> pointer impl conversions well |
| takesConstPointer([0.0, 1.0, 2.0]) // expected-error{{cannot convert value of type 'Double' to expected element type 'Int'}} |
| |
| // We don't allow these conversions outside of function arguments. |
| var x: UnsafePointer<Int> = &i // expected-error{{cannot pass immutable value as inout argument: 'i' is immutable}} |
| x = ii // expected-error{{cannot assign value of type '[Int]' to type 'UnsafePointer<Int>'}} |
| x = p // expected-error{{cannot assign value of type 'UnsafeMutablePointer<Int>' to type 'UnsafePointer<Int>'}} |
| } |
| |
| func constVoidPointerArguments(_ p: UnsafeMutablePointer<Int>, |
| fp: UnsafeMutablePointer<Float>, |
| cp: UnsafePointer<Int>, |
| cfp: UnsafePointer<Float>) { |
| takesConstVoidPointer(nil) |
| % if not suffix: |
| // expected-error@-2 {{nil is not compatible with expected argument type}} |
| % end |
| |
| takesConstVoidPointer(p) |
| takesConstVoidPointer(fp) |
| takesConstVoidPointer(cp) |
| takesConstVoidPointer(cfp) |
| |
| var i: Int = 0 |
| var f: Float = 0 |
| takesConstVoidPointer(&i) |
| takesConstVoidPointer(&f) |
| var ii: [Int] = [0, 1, 2] |
| var ff: [Float] = [0, 1, 2] |
| takesConstVoidPointer(&ii) |
| takesConstVoidPointer(&ff) |
| takesConstVoidPointer(ii) |
| takesConstVoidPointer(ff) |
| |
| takesConstVoidPointer([0, 1, 2]) |
| takesConstVoidPointer([0.0, 1.0, 2.0]) |
| |
| // We don't allow these conversions outside of function arguments. |
| var x: UnsafeRawPointer = &i // expected-error{{cannot convert value of type 'inout Int' to specified type 'UnsafeRawPointer'}} |
| x = ii // expected-error{{cannot assign value of type '[Int]' to type 'UnsafeRawPointer'}} |
| x = p // expected-error{{cannot assign value of type 'UnsafeMutablePointer<Int>' to type 'UnsafeRawPointer'}} |
| x = fp // expected-error{{cannot assign value of type 'UnsafeMutablePointer<Float>' to type 'UnsafeRawPointer'}} |
| x = cp // expected-error{{cannot assign value of type 'UnsafePointer<Int>' to type 'UnsafeRawPointer'}} |
| x = cfp // expected-error{{cannot assign value of type 'UnsafePointer<Float>' to type 'UnsafeRawPointer'}} |
| _ = x |
| } |
| |
| func constRawPointerArguments(_ p: UnsafeMutablePointer<Int>, |
| fp: UnsafeMutablePointer<Float>, |
| cp: UnsafePointer<Int>, |
| cfp: UnsafePointer<Float>, |
| mrp: UnsafeMutableRawPointer) { |
| takesConstRawPointer(nil) |
| % if not suffix: |
| // expected-error@-2 {{nil is not compatible with expected argument type}} |
| % end |
| |
| takesConstRawPointer(p) |
| takesConstRawPointer(fp) |
| takesConstRawPointer(cp) |
| takesConstRawPointer(cfp) |
| takesConstRawPointer(mrp) |
| |
| var i: Int = 0 |
| var f: Float = 0 |
| takesConstRawPointer(&i) |
| takesConstRawPointer(&f) |
| var ii: [Int] = [0, 1, 2] |
| var ff: [Float] = [0, 1, 2] |
| takesConstRawPointer(&ii) |
| takesConstRawPointer(&ff) |
| takesConstRawPointer(ii) |
| takesConstRawPointer(ff) |
| |
| takesConstRawPointer([0, 1, 2]) |
| takesConstRawPointer([0.0, 1.0, 2.0]) |
| |
| // We don't allow these conversions outside of function arguments. |
| var x: UnsafeRawPointer = &i // expected-error{{cannot convert value of type 'inout Int' to specified type 'UnsafeRawPointer'}} |
| x = ii // expected-error{{cannot assign value of type '[Int]' to type 'UnsafeRawPointer'}} |
| x = p // expected-error{{cannot assign value of type 'UnsafeMutablePointer<Int>' to type 'UnsafeRawPointer'}} |
| x = fp // expected-error{{cannot assign value of type 'UnsafeMutablePointer<Float>' to type 'UnsafeRawPointer'}} |
| x = cp // expected-error{{cannot assign value of type 'UnsafePointer<Int>' to type 'UnsafeRawPointer'}} |
| x = cfp // expected-error{{cannot assign value of type 'UnsafePointer<Float>' to type 'UnsafeRawPointer'}} |
| _ = x |
| } |
| |
| func stringArguments(_ s: String) { |
| var s = s |
| takesConstVoidPointer(s) |
| takesConstRawPointer(s) |
| takesConstInt8Pointer(s) |
| takesConstUInt8Pointer(s) |
| takesConstPointer(s) // expected-error{{cannot convert value of type 'String' to expected argument type 'UnsafePointer<Int>${suffix}'}} |
| |
| takesMutableVoidPointer(s) // expected-error{{cannot convert value of type 'String' to expected argument type 'UnsafeMutableRawPointer${suffix}'}} |
| takesMutableRawPointer(s) // expected-error{{cannot convert value of type 'String' to expected argument type 'UnsafeMutableRawPointer${suffix}'}} |
| takesMutableInt8Pointer(s) // expected-error{{cannot convert value of type 'String' to expected argument type 'UnsafeMutablePointer<Int8>${suffix}'}} |
| takesMutableInt8Pointer(&s) // expected-error{{cannot convert value of type 'String' to expected argument type 'Int8'}} |
| takesMutablePointer(s) // expected-error{{cannot convert value of type 'String' to expected argument type 'UnsafeMutablePointer<Int>${suffix}'}} |
| takesMutablePointer(&s) // expected-error{{cannot convert value of type 'String' to expected argument type 'Int'}} |
| } |
| |
| |
| func optionality(_ op: UnsafeMutablePointer<Float>?) { |
| takesMutableVoidPointer(op) |
| % if not suffix: |
| // expected-error@-2 {{value of optional type 'UnsafeMutablePointer<Float>?' not unwrapped}} |
| % end |
| |
| takesConstVoidPointer(op) |
| % if not suffix: |
| // expected-error@-2 {{value of optional type 'UnsafeMutablePointer<Float>?' not unwrapped}} |
| % end |
| } |
| |
| func pointerArithmetic(_ x: UnsafeMutablePointer<Int>, y: UnsafeMutablePointer<Int>, |
| i: Int) { |
| _ = x + i |
| _ = x - y |
| } |
| |
| func genericPointerArithmetic<T>(_ x: UnsafeMutablePointer<T>, i: Int, t: T) -> UnsafeMutablePointer<T> { |
| let p = x + i |
| p.initialize(to: t) |
| } |
| |
| func passPointerToClosure(_ f: (UnsafeMutablePointer<Int>) -> Int) -> Int { } |
| |
| func pointerInClosure(_ f: (UnsafePointer<Int>) -> Int) -> Int { |
| return passPointerToClosure { f($0) } |
| } |
| |
| struct NotEquatable {} |
| |
| func arrayComparison(_ x: [NotEquatable], y: [NotEquatable], p: UnsafeMutablePointer<NotEquatable>) { |
| var x = x |
| // Don't allow implicit array-to-pointer conversions in operators. |
| // FIXME: The use of <Self: Equatable> in this diagnostic is awful. |
| let a: Bool = x == y // expected-error{{'<Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool' requires that 'NotEquatable' conform to 'Equatable'}} |
| // expected-note @-1 {{requirement specified as 'NotEquatable' : 'Equatable'}} |
| // expected-note @-2 {{requirement from conditional conformance of '[NotEquatable]' to 'Equatable'}} |
| |
| let _: Bool = p == &x // Allowed! |
| } |
| |
| func addressConversion(p: UnsafeMutablePointer<Int>, x: Int) { |
| var x = x |
| let _: Bool = p == &x |
| } |
| |
| // <rdar://problem/19478919> QoI: poor error: '&' used with non-inout argument of type 'UnsafeMutablePointer<Int32>' |
| func f19478919() { |
| var viewport: Int = 1 // intentionally incorrect type, not Int32 |
| func GLKProject(_ a : UnsafeMutablePointer<Int32>) {} |
| GLKProject(&viewport) // expected-error {{cannot convert value of type 'Int' to expected argument type 'Int32'}} |
| |
| func GLKProjectUP(_ a : UnsafePointer<Int32>) {} |
| func UP_Void(_ a : UnsafeRawPointer) {} |
| func UMP_Void(_ a : UnsafeMutableRawPointer) {} |
| UP_Void(&viewport) |
| UMP_Void(&viewport) |
| |
| let cst = 42 // expected-note 2 {{change 'let' to 'var' to make it mutable}} |
| UP_Void(&cst) // expected-error {{cannot pass immutable value as inout argument: 'cst' is a 'let' constant}} |
| UMP_Void(&cst) // expected-error {{cannot pass immutable value as inout argument: 'cst' is a 'let' constant}} |
| } |
| |
| // <rdar://problem/23202128> QoI: Poor diagnostic with let vs. var passed to C function |
| func f23202128() { |
| func UP(_ p: UnsafePointer<Int32>) {} |
| func UMP(_ p: UnsafeMutablePointer<Int32>) {} |
| |
| let pipe: [Int32] = [0, 0] // expected-note {{change 'let' to 'var' to make it mutable}}}} |
| UMP(&pipe) // expected-error {{cannot pass immutable value as inout argument: 'pipe' is a 'let' constant}} |
| |
| var pipe2: [Int] = [0, 0] |
| UMP(&pipe2) // expected-error {{cannot convert value of type '[Int]' to expected argument type 'Int32'}} |
| |
| |
| UP(pipe) // ok |
| UP(&pipe) // expected-error {{'&' is not allowed passing array value as 'UnsafePointer<Int32>' argument}} {{6-7=}} |
| } |
| |
| func takesRawBuffer(_ b: UnsafeRawBufferPointer) {} |
| |
| // <rdar://problem/29586888> UnsafeRawBufferPointer range subscript is inconsistent with Collection. |
| func f29586888(b: UnsafeRawBufferPointer) { |
| takesRawBuffer(b[1..<2]) // expected-error {{'subscript' is unavailable: use 'UnsafeRawBufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.}} |
| let slice = b[1..<2] |
| takesRawBuffer(slice) // expected-error {{cannot convert value of type 'RandomAccessSlice<UnsafeRawBufferPointer>' to expected argument type 'UnsafeRawBufferPointer'}} |
| } |