blob: 99ef037ae42d9e93f339b3cebd384069cb070eca [file] [log] [blame]
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -definite-init -verify | %FileCheck %s
// This test only tests mark_uninitialized [delegatingself]
sil_stage raw
import Builtin
import Swift
protocol P {}
class C : P {}
struct MyStruct : P {}
struct MyStruct2 {
var x: P
init(delegate: ())
init()
}
sil @selfinit : $@convention(thin) () -> MyStruct // user: %7
class SomeClass {}
class RootClassWithNontrivialStoredProperties {
var x, y: SomeClass
init()
}
class DerivedClassWithNontrivialStoredProperties : RootClassWithNontrivialStoredProperties {
var a, b: SomeClass
override init()
}
// CHECK-LABEL: @self_init_assert_instruction
// CHECK: apply
// CHECK-NEXT: store
// CHECK-NEXT: load
// CHECK: return
sil @self_init_assert_instruction : $@convention(thin) (Int, @thin MyStruct.Type) -> MyStruct {
bb0(%0 : $Int, %1 : $@thin MyStruct.Type):
%2 = alloc_stack $MyStruct, var, name "sf"
%3 = mark_uninitialized [delegatingself] %2 : $*MyStruct
%6 = function_ref @selfinit : $@convention(thin) () -> MyStruct
%7 = apply %6() : $@convention(thin) () -> MyStruct
assign %7 to %3 : $*MyStruct
%9 = load %3 : $*MyStruct
dealloc_stack %2 : $*MyStruct
return %9 : $MyStruct
}
sil @selfinit_delegate : $@convention(thin) (@thin MyStruct2.Type) -> @out MyStruct2
// <rdar://problem/18089574> Protocol member in struct + delegating init miscompilation
// CHECK-LABEL: @self_init_copyaddr
sil @self_init_copyaddr : $@convention(thin) (@thin MyStruct2.Type) -> @out MyStruct2 {
bb0(%0 : $*MyStruct2, %1 : $@thin MyStruct2.Type):
// CHECK: [[SELF:%[0-9]+]] = alloc_stack $MyStruct2
%2 = alloc_stack $MyStruct2, var, name "sf"
%3 = mark_uninitialized [delegatingself] %2 : $*MyStruct2
%6 = metatype $@thin MyStruct2.Type
%7 = function_ref @selfinit_delegate : $@convention(thin) (@thin MyStruct2.Type) -> @out MyStruct2
%8 = alloc_stack $MyStruct2
// Make sure this copy_addr ends up being an initialization.
apply %7(%8, %6) : $@convention(thin) (@thin MyStruct2.Type) -> @out MyStruct2
copy_addr [take] %8 to %3 : $*MyStruct2
dealloc_stack %8 : $*MyStruct2
// CHECK: apply
// CHECK-NEXT: copy_addr [take] {{.*}} to [initialization] [[SELF]] : $*MyStruct2
// CHECK-NEXT: dealloc_stack
copy_addr [take] %3 to [initialization] %0 : $*MyStruct2
%13 = tuple ()
dealloc_stack %2 : $*MyStruct2
return %13 : $()
}
// CHECK-LABEL: sil @test_delegating_box_release
// CHECK: bb0(%0 : $RootClassWithNontrivialStoredProperties):
// CHECK-NEXT: [[SELFBOX:%[0-9]+]] = alloc_box $<τ_0_0> { var τ_0_0 } <RootClassWithNontrivialStoredProperties>
// CHECK-NEXT: [[PB:%[0-9]+]] = project_box [[SELFBOX]]
// CHECK-NEXT: store %0 to [[PB]]
// CHECK-NEXT: [[SELF:%[0-9]+]] = load [[PB]]
// CHECK-NEXT: [[METATYPE:%[0-9]+]] = value_metatype $@thick RootClassWithNontrivialStoredProperties.Type, [[SELF]] : $RootClassWithNontrivialStoredProperties
// CHECK-NEXT: dealloc_partial_ref [[SELF]] : $RootClassWithNontrivialStoredProperties, [[METATYPE]] : $@thick RootClassWithNontrivialStoredProperties.Type
// CHECK-NEXT: dealloc_box [[SELFBOX]]
sil @test_delegating_box_release : $@convention(method) (@owned RootClassWithNontrivialStoredProperties) -> () {
bb0(%0 : $RootClassWithNontrivialStoredProperties):
%2 = alloc_box $_0_0> { var τ_0_0 } <RootClassWithNontrivialStoredProperties>
%2a = project_box %2 : $_0_0> { var τ_0_0 } <RootClassWithNontrivialStoredProperties>, 0
%4 = mark_uninitialized [delegatingself] %2a : $*RootClassWithNontrivialStoredProperties
store %0 to %4 : $*RootClassWithNontrivialStoredProperties
strong_release %2 : $_0_0> { var τ_0_0 } <RootClassWithNontrivialStoredProperties>
%13 = tuple ()
return %13 : $()
}
// CHECK-LABEL: sil @test_delegating_rvalue_release
// CHECK: bb0(%0 : $RootClassWithNontrivialStoredProperties):
// CHECK-NEXT: [[SELFBOX:%[0-9]+]] = alloc_box $<τ_0_0> { var τ_0_0 } <RootClassWithNontrivialStoredProperties>
// CHECK-NEXT: [[PB:%[0-9]+]] = project_box [[SELFBOX]]
// CHECK-NEXT: store %0 to [[PB]]
// CHECK-NEXT: [[SELF:%[0-9]+]] = load [[PB]]
// CHECK-NEXT: [[METATYPE:%[0-9]+]] = value_metatype $@thick RootClassWithNontrivialStoredProperties.Type, [[SELF]] : $RootClassWithNontrivialStoredProperties
// CHECK-NEXT: dealloc_partial_ref [[SELF]] : $RootClassWithNontrivialStoredProperties, [[METATYPE]] : $@thick RootClassWithNontrivialStoredProperties.Type
// CHECK-NEXT: [[SELF2:%[0-9]+]] = load [[PB]]
// CHECK-NEXT: [[METATYPE2:%[0-9]+]] = value_metatype $@thick RootClassWithNontrivialStoredProperties.Type, [[SELF2]] : $RootClassWithNontrivialStoredProperties
// CHECK-NEXT: dealloc_partial_ref [[SELF2]] : $RootClassWithNontrivialStoredProperties, [[METATYPE2]] : $@thick RootClassWithNontrivialStoredProperties.Type
// CHECK-NEXT: dealloc_box [[SELFBOX]]
sil @test_delegating_rvalue_release : $@convention(method) (@owned RootClassWithNontrivialStoredProperties) -> () {
bb0(%0 : $RootClassWithNontrivialStoredProperties):
%2 = alloc_box $_0_0> { var τ_0_0 } <RootClassWithNontrivialStoredProperties>
%2a = project_box %2 : $_0_0> { var τ_0_0 } <RootClassWithNontrivialStoredProperties>, 0
%4 = mark_uninitialized [delegatingself] %2a : $*RootClassWithNontrivialStoredProperties
store %0 to %4 : $*RootClassWithNontrivialStoredProperties
%6 = load %4 : $*RootClassWithNontrivialStoredProperties
strong_release %6 : $RootClassWithNontrivialStoredProperties
strong_release %2 : $_0_0> { var τ_0_0 } <RootClassWithNontrivialStoredProperties>
%13 = tuple ()
return %13 : $()
}
// CHECK-LABEL: sil @test_delegating_derived_release
// CHECK: bb0(%0 : $DerivedClassWithNontrivialStoredProperties):
// CHECK-NEXT: [[SELFBOX:%[0-9]+]] = alloc_stack $DerivedClassWithNontrivialStoredProperties
// CHECK-NEXT: store %0 to [[SELFBOX]]
// CHECK-NEXT: [[SELF:%[0-9]+]] = load [[SELFBOX]]
// CHECK-NEXT: [[METATYPE:%[0-9]+]] = value_metatype $@thick DerivedClassWithNontrivialStoredProperties.Type, [[SELF]] : $DerivedClassWithNontrivialStoredProperties
// CHECK-NEXT: dealloc_partial_ref [[SELF]] : $DerivedClassWithNontrivialStoredProperties, [[METATYPE]] : $@thick DerivedClassWithNontrivialStoredProperties.Type
// CHECK-NEXT: dealloc_stack [[SELFBOX]]
sil @test_delegating_derived_release : $@convention(method) (@owned DerivedClassWithNontrivialStoredProperties) -> () {
bb0(%0 : $DerivedClassWithNontrivialStoredProperties):
%2 = alloc_stack $DerivedClassWithNontrivialStoredProperties
%4 = mark_uninitialized [delegatingself] %2 : $*DerivedClassWithNontrivialStoredProperties
store %0 to %4 : $*DerivedClassWithNontrivialStoredProperties
destroy_addr %4 : $*DerivedClassWithNontrivialStoredProperties
dealloc_stack %2 : $*DerivedClassWithNontrivialStoredProperties
%13 = tuple ()
return %13 : $()
}
// <rdar://problem/20608881> DI miscompiles this testcase into a memory leak
struct MyStruct3 {
@sil_stored var c: C
}
sil @selfinit_mystruct3 : $@convention(thin) () -> @owned MyStruct3
// CHECK-LABEL: sil hidden @test_conditional_destroy_delegating_init
sil hidden @test_conditional_destroy_delegating_init : $@convention(thin) (Builtin.Int1) -> () {
bb0(%0 : $Builtin.Int1):
// CHECK: [[CONTROL:%[0-9]+]] = alloc_stack $Builtin.Int1
// CHECK-NEXT: [[SELF_BOX:%[0-9]+]] = alloc_stack $MyStruct3
%2 = alloc_stack $MyStruct3
%3 = mark_uninitialized [delegatingself] %2 : $*MyStruct3
// CHECK: cond_br %0, [[SUCCESS:bb[0-9]+]], [[EXIT:bb[0-9]+]]
cond_br %0, bb1, bb2
// CHECK: [[SUCCESS]]:
bb1:
%9 = function_ref @selfinit_mystruct3 : $@convention(thin) () -> @owned MyStruct3
%10 = apply %9() : $@convention(thin) () -> @owned MyStruct3
assign %10 to %3 : $*MyStruct3
// CHECK: [[NEW_SELF:%[0-9]+]] = apply {{.*}}() : $@convention(thin) () -> @owned MyStruct3
// CHECK-NEXT: [[SET:%[0-9]+]] = integer_literal $Builtin.Int1, -1
// CHECK-NEXT: store [[SET]] to [[CONTROL]] : $*Builtin.Int1
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_BOX]] : $*MyStruct3
// CHECK-NEXT: br [[CHECK:bb[0-9]+]]
br bb2
// CHECK: [[CHECK]]:
bb2:
// CHECK-NEXT: [[BIT:%[0-9]+]] = load [[CONTROL]] : $*Builtin.Int1
// CHECK-NEXT: cond_br [[BIT]], [[INITIALIZED:bb[0-9]+]], [[UNINITIALIZED:bb[0-9]+]]
// CHECK: [[INITIALIZED]]:
// CHECK-NEXT: destroy_addr [[SELF_BOX]] : $*MyStruct3
// CHECK-NEXT: br [[EXIT:bb[0-9]+]]
// CHECK: [[UNINITIALIZED]]:
// CHECK-NEXT: br [[EXIT]]
// CHECK: [[EXIT]]:
destroy_addr %3 : $*MyStruct3
dealloc_stack %2 : $*MyStruct3
%15 = tuple ()
return %15 : $()
}
// <rdar://problem/21991742> DI miscompiles this testcase into a double free
class MyClass3 {
}
sil @selfinit_myclass3 : $@convention(thin) (@owned MyClass3) -> @owned MyClass3
// CHECK-LABEL: sil hidden @test_conditional_destroy_class_delegating_init
sil hidden @test_conditional_destroy_class_delegating_init : $@convention(thin) (Builtin.Int1) -> () {
bb0(%0 : $Builtin.Int1):
// CHECK: [[CONTROL:%[0-9]+]] = alloc_stack $Builtin.Int1
// CHECK-NEXT: [[SELF_BOX:%[0-9]+]] = alloc_stack $MyClass3
%2 = alloc_stack $MyClass3
%3 = mark_uninitialized [delegatingself] %2 : $*MyClass3
// CHECK: cond_br %0, [[SUCCESS:bb[0-9]+]], [[EXIT:bb[0-9]+]]
cond_br %0, bb1, bb2
// CHECK: [[SUCCESS]]:
bb1:
%4 = load %3 : $*MyClass3
%5 = function_ref @selfinit_myclass3 : $@convention(thin) (@owned MyClass3) -> @owned MyClass3
%6 = apply %5(%4) : $@convention(thin) (@owned MyClass3) -> @owned MyClass3
store %6 to %3 : $*MyClass3
// CHECK: [[SET:%[0-9]+]] = integer_literal $Builtin.Int1, -1
// CHECK-NEXT: store [[SET]] to [[CONTROL]] : $*Builtin.Int1
// CHECK: [[NEW_SELF:%[0-9]+]] = apply {{.*}}({{.*}}) : $@convention(thin) (@owned MyClass3) -> @owned MyClass3
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_BOX]] : $*MyClass3
// CHECK-NEXT: br [[CHECK:bb[0-9]+]]
br bb2
// CHECK: [[CHECK]]:
bb2:
// CHECK-NEXT: [[BIT:%[0-9]+]] = load [[CONTROL]] : $*Builtin.Int1
// CHECK-NEXT: cond_br [[BIT]], [[INITIALIZED:bb[0-9]+]], [[UNINITIALIZED:bb[0-9]+]]
// CHECK: [[INITIALIZED]]:
// CHECK-NEXT: destroy_addr [[SELF_BOX]] : $*MyClass3
// CHECK-NEXT: br [[EXIT:bb[0-9]+]]
// CHECK: [[UNINITIALIZED]]:
// CHECK-NEXT: [[OLD_SELF:%[0-9]+]] = load [[SELF_BOX]] : $*MyClass3
// CHECK-NEXT: [[METATYPE:%[0-9]+]] = value_metatype $@thick MyClass3.Type, [[OLD_SELF]] : $MyClass3
// CHECK-NEXT: dealloc_partial_ref [[OLD_SELF]] : $MyClass3, [[METATYPE]] : $@thick MyClass3.Type
// CHECK-NEXT: br [[EXIT]]
// CHECK: [[EXIT]]:
destroy_addr %3 : $*MyClass3
dealloc_stack %2 : $*MyClass3
%7 = tuple ()
return %7 : $()
}