Files
swift-mirror/test/SILOptimizer/consume_operator_reinit_in_defer.swift
Joe Groff 74aaf88697 Turn mishandled reinitialize-in-defer-after-consume cases into errors.
The handling of multi-basic-block control flow in `defer` blocks looks like it
was left incomplete and completely untested; I fixed a few obvious problems but
it still completely lacks any analysis of conditional reinitializations. For now,
change it to treat attempted reinitializations as uses-after-consumes so we raise
reliable errors now instead of emitting code that causes memory corruption at
runtime. Fixes rdar://129303198.
2024-06-05 14:12:00 -07:00

53 lines
1.5 KiB
Swift

// RUN: %target-swift-frontend -emit-sil -verify %s
func consume<T>(_: consuming T) {}
func testSingleBlock<T>(x: inout T, y: T) {
defer { x = y }
consume(consume x)
}
func cond() -> Bool { fatalError() }
// TODO: should be accepted
func testAlwaysReinitAfterConditional<T>(x: inout T, y: T) { // not-really expected-error{{used after consume}}
defer {
if cond() { }
x = y // not-really expected-note{{}}
}
consume(consume x) // not-really expected-note{{}}
}
// TODO: should be accepted
func testAlwaysReinitBeforeConditional<T>(x: inout T, y: T) { // not-really expected-error{{used after consume}}
defer {
x = y // not-really expected-note{{}}
if cond() { }
}
consume(consume x) // not-really expected-note{{}}
}
// TODO: should be accepted
func testAlwaysReinitInBothBranchesOfConditional<T>(x: inout T, y: T) { // not-really expected-error{{used after consume}}
defer {
if cond() {
x = y // not-really expected-note{{}}
} else {
x = y
}
}
consume(consume x) // not-really expected-note{{}}
}
// TODO: should raise an error about inout not being reinitialized on all paths
func testSometimesReinitInConditional<T>(x: inout T, y: T) { // not-really expected-error{{used after consume}}
defer {
if cond() {
x = y // not-really expected-note{{}}
} else {
// ex/pected-note {{not initialized on this path}}
}
}
consume(consume x) // not-really expected-note{{}}
}