mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
The callers to ConversionInitialization::tryPeephole assume that, if the conversion peephole succeeded, that the peepholed result was fully emitted into the initialization. However, if the ConversionInitialization sat on top of an in-memory initialization, then tryPeephole would only set the value of the ConversionInitialization, without forwarding the value into the underlying initialization, causing code generation to proceed leaving the underlying memory uninitialized. This problem becomes exposed now when literal closures are emitted with a return value that is indirectly returned and also reabstracted, and the return expression undergoes a ping-pong reabstraction pair: we see through the conversions and peephole away the reabstractions, but fail to emplace the result in the indirect return slot. Fixes rdar://92654098
33 lines
929 B
Swift
33 lines
929 B
Swift
// RUN: %target-swift-emit-silgen -verify %s
|
|
|
|
fileprivate typealias Closure = () -> Void
|
|
|
|
func crash1() {
|
|
let closure1: Closure? = nil
|
|
let closure2: Closure? = nil
|
|
let closure3: Closure? = nil
|
|
print("Closures: \(String(describing: closure1)), \(String(describing: closure2)), \(String(describing: closure3))")
|
|
|
|
let closure = closure1 ?? closure2 ?? closure3
|
|
|
|
print("\(#line): \(String(describing: closure))")
|
|
closure?() // <- EXC_BAD_ACCESS
|
|
assert(closure == nil)
|
|
}
|
|
|
|
func crash2() {
|
|
let closure1: Closure? = nil
|
|
let closure2: Closure? = nil
|
|
let closure3: Closure? = { }
|
|
print("Closures: \(String(describing: closure1)), \(String(describing: closure2)), \(String(describing: closure3))")
|
|
|
|
let closure = closure1 ?? closure2 ?? closure3
|
|
|
|
print("\(#line): \(String(describing: closure))")
|
|
closure?() // <- EXC_BAD_ACCESS
|
|
assert(closure != nil)
|
|
}
|
|
|
|
crash1()
|
|
crash2()
|