mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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
752 lines
26 KiB
Plaintext
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 : $()
|
|
}
|
|
|