Files
swift-mirror/test/SIL/OwnershipVerifier/arguments.sil
Erik Eckstein 7bf0010c92 SIL: remove computeIsReborrow
This API computes the re-borrow flags for guaranteed phis based on the presence of forwarding instructions in the incoming values.
This is not correct in all cases, because optimizations can optimize away forwarding instructions.

Fixes a verifier crash: rdar://139280579
2024-11-12 09:26:59 +01:00

752 lines
26 KiB
Plaintext

// RUN: %target-sil-opt -module-name Swift -disable-swift-verification -sil-ownership-verifier-enable-testing -ownership-verifier-textual-error-dumper -enable-sil-verify-all=0 %s -o /dev/null 2>&1 | %FileCheck %s
// REQUIRES: asserts
// This is a test that verifies ownership behavior around arguments that should
// be flagged as failures.
sil_stage canonical
import Builtin
//////////////////
// Declarations //
//////////////////
struct NativeObjectPair {
var obj1 : Builtin.NativeObject
var obj2 : Builtin.NativeObject
}
enum FakeOptional<T> {
case none
case some(T)
}
///////////
// Tests //
///////////
// CHECK-NOT: Function: 'no_end_borrow_error1'
sil [ossa] @no_end_borrow_error1 : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
br bb1(%0 : $Builtin.NativeObject)
bb1(%1 : @guaranteed $Builtin.NativeObject):
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'no_end_borrow_error2'
// CHECK: Non trivial values, non address values, and non guaranteed function args must have at least one lifetime ending use?!
// CHECK: Value: %1 = begin_borrow %0 : $Builtin.NativeObject
// CHECK-LABEL: Error#: 0. End Error in Function: 'no_end_borrow_error2'
//
// CHECK-NOT: Error#: {{[0-9][0-9]*}}. End Error in Function: 'no_end_borrow_error2'
sil [ossa] @no_end_borrow_error2 : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
br bb1(%1 : $Builtin.NativeObject)
bb1(%2 : @guaranteed $Builtin.NativeObject):
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'leak_along_path'
// CHECK: Error! Found a leak due to a consuming post-dominance failure!
// CHECK: Value: %3 = argument of bb1 : $Builtin.NativeObject
// CHECK: Post Dominating Failure Blocks:
// CHECK: bb3
// CHECK: Error#: 0. End Error in Function: 'leak_along_path'
//
// CHECK-NOT: Error#: {{[0-9][0-9]*}}. End Error in Function: 'leak_along_path'
sil [ossa] @leak_along_path : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
br bb1(%1 : $Builtin.NativeObject)
bb1(%2 : @guaranteed $Builtin.NativeObject):
cond_br undef, bb2, bb3
bb2:
end_borrow %2 : $Builtin.NativeObject
br bb4
bb3:
br bb4
bb4:
%9999 = tuple()
return %9999 : $()
}
// Make sure that we only flag the subargument leak and not the parent
// argument. Also check for over consuming due to phi nodes.
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'leak_along_subarg_path'
// CHECK: Error! Found a leak due to a consuming post-dominance failure!
// CHECK: Value: %7 = argument of bb3 : $Builtin.NativeObject
// CHECK: Post Dominating Failure Blocks:
// CHECK: bb6
// CHECK: Error#: 0. End Error in Function: 'leak_along_subarg_path'
//
// CHECK-NOT: Error#: {{[0-9][0-9]*}}. End Error in Function: 'leak_along_subarg_path'
sil [ossa] @leak_along_subarg_path : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
br bb1(%1 : $Builtin.NativeObject)
bb1(%2 : @guaranteed $Builtin.NativeObject):
cond_br undef, bb2, bb5
bb2:
%2a = begin_borrow %2 : $Builtin.NativeObject
br bb3(%2a : $Builtin.NativeObject)
bb3(%3 : @guaranteed $Builtin.NativeObject):
cond_br undef, bb4, bb6
bb4:
end_borrow %3 : $Builtin.NativeObject
br bb7
bb5:
br bb7
bb6:
br bb7
bb7:
end_borrow %2 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-NOT: Function: 'good_order_1'
sil [ossa] @good_order_1 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
bb0(%0 : @owned $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
cond_br undef, bb1, bb5
bb1:
br bb2(%1 : $Builtin.NativeObject)
bb2(%2 : @guaranteed $Builtin.NativeObject):
end_borrow %2 : $Builtin.NativeObject
cond_br undef, bb3, bb6
bb3:
br bb4
bb4:
destroy_value %0 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
bb5:
end_borrow %1 : $Builtin.NativeObject
br bb4
bb6:
br bb4
}
// CHECK-NOT: Function: 'good_order_2'
sil [ossa] @good_order_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
bb0(%0 : @owned $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
cond_br undef, bb1, bb5
bb1:
%1a = begin_borrow %1 : $Builtin.NativeObject
br bb2(%1a : $Builtin.NativeObject)
bb2(%2 : @guaranteed $Builtin.NativeObject):
end_borrow %2 : $Builtin.NativeObject
end_borrow %1 : $Builtin.NativeObject
cond_br undef, bb3, bb6
bb3:
br bb4
bb4:
destroy_value %0 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
bb5:
end_borrow %1 : $Builtin.NativeObject
br bb4
bb6:
br bb4
}
// Make sure that we only flag the end_borrow "use after free" in bb2.
//
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'bad_order'
// CHECK: Found outside of lifetime use?!
// CHECK: Value: %1 = begin_borrow %0 : $Builtin.NativeObject
// CHECK: Consuming User: end_borrow %1 : $Builtin.NativeObject
// CHECK: Non Consuming User: end_borrow %5 : $Builtin.NativeObject
// CHECK: Block: bb2
// CHECK: Error#: 0. End Error in Function: 'bad_order'
//
// CHECK-NOT: Error#: {{[0-9][0-9]*}}. End Error in Function: 'bad_order'
sil [ossa] @bad_order : $@convention(thin) (@owned Builtin.NativeObject) -> () {
bb0(%0 : @owned $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
cond_br undef, bb1, bb5
bb1:
%1a = begin_borrow %1 : $Builtin.NativeObject
br bb2(%1a : $Builtin.NativeObject)
bb2(%2 : @guaranteed $Builtin.NativeObject):
end_borrow %1 : $Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
cond_br undef, bb3, bb6
bb3:
br bb4
bb4:
destroy_value %0 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
bb5:
end_borrow %1 : $Builtin.NativeObject
br bb4
bb6:
br bb4
}
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'bad_order_add_a_level'
// CHECK: Found outside of lifetime use?!
// CHECK: Value: %1 = begin_borrow %0 : $Builtin.NativeObject // users: %19, %14, %6, %3
// CHECK: Consuming User: end_borrow %1 : $Builtin.NativeObject // id: %6
// CHECK: Non Consuming User: end_borrow %5 : $Builtin.NativeObject // id: %7
// CHECK: Block: bb2
// CHECK-LABEL: Error#: 0. End Error in Function: 'bad_order_add_a_level'
// CHECK-LABEL: Error#: 1. Begin Error in Function: 'bad_order_add_a_level'
// CHECK: Found over consume?!
// CHECK: Value: %1 = begin_borrow %0 : $Builtin.NativeObject // users: %19, %14, %6, %3
// CHECK: User: end_borrow %1 : $Builtin.NativeObject // id: %14
// CHECK: Block: bb2
// CHECK: Consuming Users:
// CHECK: end_borrow %1 : $Builtin.NativeObject // id: %19
// CHECK: end_borrow %1 : $Builtin.NativeObject // id: %14
// CHECK: end_borrow %1 : $Builtin.NativeObject // id: %6
// CHECK: Error#: 1. End Error in Function: 'bad_order_add_a_level'
//
// This block is reported as leaking block since given our partial-cfg:
//
// /---> BB3
// BB1 -> BB2 ------> BB5
//
// we create the borrow at BB1 and end its lifetime at BB2 and BB5. This causes
// us to walk up, identify they double consume at BB2 from BB5. Since we skipped
// BB3 that is identified as a leaking block appropriately.
//
// CHECK-LABEL: Error#: 2. Begin Error in Function: 'bad_order_add_a_level'
// CHECK: Error! Found a leak due to a consuming post-dominance failure!
// CHECK: Value: %1 = begin_borrow %0 : $Builtin.NativeObject // users: %19, %14, %6, %3
// CHECK: Post Dominating Failure Blocks:
// CHECK: bb3
// CHECK-LABEL: Error#: 2. End Error in Function: 'bad_order_add_a_level'
//
// CHECK-LABEL: Error#: 3. Begin Error in Function: 'bad_order_add_a_level'
// CHECK: Found outside of lifetime use!
// CHECK: Value: %1 = begin_borrow %0 : $Builtin.NativeObject // users: %19, %14, %6, %3
// CHECK: User: %9 = begin_borrow %5 : $Builtin.NativeObject // user: %10
// CHECK: Block: bb3
// CHECK-LABEL: Error#: 3. End Error in Function: 'bad_order_add_a_level'
//
// CHECK-LABEL: Error#: 6. Begin Error in Function: 'bad_order_add_a_level'
// CHECK: Found over consume?!
// CHECK: Value: %5 = argument of bb2 : $Builtin.NativeObject // users: %13, %9, %7
// CHECK: User: end_borrow %5 : $Builtin.NativeObject // id: %13
// CHECK: Block: bb2
// CHECK: Consuming Users:
// CHECK: end_borrow %5 : $Builtin.NativeObject
// CHECK: end_borrow %5 : $Builtin.NativeObject
// CHECK: Error#: 6. End Error in Function: 'bad_order_add_a_level'
//
// CHECK-LABEL: Error#: 7. Begin Error in Function: 'bad_order_add_a_level'
// CHECK: Error! Found a leak due to a consuming post-dominance failure!
// CHECK: Value: %5 = argument of bb2 : $Builtin.NativeObject // users: %13, %9, %7
// CHECK: Post Dominating Failure Blocks:
// CHECK: bb3
// CHECK: Error#: 7. End Error in Function: 'bad_order_add_a_level'
//
// CHECK-LABEL: Error#: 9. Begin Error in Function: 'bad_order_add_a_level'
// CHECK: Found outside of lifetime use!
// CHECK: Value: %5 = argument of bb2 : $Builtin.NativeObject // users: %13, %9, %7
// CHECK: User: %9 = begin_borrow %5 : $Builtin.NativeObject
// CHECK: Block: bb3
// CHECK-LABEL: Error#: 9. End Error in Function: 'bad_order_add_a_level'
//
// CHECK-LABEL: Error#: 10. Begin Error in Function: 'bad_order_add_a_level'
// CHECK: Non trivial values, non address values, and non guaranteed function args must have at least one lifetime ending use?!
// CHECK: Value: %9 = begin_borrow %5 : $Builtin.NativeObject
// CHECK: Error#: 10. End Error in Function: 'bad_order_add_a_level'
sil [ossa] @bad_order_add_a_level : $@convention(thin) (@owned Builtin.NativeObject) -> () {
bb0(%0 : @owned $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
cond_br undef, bb1, bb7
bb1:
%2 = begin_borrow %1 : $Builtin.NativeObject
br bb2(%2 : $Builtin.NativeObject)
bb2(%4 : @guaranteed $Builtin.NativeObject):
end_borrow %1 : $Builtin.NativeObject
end_borrow %4 : $Builtin.NativeObject
cond_br undef, bb3, bb5
bb3:
%4a = begin_borrow %4 : $Builtin.NativeObject
br bb4(%4a : $Builtin.NativeObject)
bb4(%9 : @guaranteed $Builtin.NativeObject):
br bb6
bb5:
end_borrow %4 : $Builtin.NativeObject
end_borrow %1 : $Builtin.NativeObject
br bb6
bb6:
destroy_value %0 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
bb7:
end_borrow %1 : $Builtin.NativeObject
br bb6
}
// Check that we only add an argument to the use set of its parent argument.
// This ensures that when checking we do not waste a bunch of compile time by
// propagating up end_borrows through many arguments. Also make sure that we do
// properly visit terminators so that we do not erroneously flag them as
// improper uses.
//
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'bad_order_add_a_level_2'
// CHECK: Found outside of lifetime use?!
// CHECK: Value: %1 = begin_borrow %0 : $Builtin.NativeObject // users: %22, %16, %12, %6, %3
// CHECK: Consuming User: end_borrow %1 : $Builtin.NativeObject // id: %16
// CHECK: Non Consuming User: end_borrow %5 : $Builtin.NativeObject // id: %17
// CHECK: Block: bb5
// CHECK-LABEL: Error#: 0. End Error in Function: 'bad_order_add_a_level_2'
//
// CHECK-LABEL: Error#: 1. Begin Error in Function: 'bad_order_add_a_level_2'
// CHECK: Found outside of lifetime use?!
// CHECK: Value: %1 = begin_borrow %0 : $Builtin.NativeObject // users: %22, %16, %12, %6, %3
// CHECK: Consuming User: end_borrow %1 : $Builtin.NativeObject // id: %12
// CHECK: Non Consuming User: end_borrow %5 : $Builtin.NativeObject // id: %13
// CHECK: Block: bb4
// CHECK-LABEL:Error#: 1. End Error in Function: 'bad_order_add_a_level_2'
// CHECK-LABEL: Error#: 2. Begin Error in Function: 'bad_order_add_a_level_2'
// CHECK: Found outside of lifetime use?!
// CHECK: Value: %1 = begin_borrow %0 : $Builtin.NativeObject // users: %22, %16, %12, %6, %3
// CHECK: Consuming User: end_borrow %1 : $Builtin.NativeObject // id: %6
// CHECK: Non Consuming User: end_borrow %5 : $Builtin.NativeObject // id: %7
// CHECK: Block: bb2
// CHECK-LABEL: Error#: 2. End Error in Function: 'bad_order_add_a_level_2'
//
// CHECK-LABEL: Error#: 3. Begin Error in Function: 'bad_order_add_a_level_2'
// CHECK: Found over consume?!
// CHECK: Value: %1 = begin_borrow %0 : $Builtin.NativeObject // users: %22, %16, %12, %6, %3
// CHECK: User: end_borrow %1 : $Builtin.NativeObject // id: %16
// CHECK: Block: bb2
// CHECK: Consuming Users:
// CHECK: end_borrow %1 : $Builtin.NativeObject // id: %22
// CHECK: end_borrow %1 : $Builtin.NativeObject // id: %16
// CHECK: end_borrow %1 : $Builtin.NativeObject // id: %12
// CHECK: end_borrow %1 : $Builtin.NativeObject // id: %6
// CHECK-LABEL: Error#: 3. End Error in Function: 'bad_order_add_a_level_2'
//
// CHECK-LABEL: Error#: 7. Begin Error in Function: 'bad_order_add_a_level_2'
// CHECK: Found outside of lifetime use?!
// CHECK: Value: %5 = argument of bb2 : $Builtin.NativeObject // users: %17, %13, %9, %7
// CHECK: Consuming User: end_borrow %5 : $Builtin.NativeObject // id: %13
// CHECK: Non Consuming User: end_borrow %11 : $Builtin.NativeObject // id: %14
// CHECK: Block: bb4
// CHECK-LABEL: Error#: 7. End Error in Function: 'bad_order_add_a_level_2'
// CHECK-LABEL: Error#: 8. Begin Error in Function: 'bad_order_add_a_level_2'
// CHECK: Found over consume?!
// CHECK: Value: %5 = argument of bb2 : $Builtin.NativeObject // users: %17, %13, %9, %7
// CHECK: User: end_borrow %5 : $Builtin.NativeObject // id: %17
// CHECK: Block: bb2
// CHECK: Consuming Users:
// CHECK: end_borrow %5 : $Builtin.NativeObject // id: %17
// CHECK: end_borrow %5 : $Builtin.NativeObject // id: %13
// CHECK: end_borrow %5 : $Builtin.NativeObject // id: %7
// CHECK-LABEL: Error#: 8. End Error in Function: 'bad_order_add_a_level_2'
//
// NOTE: There are 2-3 errors here we are not pattern matching. We should add
// patterns for them so we track if they are changed.
sil [ossa] @bad_order_add_a_level_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
bb0(%0 : @owned $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
cond_br undef, bb1, bb7
bb1:
%1a = begin_borrow %1 : $Builtin.NativeObject
br bb2(%1a : $Builtin.NativeObject)
bb2(%4 : @guaranteed $Builtin.NativeObject):
end_borrow %1 : $Builtin.NativeObject
end_borrow %4 : $Builtin.NativeObject
cond_br undef, bb3, bb5
bb3:
%4a = begin_borrow %4 : $Builtin.NativeObject
br bb4(%4a : $Builtin.NativeObject)
bb4(%9 : @guaranteed $Builtin.NativeObject):
end_borrow %1 : $Builtin.NativeObject
end_borrow %4 : $Builtin.NativeObject
end_borrow %9 : $Builtin.NativeObject
br bb6
bb5:
end_borrow %1 : $Builtin.NativeObject
end_borrow %4 : $Builtin.NativeObject
br bb6
bb6:
destroy_value %0 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
bb7:
end_borrow %1 : $Builtin.NativeObject
br bb6
}
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'owned_argument_overuse_br1'
// CHECK-NEXT: Found over consume?!
// CHECK-NEXT: Value: %0 = argument of bb0 : $Builtin.NativeObject
// CHECK-NEXT: User: destroy_value %0 : $Builtin.NativeObject
// CHECK-NEXT: Block: bb0
// CHECK: Error#: 0. End Error in Function: 'owned_argument_overuse_br1'
//
// CHECK-LABEL: Error#: 1. Begin Error in Function: 'owned_argument_overuse_br1'
// CHECK-NEXT: Error! Found a leaked owned value that was never consumed.
// CHECK-NEXT: Value: %3 = argument of bb1 : $Builtin.NativeObject
// CHECK-NOT: Block
// CHECK: Error#: 1. End Error in Function: 'owned_argument_overuse_br1'
//
// CHECK-NOT: Error#: {{[0-9][0-9]*}}. End Error in Function: 'owned_argument_overuse_br1'
sil [ossa] @owned_argument_overuse_br1 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
bb0(%0 : @owned $Builtin.NativeObject):
destroy_value %0 : $Builtin.NativeObject
br bb1(%0 : $Builtin.NativeObject)
bb1(%1 : @owned $Builtin.NativeObject):
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'owned_argument_overuse_br2'
// CHECK-NEXT: Found over consume?!
// CHECK-NEXT: Value: %0 = argument of bb0 : $Builtin.NativeObject
// CHECK-NEXT: User: destroy_value %0 : $Builtin.NativeObject
// CHECK-NEXT: Block: bb0
// CHECK-NOT: Block
// CHECK: Error#: 0. End Error in Function: 'owned_argument_overuse_br2'
//
// CHECK-NOT: Error#: {{[0-9][0-9]*}}. End Error in Function: 'owned_argument_overuse_br2'
sil [ossa] @owned_argument_overuse_br2 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
bb0(%0 : @owned $Builtin.NativeObject):
destroy_value %0 : $Builtin.NativeObject
br bb1(%0 : $Builtin.NativeObject)
bb1(%1 : @owned $Builtin.NativeObject):
destroy_value %1 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
/////////////////////////////////////////
// Movable Guaranteed Scope Test Cases //
/////////////////////////////////////////
//
// CHECK-NOT: Error#: {{[0-9][0-9]*}}. End Error in Function: 'simple_non_postdominating_diamond_with_forwarding_uses'
sil [ossa] @simple_non_postdominating_diamond_with_forwarding_uses : $@convention(thin) (@in_guaranteed NativeObjectPair, @guaranteed NativeObjectPair) -> () {
bb0(%0 : $*NativeObjectPair, %1 : @guaranteed $NativeObjectPair):
cond_br undef, bb1, bb2
bb1:
%3 = load_borrow %0 : $*NativeObjectPair
%4 = struct_extract %3 : $NativeObjectPair, #NativeObjectPair.obj1
br bb3(%4 : $Builtin.NativeObject, %3 : $NativeObjectPair)
bb2:
%5 = begin_borrow %1 : $NativeObjectPair
%6 = struct_extract %5 : $NativeObjectPair, #NativeObjectPair.obj1
br bb3(%6 : $Builtin.NativeObject, %5 : $NativeObjectPair)
bb3(%7 : @guaranteed $Builtin.NativeObject, %8 : @guaranteed $NativeObjectPair):
end_borrow %8 : $NativeObjectPair
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @simple_loop_carry_borrow_owned_arg : $@convention(thin) (@owned Builtin.NativeObject) -> () {
bb0(%0 : @owned $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
br bb1(%1 : $Builtin.NativeObject)
bb1(%2 : @guaranteed $Builtin.NativeObject):
cond_br undef, bb2, bb3
bb2:
br bb2a
bb2a:
br bb1(%2 : $Builtin.NativeObject)
bb3:
// Should error b/c destroy_value before end_borrow.
destroy_value %0 : $Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
sil [ossa] @simple_loop_carry_implicitregularusers_do_not_loop_carry : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1a = begin_borrow %0 : $Builtin.NativeObject
%1b = copy_value %0 : $Builtin.NativeObject
br bb1(%1a : $Builtin.NativeObject, %1b : $Builtin.NativeObject)
bb1(%2a : @guaranteed $Builtin.NativeObject, %2b : @owned $Builtin.NativeObject):
cond_br undef, bb2, bb3
bb2:
br bb2a
bb2a:
%3 = copy_value %2a : $Builtin.NativeObject
%3a = begin_borrow %3 : $Builtin.NativeObject
end_borrow %2a : $Builtin.NativeObject
destroy_value %2b : $Builtin.NativeObject
br bb1(%3a : $Builtin.NativeObject, %3 : $Builtin.NativeObject)
bb3:
end_borrow %2a : $Builtin.NativeObject
destroy_value %2b : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// We should identify bb0a as consuming the value twice.
//
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'simple_loop_carry_over_consume'
// CHECK-NEXT: Found over consume?!
// CHECK-NEXT: Value: %1 = begin_borrow %0 : $Builtin.NativeObject // users: %3, %3
// CHECK-NEXT: User: br bb2(%1 : $Builtin.NativeObject, %1 : $Builtin.NativeObject) // id: %3
// CHECK-NEXT: Block: bb1
// CHECK-NEXT: Consuming Users:
// CHECK-NEXT: br bb2(%1 : $Builtin.NativeObject, %1 : $Builtin.NativeObject) // id: %3
// CHECK-NEXT: br bb2(%1 : $Builtin.NativeObject, %1 : $Builtin.NativeObject) // id: %3
// CHECK: Error#: 0. End Error in Function: 'simple_loop_carry_over_consume'
//
// CHECK-LABEL: Error#: 1. Begin Error in Function: 'simple_loop_carry_over_consume'
// CHECK: Found outside of lifetime use?!
// CHECK: Value: %4 = argument of bb2 : $Builtin.NativeObject
// CHECK: Consuming User: end_borrow %4 : $Builtin.NativeObject
// CHECK: Non Consuming User: br bb2(%5 : $Builtin.NativeObject, %8 : $Builtin.NativeObject)
// CHECK: Block: bb4
// CHECK-LABEL: Error#: 1. End Error in Function: 'simple_loop_carry_over_consume'
// Some more errors are emitted
sil [ossa] @simple_loop_carry_over_consume : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
br bb0a
bb0a:
br bb1(%1 : $Builtin.NativeObject, %1 : $Builtin.NativeObject)
bb1(%2 : @guaranteed $Builtin.NativeObject, %2a : @guaranteed $Builtin.NativeObject):
cond_br undef, bb2, bb3
bb2:
br bb2a
bb2a:
%3 = begin_borrow %2a : $Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
br bb1(%2a : $Builtin.NativeObject, %3 : $Builtin.NativeObject)
bb3:
end_borrow %2a : $Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-NOT: Function: 'simple_loop_carry_cycle'
sil [ossa] @simple_loop_carry_cycle : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
br bb1(%1 : $Builtin.NativeObject)
bb1(%2 : @guaranteed $Builtin.NativeObject):
cond_br undef, bb2, bb3
bb2:
br bb2a
bb2a:
br bb1(%2 : $Builtin.NativeObject)
bb3:
end_borrow %2 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'simple_loop_carry_borrows_do_not_loop_carry'
// CHECK: Found outside of lifetime use?!
// CHECK: Value: %4 = argument of bb1 : $Builtin.NativeObject
// CHECK: Consuming User: end_borrow %4 : $Builtin.NativeObject
// CHECK: Non Consuming User: br bb1(%5 : $Builtin.NativeObject, %8 : $Builtin.NativeObject)
// CHECK: Block: bb3
// CHECK-LABEL: Error#: 0. End Error in Function: 'simple_loop_carry_borrows_do_not_loop_carry'
sil [ossa] @simple_loop_carry_borrows_do_not_loop_carry : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
%1a = begin_borrow %0 : $Builtin.NativeObject
br bb1(%1 : $Builtin.NativeObject, %1a : $Builtin.NativeObject)
bb1(%2 : @guaranteed $Builtin.NativeObject, %2a : @guaranteed $Builtin.NativeObject):
cond_br undef, bb2, bb3
bb2:
br bb2a
bb2a:
%3 = begin_borrow %2a : $Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
br bb1(%2a : $Builtin.NativeObject, %3 : $Builtin.NativeObject)
bb3:
end_borrow %2a : $Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'simple_loop_carry_borrows_do_not_loop_carry2'
// CHECK: Found outside of lifetime use?!
// CHECK: Value: %4 = argument of bb1 : $Builtin.NativeObject // users: %11, %9
// CHECK: Consuming User: end_borrow %4 : $Builtin.NativeObject // id: %11
// CHECK: Non Consuming User: end_borrow %5 : $Builtin.NativeObject // id: %12
// CHECK: Block: bb4
// CHECK: Error#: 0. End Error in Function: 'simple_loop_carry_borrows_do_not_loop_carry2'
sil [ossa] @simple_loop_carry_borrows_do_not_loop_carry2 : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
%1a = begin_borrow %0 : $Builtin.NativeObject
br bb1(%1 : $Builtin.NativeObject, %1a : $Builtin.NativeObject)
bb1(%2 : @guaranteed $Builtin.NativeObject, %2a : @guaranteed $Builtin.NativeObject):
cond_br undef, bb2, bb3
bb2:
br bb2a
bb2a:
%3 = begin_borrow %2a : $Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
br bb1(%2a : $Builtin.NativeObject, %3 : $Builtin.NativeObject)
bb3:
end_borrow %2 : $Builtin.NativeObject
end_borrow %2a : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-NOT: Function: 'simple_validate_enclosing_borrow_around_loop'
sil [ossa] @simple_validate_enclosing_borrow_around_loop : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
%2 = begin_borrow %1 : $Builtin.NativeObject
%3 = begin_borrow %1 : $Builtin.NativeObject
br bb1(%2 : $Builtin.NativeObject, %3 : $Builtin.NativeObject)
bb1(%4 : @guaranteed $Builtin.NativeObject, %5 : @guaranteed $Builtin.NativeObject):
cond_br undef, bb2, bb3
bb2:
br bb2a
bb2a:
br bb1(%5 : $Builtin.NativeObject, %4 : $Builtin.NativeObject)
bb3:
end_borrow %4 : $Builtin.NativeObject
end_borrow %5 : $Builtin.NativeObject
end_borrow %1 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-NOT: Function: 'simple_validate_enclosing_borrow_around_loop_2'
sil [ossa] @simple_validate_enclosing_borrow_around_loop_2 : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%2 = begin_borrow %0 : $Builtin.NativeObject
%3 = begin_borrow %0 : $Builtin.NativeObject
br bb1(%2 : $Builtin.NativeObject, %3 : $Builtin.NativeObject)
bb1(%4 : @guaranteed $Builtin.NativeObject, %5 : @guaranteed $Builtin.NativeObject):
cond_br undef, bb2, bb3
bb2:
br bb2a
bb2a:
br bb1(%5 : $Builtin.NativeObject, %4 : $Builtin.NativeObject)
bb3:
end_borrow %4 : $Builtin.NativeObject
end_borrow %5 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-NOT: Function: 'simple_validate_enclosing_borrow_around_loop_3'
sil [ossa] @simple_validate_enclosing_borrow_around_loop_3 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
bb0(%0 : @owned $Builtin.NativeObject):
%2 = begin_borrow %0 : $Builtin.NativeObject
%3 = begin_borrow %0 : $Builtin.NativeObject
br bb1(%2 : $Builtin.NativeObject, %3 : $Builtin.NativeObject)
bb1(%4 : @guaranteed $Builtin.NativeObject, %5 : @guaranteed $Builtin.NativeObject):
cond_br undef, bb2, bb3
bb2:
br bb2a
bb2a:
br bb1(%5 : $Builtin.NativeObject, %4 : $Builtin.NativeObject)
bb3:
end_borrow %4 : $Builtin.NativeObject
end_borrow %5 : $Builtin.NativeObject
destroy_value %0 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}