mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
The effect of passing -enable-copy-propagation is both to enable the CopyPropagation pass to shorten object lifetimes and also to enable lexical lifetimes to ensure that object lifetimes aren't shortened while a variable is still in scope and used. Add a new flag, -enable-lexical-borrow-scopes=true to override -enable-copy-propagation's effect (setting it to ::ExperimentalLate) on SILOptions::LexicalLifetimes that sets it to ::Early even in the face of -enable-copy-propagation. The old flag -disable-lexical-lifetimes is renamed to -enable-lexical-borrow-scopes=false but continues to set that option to ::Off even when -enable-copy-propagation is passed.
100 lines
2.6 KiB
Swift
100 lines
2.6 KiB
Swift
// RUN: %target-swift-frontend -emit-sil -enable-lexical-borrow-scopes=false -enable-copy-propagation %s -o /dev/null -verify
|
|
|
|
class Delegate {
|
|
func foo() { }
|
|
}
|
|
|
|
final class Container {
|
|
weak var delegate: Delegate?
|
|
var strongRef: Delegate
|
|
|
|
func callDelegate() {
|
|
delegate!.foo()
|
|
}
|
|
|
|
init(_ d: Delegate) { strongRef = d }
|
|
init(weakDelegate: Delegate, strongDelegate: Delegate) {
|
|
delegate = weakDelegate
|
|
strongRef = strongDelegate
|
|
}
|
|
}
|
|
|
|
func warningForDeadDelegate(container: Container) {
|
|
let delegate = Delegate()
|
|
container.delegate = delegate // expected-warning {{weak reference will always be nil because the referenced object is deallocated here}}
|
|
container.callDelegate()
|
|
}
|
|
|
|
func noWarningForStoredDelegate(container: Container) {
|
|
let delegate = Delegate()
|
|
container.strongRef = delegate
|
|
container.delegate = delegate
|
|
container.callDelegate()
|
|
}
|
|
|
|
func noWarningWithFixLifetime(container: Container) {
|
|
let delegate = Delegate()
|
|
defer { _fixLifetime(delegate) }
|
|
container.delegate = delegate
|
|
container.callDelegate()
|
|
}
|
|
|
|
func warningWithControlFlow(container: Container, _ b: Bool) {
|
|
let delegate = Delegate()
|
|
container.delegate = delegate // expected-warning {{weak reference will always be nil because the referenced object is deallocated here}}
|
|
if b {
|
|
container.callDelegate()
|
|
}
|
|
}
|
|
|
|
var globalClosure: (() -> ())?
|
|
|
|
func storeClosure(_ c: @escaping () -> ()) {
|
|
globalClosure = c
|
|
}
|
|
|
|
func warningForDeadClosureCapture() {
|
|
let k = Delegate()
|
|
storeClosure({ [weak k] in // expected-warning {{weak reference will always be nil because the referenced object is deallocated here}}
|
|
k!.foo()
|
|
})
|
|
}
|
|
|
|
func noWarningWithFixLifetime2() {
|
|
let k = Delegate()
|
|
defer { _fixLifetime(k) }
|
|
storeClosure({ [weak k] in
|
|
k!.foo()
|
|
})
|
|
}
|
|
|
|
func warningWithStoreWeakInCalledFunction() {
|
|
let d = Delegate()
|
|
let c = Container(weakDelegate: d, strongDelegate: Delegate()) // expected-warning {{weak reference will always be nil because the referenced object is deallocated here}}
|
|
c.callDelegate()
|
|
}
|
|
|
|
final class StrongContainer {
|
|
var k: Delegate
|
|
init(_ k: Delegate) { self.k = k }
|
|
func set(_ newk: Delegate) { k = newk }
|
|
func noset(_ newk: Delegate) { }
|
|
}
|
|
|
|
final class Testcl {
|
|
private weak var wk: Delegate?
|
|
|
|
func test_set(_ c: StrongContainer) {
|
|
let k = Delegate()
|
|
c.set(k)
|
|
wk = k // No warning here, because k is kept alive by c
|
|
}
|
|
|
|
func test_noset(_ c: StrongContainer) {
|
|
let k = Delegate()
|
|
c.noset(k)
|
|
wk = k // expected-warning {{weak reference will always be nil because the referenced object is deallocated here}}
|
|
}
|
|
}
|
|
|