mirror of
https://github.com/apple/swift.git
synced 2026-10-28 21:15:56 +01:00
157 lines
6.1 KiB
Plaintext
157 lines
6.1 KiB
Plaintext
// RUN: %target-sil-opt -sil-ownership-verifier-enable-testing -ownership-verifier-textual-error-dumper -enable-sil-verify-all=0 -o /dev/null %s 2>&1 | %FileCheck %s
|
|
// REQUIRES: asserts
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
|
|
//////////////////
|
|
// Declarations //
|
|
//////////////////
|
|
|
|
enum Optional<T> {
|
|
case some(T)
|
|
case none
|
|
}
|
|
|
|
struct A {
|
|
var ptr: Builtin.NativeObject
|
|
var ptr2: Optional<(Builtin.NativeObject, Builtin.NativeObject)>
|
|
}
|
|
|
|
struct B {
|
|
var a1: A
|
|
var a2: A
|
|
}
|
|
|
|
sil @owned_use_of_nativeobject : $@convention(thin) (@owned Builtin.NativeObject) -> ()
|
|
sil @guaranteed_use_of_nativeobject : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
|
|
///////////
|
|
// Tests //
|
|
///////////
|
|
|
|
//===---
|
|
// begin_borrow subobject tests
|
|
//
|
|
|
|
sil [ossa] @value_subobject_without_corresponding_end_borrow : $@convention(thin) (@owned B) -> () {
|
|
bb0(%0 : @owned $B):
|
|
%1 = begin_borrow %0 : $B
|
|
%2 = struct_extract %1 : $B, #B.a1
|
|
%3 = struct_extract %2 : $A, #A.ptr
|
|
%4 = function_ref @guaranteed_use_of_nativeobject : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %4(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
end_borrow %1 : $B
|
|
destroy_value %0 : $B
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We fail here since we have a use of our subobject after the end_borrow which
|
|
// ends the borrow's lifetime.
|
|
//
|
|
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'value_subobject_with_use_after_end_borrow'
|
|
// CHECK: Found outside of lifetime use?!
|
|
// CHECK: Value: %1 = begin_borrow %0 : $B
|
|
// CHECK: Consuming User: end_borrow %1 : $B
|
|
// CHECK: Non Consuming User: %4 = struct_extract %2 : $A, #A.ptr
|
|
// CHECK: Block: bb0
|
|
// CHECK: Error#: 0. End Error in Function: 'value_subobject_with_use_after_end_borrow'
|
|
sil [ossa] @value_subobject_with_use_after_end_borrow : $@convention(thin) (@owned B) -> () {
|
|
bb0(%0 : @owned $B):
|
|
%1 = begin_borrow %0 : $B
|
|
%2 = struct_extract %1 : $B, #B.a1
|
|
end_borrow %1 : $B
|
|
%3 = struct_extract %2 : $A, #A.ptr
|
|
destroy_value %0 : $B
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We fail here since we have a destroy of our subobject. The idea is to make
|
|
// sure that our special handling code for subobjects here does not stop us from
|
|
// detecting violations of ownership kinds on the subobjects.
|
|
//
|
|
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'value_subobject_with_destroy_of_subobject'
|
|
// CHECK: Have operand with incompatible ownership?!
|
|
// CHECK: Value: %5 = tuple_extract %4 : $(Builtin.NativeObject, Builtin.NativeObject), 1
|
|
// CHECK: User: destroy_value %5 : $Builtin.NativeObject
|
|
// CHECK: Conv: guaranteed
|
|
// CHECK: Error#: 0. End Error in Function: 'value_subobject_with_destroy_of_subobject'
|
|
//
|
|
// CHECK-NOT: Error#: {{[0-9][0-9]+}}. Begin Error in Function: 'value_subobject_with_destroy_of_subobject'
|
|
sil [ossa] @value_subobject_with_destroy_of_subobject : $@convention(thin) (@owned B) -> () {
|
|
bb0(%0 : @owned $B):
|
|
%1 = begin_borrow %0 : $B
|
|
%2 = struct_extract %1 : $B, #B.a1
|
|
%3 = struct_extract %2 : $A, #A.ptr2
|
|
%4 = unchecked_enum_data %3 : $Optional<(Builtin.NativeObject, Builtin.NativeObject)>, #Optional.some!enumelt
|
|
%5 = tuple_extract %4 : $(Builtin.NativeObject, Builtin.NativeObject), 1
|
|
destroy_value %5 : $Builtin.NativeObject
|
|
end_borrow %1 : $B
|
|
destroy_value %0 : $B
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'value_different_subobject_kinds_multiple_levels'
|
|
// CHECK: Found outside of lifetime use?!
|
|
// CHECK: Value: %1 = begin_borrow %0 : $B
|
|
// CHECK: Consuming User: end_borrow %1 : $B
|
|
// CHECK: Non Consuming User: %6 = tuple_extract %4 : $(Builtin.NativeObject, Builtin.NativeObject), 1
|
|
// CHECK: Block: bb0
|
|
// CHECK: Error#: 0. End Error in Function: 'value_different_subobject_kinds_multiple_levels'
|
|
//
|
|
// CHECK-NOT: Error#: {{[0-9][0-9]+}}. End Error in Function: 'value_different_subobject_kinds_multiple_levels'
|
|
sil [ossa] @value_different_subobject_kinds_multiple_levels : $@convention(thin) (@owned B) -> () {
|
|
bb0(%0 : @owned $B):
|
|
%1 = begin_borrow %0 : $B
|
|
%2 = struct_extract %1 : $B, #B.a1
|
|
%3 = struct_extract %2 : $A, #A.ptr2
|
|
%4 = unchecked_enum_data %3 : $Optional<(Builtin.NativeObject, Builtin.NativeObject)>, #Optional.some!enumelt
|
|
end_borrow %1 : $B
|
|
%5 = tuple_extract %4 : $(Builtin.NativeObject, Builtin.NativeObject), 1
|
|
destroy_value %0 : $B
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
//===---
|
|
// Function Argument guaranteed tests
|
|
//
|
|
|
|
// CHECK-NOT: Begin Error in Function: 'funcarg_subobject_basic_test'
|
|
sil [ossa] @funcarg_subobject_basic_test : $@convention(thin) (@guaranteed B) -> () {
|
|
bb0(%0 : @guaranteed $B):
|
|
%2 = struct_extract %0 : $B, #B.a1
|
|
%3 = struct_extract %2 : $A, #A.ptr
|
|
%4 = function_ref @guaranteed_use_of_nativeobject : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %4(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// We fail here since we have a destroy of our subobject. The idea is to make
|
|
// sure that our special handling code for subobjects here does not stop us from
|
|
// detecting violations of ownership kinds on the subobjects.
|
|
//
|
|
// CHECK-LABEL: Error#: 0. Begin Error in Function: 'funcarg_subobject_with_destroy_of_subobject'
|
|
// CHECK: Have operand with incompatible ownership?!
|
|
// CHECK: Value: %4 = tuple_extract %3 : $(Builtin.NativeObject, Builtin.NativeObject), 1
|
|
// CHECK: User: destroy_value %4 : $Builtin.NativeObject
|
|
// CHECK: Conv: guaranteed
|
|
// CHECK: Error#: 0. End Error in Function: 'funcarg_subobject_with_destroy_of_subobject'
|
|
//
|
|
// CHECK-NOT: Error#: {{[0-9][0-9]+}}. End Error in Function: 'funcarg_subobject_with_destroy_of_subobject'
|
|
sil [ossa] @funcarg_subobject_with_destroy_of_subobject : $@convention(thin) (@guaranteed B) -> () {
|
|
bb0(%0 : @guaranteed $B):
|
|
%2 = struct_extract %0 : $B, #B.a1
|
|
%3 = struct_extract %2 : $A, #A.ptr2
|
|
%4 = unchecked_enum_data %3 : $Optional<(Builtin.NativeObject, Builtin.NativeObject)>, #Optional.some!enumelt
|
|
%5 = tuple_extract %4 : $(Builtin.NativeObject, Builtin.NativeObject), 1
|
|
destroy_value %5 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|