Improves OSSALifetimeCompletion to handle trivial variables when running from
SILGenCleanup. This only affects lifetime dependence diagnostics.
For the purpose of lifetime diagnostics, trivial local variables are only valid
within their lexical scope. Sadly, SILGen only know how to insert cleanup code
on normal function exits. SILGenCleanup relies on lifetime completion to fix
lifetimes on dead end paths.
%var = move_value [var_decl]
try_apply %f() : $..., normal bb1, error error
error:
extend_lifetime %var <=== insert this
unreachable
This allows Span to depend on local unsafe pointers AND be used within
throwing closures:
_ = a.withUnsafeBufferPointer {
let buffer = $0
let view = Span(_unsafeElements: buffer)
return view.withUnsafeBufferPointer(\.count)
}
Complete scopes of scoped addresses (introduced by `store_borrow` and
`begin_access`) in dead end blocks via
`ScopedAddressValue::computeTransitiveLiveness`.
rdar://141037060
Now that the two known issues which resulted in invalid SIL being
provided to lifetime completion have been addressed, tighten up the
completion done on the availability boundary not to allow leaks.
The new boundary allows for invalid OSSA where values are not consumed
on paths leading to blocks that exit the function normally. In such
cases, the value is allowed to continue leaking as before.
Not every block in a region which begins with the non-lifetime-ending
boundary of a value and ending with unreachable-terminated blocks has
the value available. If the unreachable-terminated blocks in this
boundary are not available, it is incorrect to insert destroys of the
value in them: it is an overconsume on some paths. Previously,
however, destroys were simply being inserted at the unreachable.
Here, this is fixed by finding the boundary of availability within that
region and inserting destroys before the terminators of the blocks on
that boundary.
rdar://116255254
Extracted the new visitUnreachableLifetimeEnds static member of
OSSALifetimeCompletion from the preexisting
endLifetimeAtUnreachableBlocks which now calls through the former.
Add local lifetime-ending operations to any owned or borrowed value.
This puts a single value into valid OSSA form so that linear lifetime
checking will pass.
Also adds UnreachableLifetimeCompletion which fixes OSSA after
converting a code path to unreachable (e.g. DiagnoseUnreachable and MandatoryInlining).