Files
swift-mirror/test/SIL/memory_lifetime_failures.sil
Erik Eckstein 535a58e3fb SIL: assume a read-effect for unused indirect arguments
Even if an indirect argument is unused, pretend that the function reads from it.
If the unused argument is passed to another generic function and that function is specialized,
the argument may be re-abstracted and the specializer inserts a load from the indirect argument.
Therefore we must be prepared that unused indirect argument might get loaded from at some time.

Fixes a compiler crash
rdar://168623362
2026-01-23 15:58:23 +01:00

964 lines
34 KiB
Plaintext

// RUN: %target-sil-opt -disable-swift-verification -dont-abort-on-memory-lifetime-errors -o /dev/null %s 2>&1 | %FileCheck %s
// REQUIRES: asserts
// REQUIRES: swift_in_compiler
sil_stage canonical
import Builtin
import Swift
import SwiftShims
// A non-trivial type
class T {
init()
}
struct Inner {
var a: T
var b: T
}
struct Outer {
var x: T
var y: Inner
var z: T
}
struct Mixed {
var t: T
var i: Int
}
public struct InnerWrapper<T> {
@_hasStorage var _prop: T { get set }
public var prop: T
}
public struct GenWrapper<T> {
@_hasStorage var _prop: T { get set }
public var prop: T
@_hasStorage var _nestedProp: InnerWrapper<T> { get set }
public var nestedProp: InnerWrapper<T>
}
sil @use_owned : $@convention(thin) (@owned T) -> ()
sil @use_guaranteed : $@convention(thin) (@guaranteed T) -> ()
sil @get_owned : $@convention(thin) () -> @owned T
sil @use_T : $@convention(thin) <T> (@in_guaranteed T) -> ()
sil @mutate_T : $@convention(thin) <T> (@inout T) -> ()
// CHECK: SIL memory lifetime failure in @test_simple: indirect argument is not alive at function return
sil [ossa] @test_simple : $@convention(thin) (@inout T) -> @owned T {
bb0(%0 : $*T):
%2 = begin_access [read] [static] %0 : $*T
%3 = load [copy] %2 : $*T
end_access %2 : $*T
br bb1
bb1:
destroy_addr %0 : $*T
return %3 : $T
}
// CHECK: SIL memory lifetime failure in @test_loop: memory is initialized at function return but shouldn't
sil [ossa] @test_loop : $@convention(thin) (@in T) -> @owned T {
bb0(%0 : $*T):
%2 = begin_access [read] [static] %0 : $*T
%3 = load [copy] %2 : $*T
end_access %2 : $*T
br bb1
bb1:
cond_br undef, bb2, bb3
bb2:
br bb1
bb3:
return %3 : $T
}
// CHECK: SIL memory lifetime failure in @test_merge: lifetime mismatch in predecessors
sil [ossa] @test_merge : $@convention(thin) (@in_guaranteed T) -> () {
bb0(%0 : $*T):
%2 = alloc_stack $T
cond_br undef, bb1, bb2
bb1:
copy_addr %0 to [init] %2 : $*T
br bb3
bb2:
copy_addr %0 to [init] %2 : $*T
destroy_addr %2 : $*T
br bb3
bb3:
dealloc_stack %2 : $*T
%r = tuple ()
return %r : $()
}
// CHECK: SIL memory lifetime failure in @test_nesting: memory is initialized at function return but shouldn't
sil [ossa] @test_nesting : $@convention(thin) (@in Outer) -> () {
bb0(%0 : $*Outer):
%1 = struct_element_addr %0 : $*Outer, #Outer.x
%2 = struct_element_addr %0 : $*Outer, #Outer.y
destroy_addr %1 : $*T
destroy_addr %2 : $*Inner
%3 = tuple ()
return %3 : $()
}
sil @throwing_func : $@convention(thin) () -> (@out T, @error Error)
// CHECK: SIL memory lifetime failure in @test_try_apply_return: memory is initialized, but shouldn't be
sil [ossa] @test_try_apply_return : $@convention(thin) () -> ((), @error Error) {
bb0:
%0 = alloc_stack $T
%1 = function_ref @throwing_func : $@convention(thin) () -> (@out T, @error Error)
try_apply %1(%0) : $@convention(thin) () -> (@out T, @error Error), normal bb1, error bb2
bb1(%2 : $()):
dealloc_stack %0 : $*T
%3 = tuple ()
return %3 : $()
bb2(%4 : @owned $Error):
dealloc_stack %0 : $*T
throw %4 : $Error
}
// CHECK: SIL memory lifetime failure in @test_try_apply_throw: memory is not initialized, but should be
sil [ossa] @test_try_apply_throw : $@convention(thin) () -> ((), @error Error) {
bb0:
%0 = alloc_stack $T
%1 = function_ref @throwing_func : $@convention(thin) () -> (@out T, @error Error)
try_apply %1(%0) : $@convention(thin) () -> (@out T, @error Error), normal bb1, error bb2
bb1(%2 : $()):
destroy_addr %0 : $*T
dealloc_stack %0 : $*T
%3 = tuple ()
return %3 : $()
bb2(%4 : @owned $Error):
destroy_addr %0 : $*T
dealloc_stack %0 : $*T
throw %4 : $Error
}
// CHECK: SIL memory lifetime failure in @test_single_block: memory is initialized, but shouldn't be
sil [ossa] @test_single_block : $@convention(thin) (@owned T) -> () {
bb0(%0 : @owned $T):
%2 = alloc_stack $T
store %0 to [init] %2 : $*T
dealloc_stack %2 : $*T
%r = tuple ()
return %r : $()
}
// CHECK: SIL memory lifetime failure in @test_mixed: memory is not initialized, but should be
sil [ossa] @test_mixed : $@convention(thin) (@in Mixed, Int) -> Int {
bb0(%0 : $*Mixed, %1 : $Int):
%2 = struct_element_addr %0 : $*Mixed, #Mixed.i
store %1 to [trivial] %2 : $*Int
destroy_addr %0 : $*Mixed
%3 = load [trivial] %2 : $*Int
return %3 : $Int
}
// CHECK: SIL memory lifetime failure in @test_missing_store_to_trivial: memory is not initialized, but should be
sil [ossa] @test_missing_store_to_trivial : $@convention(thin) () -> Int {
bb0:
%1 = alloc_stack $Mixed
%2 = struct_element_addr %1 : $*Mixed, #Mixed.i
%3 = load [trivial] %2 : $*Int
dealloc_stack %1 : $*Mixed
return %3 : $Int
}
// CHECK: SIL memory lifetime failure in @test_load_after_dealloc: memory is not initialized, but should be
sil [ossa] @test_load_after_dealloc : $@convention(thin) (Int) -> Int {
bb0(%0 : $Int):
%1 = alloc_stack $Mixed
%2 = struct_element_addr %1 : $*Mixed, #Mixed.i
store %0 to [trivial] %2 : $*Int
dealloc_stack %1 : $*Mixed
%3 = load [trivial] %2 : $*Int
return %3 : $Int
}
// CHECK: SIL memory lifetime failure in @test_switch_enum_addr: memory is initialized at function return but shouldn't
sil [ossa] @test_switch_enum_addr : $@convention(thin) (@in Optional<T>) -> () {
bb0(%0 : $*Optional<T>):
switch_enum_addr %0 : $*Optional<T>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
bb1:
%2 = unchecked_take_enum_data_addr %0 : $*Optional<T>, #Optional.some!enumelt
br bb3
bb2:
br bb3
bb3:
%r = tuple ()
return %r : $()
}
// CHECK: SIL memory lifetime failure in @test_switch_enum: memory is initialized at function return but shouldn't
sil [ossa] @test_switch_enum : $@convention(thin) (@in Optional<T>) -> () {
bb0(%0 : $*Optional<T>):
%1 = load_borrow %0 : $*Optional<T>
switch_enum %1 : $Optional<T>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
bb1(%3 : @guaranteed $T):
end_borrow %1 : $Optional<T>
%2 = unchecked_take_enum_data_addr %0 : $*Optional<T>, #Optional.some!enumelt
br bb3
bb2:
end_borrow %1 : $Optional<T>
br bb3
bb3:
%r = tuple ()
return %r : $()
}
// CHECK: SIL memory lifetime failure in @test_init_enum: indirect argument is not alive at function return
sil [ossa] @test_init_enum : $@convention(thin) (@in_guaranteed T) -> @out Optional<T> {
bb0(%0 : $*Optional<T>, %1 : $*T):
cond_br undef, bb1, bb2
bb1:
inject_enum_addr %0 : $*Optional<T>, #Optional.none!enumelt
br bb3
bb2:
%5 = init_enum_data_addr %0 : $*Optional<T>, #Optional.some!enumelt
inject_enum_addr %0 : $*Optional<T>, #Optional.some!enumelt
br bb3
bb3:
%r = tuple ()
return %r : $()
}
// CHECK: SIL memory lifetime failure in @test_store_to_enum: memory is initialized, but shouldn't be
sil [ossa] @test_store_to_enum : $@convention(thin) (@owned T) -> () {
bb0(%0 : @owned $T):
%1 = alloc_stack $Optional<T>
%2 = enum $Optional<T>, #Optional.none!enumelt
store %2 to [trivial] %1 : $*Optional<T>
destroy_addr %1 : $*Optional<T>
%3 = enum $Optional<T>, #Optional.some!enumelt, %0 : $T
store %3 to [init] %1 : $*Optional<T>
dealloc_stack %1 : $*Optional<T>
%r = tuple ()
return %r : $()
}
// CHECK: SIL memory lifetime failure in @test_select_enum_addr: memory is not initialized, but should be
sil [ossa] @test_select_enum_addr : $@convention(thin) () -> Builtin.Int1 {
bb0:
%0 = alloc_stack $Optional<T>
%1 = integer_literal $Builtin.Int1, -1
%2 = integer_literal $Builtin.Int1, 0
%3 = select_enum_addr %0 : $*Optional<T>, case #Optional.some!enumelt: %1, case #Optional.none!enumelt: %2 : $Builtin.Int1
dealloc_stack %0 : $*Optional<T>
return %3 : $Builtin.Int1
}
sil [ossa] @closure : $@convention(thin) (@in_guaranteed T) -> ()
// CHECK: SIL memory lifetime failure in @test_non_escaping_closure: memory is initialized at function return but shouldn't
sil [ossa] @test_non_escaping_closure : $@convention(thin) (@in T) -> () {
bb0(%0 : $*T):
%func = function_ref @closure : $@convention(thin) (@in_guaranteed T) -> ()
%pa = partial_apply [callee_guaranteed] [on_stack] %func(%0) : $@convention(thin) (@in_guaranteed T) -> ()
destroy_value %pa : $@noescape @callee_guaranteed () -> ()
%res = tuple ()
return %res : $()
}
// CHECK: SIL memory lifetime failure in @test_escaping_closure: indirect argument is not alive at function return
sil [ossa] @test_escaping_closure : $@convention(thin) (@in_guaranteed T) -> () {
bb0(%0 : $*T):
%func = function_ref @closure : $@convention(thin) (@in_guaranteed T) -> ()
%pa = partial_apply %func(%0) : $@convention(thin) (@in_guaranteed T) -> ()
destroy_value %pa : $@callee_owned () -> ()
%res = tuple ()
return %res : $()
}
// CHECK: SIL memory lifetime failure in @test_non_escaping_closure_with_mark_dependence: memory is not initialized, but should be
sil [ossa] @test_non_escaping_closure_with_mark_dependence : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $T
%func = function_ref @closure : $@convention(thin) (@in_guaranteed T) -> ()
%pa = partial_apply [callee_guaranteed] [on_stack] %func(%0) : $@convention(thin) (@in_guaranteed T) -> ()
%pa1 = mark_dependence %pa on %0
destroy_value %pa1 : $@noescape @callee_guaranteed () -> ()
dealloc_stack %0
%res = tuple ()
return %res : $()
}
// CHECK: SIL memory lifetime failure in @test_store_borrow_destroy1: store-borrow location cannot be written
sil [ossa] @test_store_borrow_destroy1 : $@convention(thin) (@guaranteed T) -> () {
bb0(%0 : @guaranteed $T):
%s = alloc_stack $T
%sb = store_borrow %0 to %s : $*T
destroy_addr %sb : $*T
end_borrow %sb : $*T
dealloc_stack %s : $*T
%res = tuple ()
return %res : $()
}
// CHECK: SIL memory lifetime failure in @test_store_borrow_destroy2: store-borrow location cannot be written
sil [ossa] @test_store_borrow_destroy2 : $@convention(thin) (@guaranteed Inner) -> () {
bb0(%0 : @guaranteed $Inner):
%s = alloc_stack $Inner
%sb = store_borrow %0 to %s
%elem = struct_element_addr %sb, #Inner.a
destroy_addr %elem
end_borrow %sb
dealloc_stack %s
%res = tuple ()
return %res : $()
}
sil [ossa] @func_with_inout_param : $@convention(thin) (@inout T) -> ()
// T-CHECK: SIL memory lifetime failure in @test_store_borrow_inout: store-borrow location cannot be written
sil [ossa] @test_store_borrow_inout : $@convention(thin) (@guaranteed T) -> () {
bb0(%0 : @guaranteed $T):
%s = alloc_stack $T
%sb = store_borrow %0 to %s : $*T
%f = function_ref @func_with_inout_param : $@convention(thin) (@inout T) -> ()
%a = apply %f(%sb) : $@convention(thin) (@inout T) -> ()
end_borrow %sb : $*T
dealloc_stack %s : $*T
%res = tuple ()
return %res : $()
}
// CHECK: SIL memory lifetime failure in @test_store_borrow_store: store-borrow location cannot be written
sil [ossa] @test_store_borrow_store : $@convention(thin) (@guaranteed T, @owned T) -> () {
bb0(%0 : @guaranteed $T, %1 : @owned $T):
%s = alloc_stack $T
%sb = store_borrow %0 to %s : $*T
store %1 to [assign] %sb : $*T
end_borrow %sb : $*T
dealloc_stack %s : $*T
%res = tuple ()
return %res : $()
}
// CHECK: SIL memory lifetime failure in @test_store_borrow_load: store-borrow location cannot be written
sil [ossa] @test_store_borrow_load : $@convention(thin) (@guaranteed T) -> @owned T {
bb0(%0 : @guaranteed $T):
%s = alloc_stack $T
%sb = store_borrow %0 to %s : $*T
%res = load [take] %sb : $*T
end_borrow %sb : $*T
dealloc_stack %s : $*T
return %res : $T
}
// CHECK: SIL memory lifetime failure in @test_store_borrow_copy_src: store-borrow location cannot be written
sil [ossa] @test_store_borrow_copy_src : $@convention(thin) (@guaranteed T) -> @out T {
bb0(%0 : $*T, %1 : @guaranteed $T):
%s = alloc_stack $T
%sb = store_borrow %1 to %s : $*T
copy_addr [take] %sb to [init] %0 : $*T
end_borrow %sb : $*T
dealloc_stack %s : $*T
%res = tuple ()
return %res : $()
}
// CHECK: SIL memory lifetime failure in @test_store_borrow_copy_dst: store-borrow location cannot be written
sil [ossa] @test_store_borrow_copy_dst : $@convention(thin) (@in_guaranteed T, @guaranteed T) -> () {
bb0(%0 : $*T, %1 : @guaranteed $T):
%s = alloc_stack $T
%sb = store_borrow %1 to %s : $*T
copy_addr %0 to %sb : $*T
end_borrow %sb : $*T
dealloc_stack %s : $*T
%res = tuple ()
return %res : $()
}
// CHECK: SIL memory lifetime failure in @test_store_borrow_init_enum: store-borrow location cannot be written
sil [ossa] @test_store_borrow_init_enum : $@convention(thin) (@guaranteed Optional<T>) -> () {
bb0(%0 : @guaranteed $Optional<T>):
%s = alloc_stack $Optional<T>
%sb = store_borrow %0 to %s : $*Optional<T>
%ie = init_enum_data_addr %sb : $*Optional<T>, #Optional.some!enumelt
end_borrow %sb : $*Optional<T>
dealloc_stack %s : $*Optional<T>
%res = tuple ()
return %res : $()
}
sil [ossa] @test_store_borrow_take_enum : $@convention(thin) (@guaranteed Optional<T>) -> () {
bb0(%0 : @guaranteed $Optional<T>):
%s = alloc_stack $Optional<T>
%sb = store_borrow %0 to %s : $*Optional<T>
%ue = unchecked_take_enum_data_addr %sb : $*Optional<T>, #Optional.some!enumelt
end_borrow %sb : $*Optional<T>
dealloc_stack %s : $*Optional<T>
%res = tuple ()
return %res : $()
}
// CHECK: SIL memory lifetime failure in @test_store_borrow_addr_after_dealloc: memory is initialized, but shouldn't be
sil [ossa] @test_store_borrow_addr_after_dealloc : $@convention(thin) (@guaranteed Optional<T>) -> () {
bb0(%0 : @guaranteed $Optional<T>):
%s = alloc_stack $Optional<T>
%sb = store_borrow %0 to %s : $*Optional<T>
dealloc_stack %s : $*Optional<T>
end_borrow %sb : $*Optional<T>
%res = tuple ()
return %res : $()
}
// CHECK: SIL memory lifetime failure in @test_cast_br_take_always: memory is not initialized, but should be
sil [ossa] @test_cast_br_take_always : $@convention(thin) <U, V> (@in U) -> () {
bb0(%0 : $*U):
%s = alloc_stack $V
checked_cast_addr_br take_always U in %0 : $*U to V in %s : $*V, bb1, bb2
bb1:
destroy_addr %s : $*V
br bb3
bb2:
destroy_addr %0 : $*U
br bb3
bb3:
dealloc_stack %s : $*V
%res = tuple ()
return %res : $()
}
// CHECK: SIL memory lifetime failure in @test_cast_br_take_on_success: lifetime mismatch in predecessors
sil [ossa] @test_cast_br_take_on_success : $@convention(thin) <U, V> (@in U) -> () {
bb0(%0 : $*U):
%s = alloc_stack $V
checked_cast_addr_br take_on_success U in %0 : $*U to V in %s : $*V, bb1, bb2
bb1:
destroy_addr %s : $*V
br bb3
bb2:
br bb3
bb3:
dealloc_stack %s : $*V
%res = tuple ()
return %res : $()
}
// CHECK: SIL memory lifetime failure in @test_cast_br_copy_on_success: lifetime mismatch in predecessors
sil [ossa] @test_cast_br_copy_on_success : $@convention(thin) <U, V> (@in U) -> () {
bb0(%0 : $*U):
%s = alloc_stack $V
checked_cast_addr_br copy_on_success U in %0 : $*U to V in %s : $*V, bb1, bb2
bb1:
destroy_addr %s : $*V
br bb3
bb2:
destroy_addr %0 : $*U
br bb3
bb3:
dealloc_stack %s : $*V
%res = tuple ()
return %res : $()
}
// CHECK: SIL memory lifetime failure in @test_unconditional_checked_cast_1: memory is initialized, but shouldn't be
sil [ossa] @test_unconditional_checked_cast_1 : $@convention(thin) <U, V> (@in U) -> () {
bb0(%0 : $*U):
%s = alloc_stack $V
unconditional_checked_cast_addr U in %0 : $*U to V in %s : $*V
dealloc_stack %s : $*V
%5 = tuple ()
return %5 : $()
}
// CHECK: SIL memory lifetime failure in @test_unconditional_checked_cast_2: memory is not initialized, but should be
sil [ossa] @test_unconditional_checked_cast_2 : $@convention(thin) <U, V> (@in_guaranteed U) -> () {
bb0(%0 : $*U):
%u = alloc_stack $U
%s = alloc_stack $V
unconditional_checked_cast_addr U in %u : $*U to V in %s : $*V
destroy_addr %s : $*V
dealloc_stack %s : $*V
dealloc_stack %u : $*U
%5 = tuple ()
return %5 : $()
}
// CHECK: SIL memory lifetime failure in @test_unchecked_ref_cast_1: memory is initialized, but shouldn't be
sil [ossa] @test_unchecked_ref_cast_1 : $@convention(thin) <U : AnyObject, V : AnyObject> (@in U) -> () {
bb0(%0 : $*U):
%s = alloc_stack $V
unchecked_ref_cast_addr U in %0 : $*U to V in %s : $*V
dealloc_stack %s : $*V
%5 = tuple ()
return %5 : $()
}
// CHECK: SIL memory lifetime failure in @test_unchecked_ref_cast_2: memory is not initialized, but should be
sil [ossa] @test_unchecked_ref_cast_2 : $@convention(thin) <U : AnyObject, V : AnyObject> (@in_guaranteed U) -> () {
bb0(%0 : $*U):
%u = alloc_stack $U
%s = alloc_stack $V
unchecked_ref_cast_addr U in %u : $*U to V in %s : $*V
destroy_addr %s : $*V
dealloc_stack %s : $*V
dealloc_stack %u : $*U
%5 = tuple ()
return %5 : $()
}
protocol P {}
// CHECK: SIL memory lifetime failure in @test_init_existential: memory is not initialized, but should be
sil [ossa] @test_init_existential : $@convention(thin) <U: P> (@in_guaranteed U) -> () {
bb0(%0 : $*U):
%s = alloc_stack $P
%i = init_existential_addr %s : $*P, $U
destroy_addr %s : $*P
dealloc_stack %s : $*P
%5 = tuple ()
return %5 : $()
}
// CHECK: SIL memory lifetime failure in @test_open_existential: memory is not initialized, but should be
sil [ossa] @test_open_existential : $@convention(thin) <U: P> (@in_guaranteed U) -> () {
bb0(%0 : $*U):
%s = alloc_stack $P
%o = open_existential_addr immutable_access %s : $*P to $*@opened("5B62392E-7C62-11EB-BF90-D0817AD9985D", P) Self
%s2 = alloc_stack $@opened("5B62392E-7C62-11EB-BF90-D0817AD9985D", P) Self
copy_addr %o to [init] %s2 : $*@opened("5B62392E-7C62-11EB-BF90-D0817AD9985D", P) Self
destroy_addr %s2 : $*@opened("5B62392E-7C62-11EB-BF90-D0817AD9985D", P) Self
dealloc_stack %s2 : $*@opened("5B62392E-7C62-11EB-BF90-D0817AD9985D", P) Self
destroy_addr %s : $*P
dealloc_stack %s : $*P
%5 = tuple ()
return %5 : $()
}
// CHECK: SIL memory lifetime failure in @test_existential_metatype: memory is not initialized, but should be
sil [ossa] @test_existential_metatype : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $P
%714 = existential_metatype $@thick P.Type, %0 : $*P
dealloc_stack %0 : $*P
%5 = tuple ()
return %5 : $()
}
// CHECK: SIL memory lifetime failure in @test_value_metatype: memory is not initialized, but should be
sil [ossa] @test_value_metatype : $@convention(thin) <U> (@in_guaranteed U) -> () {
bb0(%0 : $*U):
%1 = alloc_stack $U
%2 = value_metatype $@thick U.Type, %1 : $*U
dealloc_stack %1 : $*U
%5 = tuple ()
return %5 : $()
}
// CHECK: SIL memory lifetime failure in @test_is_unique: memory is not initialized, but should be
sil [ossa] @test_is_unique : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $T
%1 = is_unique %0 : $*T
dealloc_stack %0 : $*T
%5 = tuple ()
return %5 : $()
}
// CHECK: SIL memory lifetime failure in @test_fix_lifetime: memory is not initialized, but should be
sil [ossa] @test_fix_lifetime : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $T
fix_lifetime %0 : $*T
dealloc_stack %0 : $*T
%5 = tuple ()
return %5 : $()
}
sil @modify_bool : $@convention(thin) (@inout_aliasable Bool) -> ()
// CHECK: SIL memory lifetime failure in @test_trivial_alloc_stack: memory is not initialized, but should be
sil [ossa] @test_trivial_alloc_stack : $@convention(thin) (Bool) -> () {
bb0(%0 : $Bool):
%1 = alloc_stack $Bool
store %0 to [trivial] %1 : $*Bool
dealloc_stack %1 : $*Bool
%8 = function_ref @modify_bool : $@convention(thin) (@inout_aliasable Bool) -> ()
%9 = apply %8(%1) : $@convention(thin) (@inout_aliasable Bool) -> ()
%10 = tuple ()
return %10 : $()
}
// MemoryLifetimeVerifier does not detect an error here due to reborrows
sil [ossa] @test_load_borrow1 : $@convention(thin) (@in Optional<T>) -> () {
bb0(%0 : $*Optional<T>):
destroy_addr %0 : $*Optional<T>
%1 = load_borrow %0 : $*Optional<T>
br bb1(%1 : $Optional<T>)
bb1(%3 : @guaranteed $Optional<T>):
end_borrow %3 : $Optional<T>
br bb2
bb2:
%r = tuple ()
return %r : $()
}
// CHECK: SIL memory lifetime failure in @test_load_borrow2: memory is not initialized, but should be
sil [ossa] @test_load_borrow2 : $@convention(thin) (@in Optional<T>) -> () {
bb0(%0 : $*Optional<T>):
destroy_addr %0 : $*Optional<T>
%1 = load_borrow %0 : $*Optional<T>
end_borrow %1 : $Optional<T>
br bb1
bb1:
%r = tuple ()
return %r : $()
}
enum Result<T1, T2>{
case success(T1)
case failure(T2)
}
sil @try_get_error : $@convention(thin) () -> @error Error
// CHECK: SIL memory lifetime failure in @test_init_enum_trivial_case: memory is not initialized, but should be
sil [ossa] @test_init_enum_trivial_case : $@convention(thin) () -> @error Error {
bb0:
%0 = alloc_stack $Result<Int, Error>
%1 = function_ref @try_get_error : $@convention(thin) () -> @error Error
try_apply %1() : $@convention(thin) () -> @error Error, normal bb1, error bb2
bb1(%3 : $()):
inject_enum_addr %0 : $*Result<Int, Error>, #Result.success!enumelt
br bb3
bb2(%7 : @owned $Error):
%8 = init_enum_data_addr %0 : $*Result<Int, Error>, #Result.failure!enumelt
store %7 to [init] %8 : $*Error
inject_enum_addr %0 : $*Result<Int, Error>, #Result.failure!enumelt
br bb3
bb3:
%12 = load [take] %0 : $*Result<Int, Error>
destroy_value %12 : $Result<Int, Error>
dealloc_stack %0 : $*Result<Int, Error>
%15 = tuple ()
return %15 : $()
}
// CHECK: SIL memory lifetime failure in @test_double_enum_destroy: memory is not initialized, but should be
sil [ossa] @test_double_enum_destroy : $@convention(thin) (@in Optional<String>) -> () {
bb0(%0 : $*Optional<String>):
%l = load_borrow %0 : $*Optional<String>
switch_enum %l : $Optional<String>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
bb1(%a : @guaranteed $String):
end_borrow %l : $Optional<String>
%2 = load [take] %0 : $*Optional<String>
destroy_value %2 : $Optional<String>
br bb3
bb2:
end_borrow %l : $Optional<String>
%3 = load [take] %0 : $*Optional<String>
destroy_value %3 : $Optional<String>
%4 = load [take] %0 : $*Optional<String>
destroy_value %4 : $Optional<String>
br bb3
bb3:
%r = tuple ()
return %r : $()
}
// CHECK: SIL memory lifetime failure in @test_destroy_enum_before_return: indirect argument is not alive at function return
sil [ossa] @test_destroy_enum_before_return : $@convention(thin) () -> @out Optional<String> {
bb0(%0 : $*Optional<String>):
%1 = enum $Optional<String>, #Optional.none!enumelt
store %1 to [trivial] %0 : $*Optional<String>
destroy_addr %0 : $*Optional<String>
%r = tuple ()
return %r : $()
}
// CHECK: SIL memory lifetime failure in @begin_apply_in_no_destroy: memory is initialized, but shouldn't be
sil [ossa] @begin_apply_in_no_destroy : $@convention(thin) () -> () {
entry:
(%instance, %token) = begin_apply undef<Inner>() : $@yield_once @convention(thin) <U> () -> @yields @in U
end_apply %token as $()
%retval = tuple ()
return %retval : $()
}
// CHECK: SIL memory lifetime failure in @begin_apply_in_use_after_end_apply: memory is initialized, but shouldn't be
sil [ossa] @begin_apply_in_use_after_end_apply : $@convention(thin) () -> () {
entry:
(%instance, %token) = begin_apply undef<Inner>() : $@yield_once @convention(thin) <U> () -> @yields @in U
end_apply %token as $()
apply undef<Inner>(%instance) : $@convention(thin) <U> (@in U) -> ()
%retval = tuple ()
return %retval : $()
}
// CHECK: SIL memory lifetime failure in @begin_apply_in_constant_no_destroy: memory is initialized, but shouldn't be
sil [ossa] @begin_apply_in_constant_no_destroy : $@convention(thin) () -> () {
entry:
(%instance, %token) = begin_apply undef<Inner>() : $@yield_once @convention(thin) <U> () -> @yields @in_constant U
end_apply %token as $()
%retval = tuple ()
return %retval : $()
}
// CHECK: SIL memory lifetime failure in @begin_apply_in_constant_use_after_end_apply: memory is initialized, but shouldn't be
sil [ossa] @begin_apply_in_constant_use_after_end_apply : $@convention(thin) () -> () {
entry:
(%instance, %token) = begin_apply undef<Inner>() : $@yield_once @convention(thin) <U> () -> @yields @in_constant U
end_apply %token as $()
apply undef<Inner>(%instance) : $@convention(thin) <U> (@in_constant U) -> ()
%retval = tuple ()
return %retval : $()
}
// CHECK: SIL memory lifetime failure in @begin_apply_in_guaranteed_destroy: memory is not initialized, but should be
sil [ossa] @begin_apply_in_guaranteed_destroy : $@convention(thin) () -> () {
entry:
(%instance, %token) = begin_apply undef<Inner>() : $@yield_once @convention(thin) <U> () -> @yields @in_guaranteed U
destroy_addr %instance : $*Inner
end_apply %token as $()
%retval = tuple ()
return %retval : $()
}
// CHECK: SIL memory lifetime failure in @begin_apply_in_guaranteed_use_after_end_apply: memory is not initialized, but should be
sil [ossa] @begin_apply_in_guaranteed_use_after_end_apply : $@convention(thin) () -> () {
entry:
(%instance, %token) = begin_apply undef<Inner>() : $@yield_once @convention(thin) <U> () -> @yields @in_guaranteed U
end_apply %token as $()
apply undef<Inner>(%instance) : $@convention(thin) <U> (@in_guaranteed U) -> ()
%retval = tuple ()
return %retval : $()
}
// CHECK: SIL memory lifetime failure in @begin_apply_inout_destroy: memory is not initialized, but should be
sil [ossa] @begin_apply_inout_destroy : $@convention(thin) () -> () {
entry:
(%instance, %token) = begin_apply undef<Inner>() : $@yield_once @convention(thin) <U> () -> @yields @inout U
destroy_addr %instance : $*Inner
end_apply %token as $()
%retval = tuple ()
return %retval : $()
}
// CHECK: SIL memory lifetime failure in @begin_apply_inout_use_after_end_apply: memory is not initialized, but should be
sil [ossa] @begin_apply_inout_use_after_end_apply : $@convention(thin) () -> () {
entry:
(%instance, %token) = begin_apply undef<Inner>() : $@yield_once @convention(thin) <U> () -> @yields @inout U
end_apply %token as $()
apply undef<Inner>(%instance) : $@convention(thin) <U> (@inout U) -> ()
%retval = tuple ()
return %retval : $()
}
// CHECK: SIL memory lifetime failure in @begin_apply_inout_aliasable_destroy: memory is not initialized, but should be
sil [ossa] @begin_apply_inout_aliasable_destroy : $@convention(thin) () -> () {
entry:
(%instance, %token) = begin_apply undef<Inner>() : $@yield_once @convention(thin) <U> () -> @yields @inout_aliasable U
destroy_addr %instance : $*Inner
end_apply %token as $()
%retval = tuple ()
return %retval : $()
}
// CHECK: SIL memory lifetime failure in @begin_apply_inout_aliasable_use_after_end_apply: memory is not initialized, but should be
sil [ossa] @begin_apply_inout_aliasable_use_after_end_apply : $@convention(thin) () -> () {
entry:
(%instance, %token) = begin_apply undef<Inner>() : $@yield_once @convention(thin) <U> () -> @yields @inout_aliasable U
end_apply %token as $()
apply undef<Inner>(%instance) : $@convention(thin) <U> (@inout_aliasable U) -> ()
%retval = tuple ()
return %retval : $()
}
// CHECK: SIL memory lifetime failure in @begin_apply_inout_destroy: memory is not initialized, but should be
sil [ossa] @begin_apply_inout_no_destroy : $@convention(thin) () -> () {
entry:
(%instance, %token) = begin_apply undef<Inner>() : $@yield_once @convention(thin) <U> () -> @yields @inout U
end_apply %token as $()
%retval = tuple ()
return %retval : $()
}
// CHECK: SIL memory lifetime failure in @begin_apply_inout_aliasable_destroy: memory is not initialized, but should be
sil [ossa] @begin_apply_inout_aliasable_no_destroy : $@convention(thin) () -> () {
entry:
(%instance, %token) = begin_apply undef<Inner>() : $@yield_once @convention(thin) <U> () -> @yields @inout_aliasable U
end_apply %token as $()
%retval = tuple ()
return %retval : $()
}
sil @read_inner_b : $@convention(thin) (@in_guaranteed Inner) -> () {
[%0: read s0]
}
// CHECK: SIL memory lifetime failure in @test_partial_read_in_argument: memory is not initialized, but should be
sil [ossa] @test_partial_read_in_argument : $@convention(thin) (@in Inner) -> () {
bb0(%0: $*Inner):
%1 = struct_element_addr %0 : $*Inner, #Inner.a
destroy_addr %1 : $*T
%3 = function_ref @read_inner_b : $@convention(thin) (@in_guaranteed Inner) -> ()
%4 = apply %3(%0) : $@convention(thin) (@in_guaranteed Inner) -> ()
%5 = struct_element_addr %0 : $*Inner, #Inner.b
destroy_addr %5 : $*T
%r = tuple ()
return %r : $()
}
// CHECK: SIL memory lifetime failure in @mark_dependence_uninit_base: memory is not initialized, but should be
sil [ossa] @mark_dependence_uninit_base : $@convention(thin) (@owned T, @owned Inner) -> @owned Inner {
bb0(%0 : @owned $T, %1 : @owned $Inner):
%2 = alloc_stack $T
store %0 to [init] %2
%4 = alloc_stack $Inner
store %1 to [init] %4
destroy_addr %2
%6 = mark_dependence %4 on %2
%7 = begin_access [read] [dynamic] %6
%8 = load [take] %7
end_access %7
dealloc_stack %4
dealloc_stack %2
return %8
}
sil @initfn : $@convention(thin) () -> @out T
// CHECK: SIL memory lifetime failure in @inject_enum_case: memory is not initialized, but should be
sil [ossa] @inject_enum_case : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $Optional<T>
%1 = function_ref @initfn : $@convention(thin) () -> @out T
%2 = init_enum_data_addr %0, #Optional.some!enumelt
%3 = apply %1(%2) : $@convention(thin) () -> @out T
destroy_addr %0
inject_enum_addr %0, #Optional.some!enumelt
dealloc_stack %0
%10 = tuple ()
return %10
}
// CHECK: SIL memory lifetime failure in @mark_dependence_addr_uninit_base: memory is not initialized, but should be
sil [ossa] @mark_dependence_addr_uninit_base : $@convention(thin) (@owned T, @owned Inner) -> @owned Inner {
bb0(%0 : @owned $T, %1 : @owned $Inner):
%2 = alloc_stack $T
store %0 to [init] %2
%4 = alloc_stack $Inner
store %1 to [init] %4
destroy_addr %2
mark_dependence %4 on %2
%7 = begin_access [read] [dynamic] %4
%8 = load [take] %7
end_access %7
dealloc_stack %4
dealloc_stack %2
return %8
}
sil [ossa] @borrow_addressonly_prop : $@convention(method) <T> (@in_guaranteed GenWrapper<T>) -> @guaranteed_address T {
bb0(%0 : $*GenWrapper<T>):
%2 = struct_element_addr %0, #GenWrapper._prop
return %2
}
sil [ossa] @mutate_addressonly_prop : $@convention(method) <T> (@inout GenWrapper<T>) -> @inout T {
bb0(%0 : $*GenWrapper<T>):
%2 = struct_element_addr %0, #GenWrapper._prop
return %2
}
sil [ossa] @borrow_addressonly_nested_prop : $@convention(method) <T> (@in_guaranteed GenWrapper<T>) -> @guaranteed_address InnerWrapper<T> {
bb0(%0 : $*GenWrapper<T>):
%2 = struct_element_addr %0, #GenWrapper._nestedProp
return %2
}
sil [ossa] @mutate_addressonly_nested_prop : $@convention(method) <T> (@inout GenWrapper<T>) -> @inout InnerWrapper<T> {
bb0(%0 : $*GenWrapper<T>):
%2 = struct_element_addr %0, #GenWrapper._nestedProp
return %2
}
// CHECK: SIL memory lifetime failure in @test_use_after_free_address_only1: memory is not initialized, but should be
// CHECK: memory location: %2 = apply %1<T>(%0) : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_address τ_0_0
// CHECK: at instruction: %5 = apply %3<T>(%2) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
sil [ossa] @test_use_after_free_address_only1 : $@convention(thin) <T> (@in GenWrapper<T>) -> () {
bb0(%0 : $*GenWrapper<T>):
%1 = function_ref @borrow_addressonly_prop : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_address τ_0_0
%2 = apply %1<T>(%0) : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_address τ_0_0
%3 = function_ref @use_T : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
destroy_addr %0
%5 = apply %3<T>(%2) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
%6 = tuple ()
return %6
}
// CHECK: SIL memory lifetime failure in @test_use_after_free_address_only2: memory is not initialized, but should be
// CHECK: memory location: %2 = apply %1<T>(%0) : $@convention(method) <τ_0_0> (@inout GenWrapper<τ_0_0>) -> @inout τ_0_0
// CHECK: at instruction: %5 = apply %3<T>(%2) : $@convention(thin) <τ_0_0> (@inout τ_0_0) -> ()
sil [ossa] @test_use_after_free_address_only2 : $@convention(thin) <T> (@in GenWrapper<T>) -> () {
bb0(%0 : $*GenWrapper<T>):
%1 = function_ref @mutate_addressonly_prop : $@convention(method) <τ_0_0> (@inout GenWrapper<τ_0_0>) -> @inout τ_0_0
%2 = apply %1<T>(%0) : $@convention(method) <τ_0_0> (@inout GenWrapper<τ_0_0>) -> @inout τ_0_0
%3 = function_ref @mutate_T : $@convention(thin) <τ_0_0> (@inout τ_0_0) -> ()
destroy_addr %0
%5 = apply %3<T>(%2) : $@convention(thin) <τ_0_0> (@inout τ_0_0) -> ()
%6 = tuple ()
return %6
}
// TODO-CHECK: SIL memory lifetime failure in @test_guaranteed_address_consume: store-borrow location cannot be written
// TODO-CHECK: memory location: %2 = apply %1<T>(%0) : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_address τ_0_0
// TODO-CHECK: at instruction: destroy_addr %2 : $*T
sil [ossa] @test_guaranteed_address_consume : $@convention(thin) <T> (@in GenWrapper<T>) -> () {
bb0(%0 : $*GenWrapper<T>):
%1 = function_ref @borrow_addressonly_prop : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_address τ_0_0
%2 = apply %1<T>(%0) : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_address τ_0_0
destroy_addr %2
%4 = tuple ()
return %4
}
// TODO-CHECK: SIL memory lifetime failure in @test_guaranteed_nested_address_consume: store-borrow location cannot be written
// TODO-CHECK: memory location: %3 = struct_element_addr %2 : $*InnerWrapper<T>, #InnerWrapper._prop
// TODO-CHECK: at instruction: destroy_addr %3 : $*T
sil [ossa] @test_guaranteed_nested_address_consume : $@convention(thin) <T> (@in GenWrapper<T>) -> () {
bb0(%0 : $*GenWrapper<T>):
%1 = function_ref @borrow_addressonly_nested_prop : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_address InnerWrapper<τ_0_0>
%2 = apply %1<T>(%0) : $@convention(method) <τ_0_0> (@in_guaranteed GenWrapper<τ_0_0>) -> @guaranteed_address InnerWrapper<τ_0_0>
%3 = struct_element_addr %2, #InnerWrapper._prop
destroy_addr %3
%4 = tuple ()
return %4
}