Files
swift-mirror/test/SIL/OwnershipVerifier/guaranteed_phis_errors.sil
Erik Eckstein e14c1d1f62 SIL, Optimizer: update and handle borrowed-from instructions
Compute, update and handle borrowed-from instruction in various utilities and passes.
Also, used borrowed-from to simplify `gatherBorrowIntroducers` and `gatherEnclosingValues`.
Replace those utilities by `Value.getBorrowIntroducers` and `Value.getEnclosingValues`, which return a lazily computed Sequence of borrowed/enclosing values.
2024-04-10 13:38:10 +02:00

227 lines
7.6 KiB
Plaintext

// RUN: %target-sil-opt -disable-swift-verification -module-name Swift -sil-ownership-verifier-enable-testing -ownership-verifier-textual-error-dumper -enable-sil-verify-all=0 %s -o /dev/null 2>&1 | %FileCheck %s
class SuperKlass {}
class Klass : SuperKlass {}
struct WrapperStruct {
var val: Klass
}
struct Wrapper1 {
var val1: Wrapper2
}
struct Wrapper2 {
var val2: Klass
}
sil @use_superklass : $@convention(thin) (@guaranteed SuperKlass) -> ()
sil @use_klass : $@convention(thin) (@guaranteed Klass) -> ()
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'test1'
// CHECK: Found outside of lifetime use?!
// CHECK: Value: %1 = begin_borrow %0 : $WrapperStruct
// CHECK: Consuming User: end_borrow %1 : $WrapperStruct
// CHECK: Non Consuming User: %5 = apply %4(%2) : $@convention(thin) (@guaranteed Klass) -> ()
// CHECK: Block: bb0
// CHECK-LABEL: Error#: 0. End Error in Function: 'test1'
sil [ossa] @test1 : $@convention(thin) (@owned WrapperStruct) -> () {
bb0(%0 : @owned $WrapperStruct):
%b = begin_borrow %0 : $WrapperStruct
%ex1 = struct_extract %b : $WrapperStruct, #WrapperStruct.val
end_borrow %b : $WrapperStruct
%func = function_ref @use_klass : $@convention(thin) (@guaranteed Klass) -> ()
apply %func(%ex1) : $@convention(thin) (@guaranteed Klass) -> ()
destroy_value %0 : $WrapperStruct
%9999 = tuple()
return %9999 : $()
}
// CHECK: Error#: 0. Begin Error in Function: 'test2'
// CHECK: Found outside of lifetime use?!
// CHECK: Value: %1 = begin_borrow %0 : $Klass
// CHECK: Consuming User: end_borrow %1 : $Klass
// CHECK: Non Consuming User: %8 = apply %7(%5) : $@convention(thin) (@guaranteed SuperKlass) -> ()
// CHECK: Block: bb2
// CHECK: Error#: 0. End Error in Function: 'test2'
sil [ossa] @test2 : $@convention(thin) (@owned Klass) -> () {
bb0(%0 : @owned $Klass):
%outer = begin_borrow %0 : $Klass
br bb1
bb1:
%cast1 = unchecked_ref_cast %outer : $Klass to $SuperKlass
br bb2(%cast1 : $SuperKlass)
bb2(%phi : @guaranteed $SuperKlass):
end_borrow %outer : $Klass
%func = function_ref @use_superklass : $@convention(thin) (@guaranteed SuperKlass) -> ()
apply %func(%phi) : $@convention(thin) (@guaranteed SuperKlass) -> ()
destroy_value %0 : $Klass
%9999 = tuple()
return %9999 : $()
}
// CHECK: Error#: 0. Begin Error in Function: 'test3'
// CHECK: Found outside of lifetime use?!
// CHECK: Value: %9 = argument of bb3 : $Klass
// CHECK: Consuming User: destroy_value %9 : $Klass
// CHECK: Non Consuming User: end_borrow %10 : $Klass
// CHECK: Block: bb3
// CHECK: Error#: 0. End Error in Function: 'test3'
sil [ossa] @test3 : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> () {
bb0(%0 : @guaranteed $Klass, %1 : @guaranteed $Klass):
cond_br undef, bb1, bb2
bb1:
%copy0 = copy_value %0 : $Klass
%borrow0 = begin_borrow %copy0 : $Klass
br bb3(%copy0 : $Klass, %borrow0 : $Klass)
bb2:
%copy1 = copy_value %1 : $Klass
%borrow1 = begin_borrow %copy1 : $Klass
br bb3(%copy1 : $Klass, %borrow1 : $Klass)
bb3(%phi : @owned $Klass, %gphi : @guaranteed $Klass):
%func = function_ref @use_klass : $@convention(thin) (@guaranteed Klass) -> ()
apply %func(%phi) : $@convention(thin) (@guaranteed Klass) -> ()
destroy_value %phi : $Klass
end_borrow %gphi : $Klass
%9999 = tuple()
return %9999 : $()
}
// CHECK: Error#: 0. Begin Error in Function: 'test4'
// CHECK: Found outside of lifetime use?!
// CHECK: Value: %15 = argument of bb4 : $Wrapper1
// CHECK: Consuming User: end_borrow %15 : $Wrapper1
// CHECK: Non Consuming User: %18 = apply %17(%14) : $@convention(thin) (@guaranteed Klass) -> ()
// CHECK: Block: bb4
// CHECK: Error#: 0. End Error in Function: 'test4'
sil [ossa] @test4 : $@convention(thin) (@owned Wrapper1, @owned Wrapper1) -> () {
bb0(%0 : @owned $Wrapper1, %1 : @owned $Wrapper1):
%b1 = begin_borrow %0 : $Wrapper1
cond_br undef, bb1, bb2
bb1:
%ex1 = struct_extract %b1 : $Wrapper1, #Wrapper1.val1
br bb3(%ex1 : $Wrapper2, %b1 : $Wrapper1)
bb2:
end_borrow %b1 : $Wrapper1
%b2 = begin_borrow %1 : $Wrapper1
%ex2 = struct_extract %b2 : $Wrapper1, #Wrapper1.val1
br bb3(%ex2 : $Wrapper2, %b2 : $Wrapper1)
bb3(%phi1 : @guaranteed $Wrapper2, %phi2 : @guaranteed $Wrapper1):
%ex3 = struct_extract %phi1 : $Wrapper2, #Wrapper2.val2
br bb4(%ex3 : $Klass, %phi2 : $Wrapper1)
bb4(%phi3 : @guaranteed $Klass, %phi4 : @guaranteed $Wrapper1):
end_borrow %phi4 : $Wrapper1
%f = function_ref @use_klass : $@convention(thin) (@guaranteed Klass) -> ()
apply %f(%phi3) : $@convention(thin) (@guaranteed Klass) -> ()
destroy_value %0 : $Wrapper1
destroy_value %1 : $Wrapper1
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'test5'
// CHECK: Have operand with incompatible ownership?!
// CHECK: Value: %5 = argument of bb2 : $SuperKlass
// CHECK: User: destroy_value %5 : $SuperKlass
// CHECK: Operand Number: 0
// CHECK: Conv: guaranteed
// CHECK: Constraint:
// CHECK: <Constraint Kind:owned LifetimeConstraint:LifetimeEnding>
// CHECK-LABEL: Error#: 0. End Error in Function: 'test5'
sil [ossa] @test5 : $@convention(thin) (@owned Klass) -> () {
bb0(%0 : @owned $Klass):
%outer = begin_borrow %0 : $Klass
br bb1
bb1:
%cast1 = unchecked_ref_cast %outer : $Klass to $SuperKlass
br bb2(%cast1 : $SuperKlass)
bb2(%phi : @guaranteed $SuperKlass):
destroy_value %phi : $SuperKlass
end_borrow %outer : $Klass
destroy_value %0 : $Klass
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'test6'
// CHECK: Found outside of lifetime use?!
// CHECK: Value: %1 = load_borrow %0 : $*Klass
// CHECK: Consuming User: end_borrow %1 : $Klass
// CHECK: Non Consuming User: %8 = apply %7(%5) : $@convention(thin) (@guaranteed SuperKlass) -> ()
// CHECK: Block: bb2
// CHECK-LABEL: Error#: 0. End Error in Function: 'test6'
sil [ossa] @test6 : $@convention(thin) (@in Klass) -> () {
bb0(%0 : $*Klass):
%outer = load_borrow %0 : $*Klass
br bb1
bb1:
%cast1 = unchecked_ref_cast %outer : $Klass to $SuperKlass
br bb2(%cast1 : $SuperKlass)
bb2(%phi : @guaranteed $SuperKlass):
end_borrow %outer : $Klass
%func = function_ref @use_superklass : $@convention(thin) (@guaranteed SuperKlass) -> ()
apply %func(%phi) : $@convention(thin) (@guaranteed SuperKlass) -> ()
destroy_addr %0 : $*Klass
%9999 = tuple()
return %9999 : $()
}
// Error#: 0. Begin Error in Function: 'test7'
// Invalid End Borrow!
// Original Value: %0 = argument of bb0 : $Klass
// End Borrow: br bb3(%3 : $SuperKlass)
//
// Error#: 0. End Error in Function: 'test7'
// CHECK: Error#: 1. Begin Error in Function: 'test7'
// CHECK: Malformed @guaranteed phi!
// CHECK: Phi: %7 = argument of bb3 : $SuperKlass
// CHECK: Guaranteed forwarding operands not found on all paths!
// CHECK: Error#: 1. End Error in Function: 'test7'
sil [ossa] @test7 : $@convention(thin) (@guaranteed Klass, @owned SuperKlass) -> () {
bb0(%0 : @guaranteed $Klass, %1 : @owned $SuperKlass):
cond_br undef, bb1, bb2
bb1:
%3 = unchecked_ref_cast %0 : $Klass to $SuperKlass
br bb3(%3 : $SuperKlass)
bb2:
%5 = begin_borrow %1 : $SuperKlass
br bb3(%5 : $SuperKlass)
bb3(%7 : @guaranteed $SuperKlass):
%8 = function_ref @use_superklass : $@convention(thin) (@guaranteed SuperKlass) -> ()
%9 = apply %8(%7) : $@convention(thin) (@guaranteed SuperKlass) -> ()
end_borrow %7 : $SuperKlass
destroy_value %1 : $SuperKlass
%12 = tuple ()
return %12 : $()
}
enum FakeOptional<T> {
case none
case some(T)
}
sil [ossa] @end_borrow_test1 : $@convention(thin) () -> () {
bb0:
%0 = enum $FakeOptional<Klass>, #FakeOptional.none!enumelt
end_borrow %0 : $FakeOptional<Klass>
%r = tuple ()
return %r : $()
}