1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
// 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 : $()
}
|