blob: d0be2dca9fdedb3bca3b39fdaf76369c143a06ee [file] [log] [blame]
// RUN: %target-sil-opt -enable-sil-verify-all %s -definite-init -raw-sil-inst-lowering -verify | %FileCheck %s
// This test only tests mark_uninitialized [derivedself]
sil_stage raw
import Builtin
import Swift
/////////////////
// Definitions //
/////////////////
sil @takes_Int_inout : $@convention(thin) (@inout Int) -> ()
sil @makesInt : $@convention(thin) () -> Int
class RootClassWithIVars {
var x: Int
var y: Int
var z: (Int, Int)
init()
}
class DerivedClassWithIVars : RootClassWithIVars {
var a: Int
override init()
}
sil @superinit : $@convention(method) (@owned RootClassWithIVars) -> @owned RootClassWithIVars
protocol P {}
class C : P {}
class SomeClass {}
sil @getSomeClass : $@convention(thin) () -> @owned SomeClass
sil @getSomeOptionalClass : $@convention(thin) () -> Optional<SomeClass>
///////////
// Tests //
///////////
// This can be generated by using:
//
// func makesInt() -> Int { return 0 }
// func takesIntInout(i: inout Int) -> () {}
//
// class RootClassWithIVars {
// var x: Int
// var y: Int
// var z: (Int, Int)
// init() {
// }
// }
//
// class DerivedClassWithIVars : RootClassWithIVars {
// var a: Int
// override init() {
// a = makesInt()
// }
// }
//
sil [ossa] @derived_test1 : $@convention(method) (@owned DerivedClassWithIVars) -> @owned DerivedClassWithIVars {
bb0(%0 : @owned $DerivedClassWithIVars):
%1 = alloc_box $_0_0> { var τ_0_0 } <DerivedClassWithIVars>
%1a = project_box %1 : $_0_0> { var τ_0_0 } <DerivedClassWithIVars>, 0
%3 = mark_uninitialized [derivedself] %1a : $*DerivedClassWithIVars
store %0 to [init] %3 : $*DerivedClassWithIVars
// Get an int
%5 = function_ref @makesInt : $@convention(thin) () -> Int
%7 = apply %5() : $@convention(thin) () -> Int
// Initialize the 'a' ivar with the int.
%8 = load_borrow %3 : $*DerivedClassWithIVars
%9 = ref_element_addr %8 : $DerivedClassWithIVars, #DerivedClassWithIVars.a
assign %7 to %9 : $*Int
end_borrow %8 : $DerivedClassWithIVars
// Then perform the self.init call.
%11 = load [take] %3 : $*DerivedClassWithIVars
%13 = upcast %11 : $DerivedClassWithIVars to $RootClassWithIVars
%14 = function_ref @superinit : $@convention(method) (@owned RootClassWithIVars) -> @owned RootClassWithIVars
%15 = apply %14(%13) : $@convention(method) (@owned RootClassWithIVars) -> @owned RootClassWithIVars
%16 = unchecked_ref_cast %15 : $RootClassWithIVars to $DerivedClassWithIVars
store %16 to [init] %3 : $*DerivedClassWithIVars
// Finally perform the epilog.
%18 = load [copy] %3 : $*DerivedClassWithIVars
destroy_value %1 : $_0_0> { var τ_0_0 } <DerivedClassWithIVars>
return %18 : $DerivedClassWithIVars
}
// This is testing the following swift:
//
// func makesInt() -> Int { return 0 }
// func takesIntInout(i: inout Int) -> () {}
//
// class RootClassWithIVars {
// var x: Int
// var y: Int
// var z: (Int, Int)
// init() {
// }
// }
//
// class DerivedClassWithIVars : RootClassWithIVars {
// var a: Int
// override init() {
// }
// }
sil [ossa] @derived_test2 : $@convention(method) (@owned DerivedClassWithIVars) -> @owned DerivedClassWithIVars {
bb0(%0 : @owned $DerivedClassWithIVars):
%1 = alloc_box $_0_0> { var τ_0_0 } <DerivedClassWithIVars>
%1a = project_box %1 : $_0_0> { var τ_0_0 } <DerivedClassWithIVars>, 0
%3 = mark_uninitialized [derivedself] %1a : $*DerivedClassWithIVars
store %0 to [init] %3 : $*DerivedClassWithIVars
%11 = load [take] %3 : $*DerivedClassWithIVars
%13 = upcast %11 : $DerivedClassWithIVars to $RootClassWithIVars
%14 = function_ref @superinit : $@convention(method) (@owned RootClassWithIVars) -> @owned RootClassWithIVars
%15 = apply %14(%13) : $@convention(method) (@owned RootClassWithIVars) -> @owned RootClassWithIVars // expected-error {{property 'self.a' not initialized at super.init call}}
%16 = unchecked_ref_cast %15 : $RootClassWithIVars to $DerivedClassWithIVars
store %16 to [init] %3 : $*DerivedClassWithIVars
%18 = load [copy] %3 : $*DerivedClassWithIVars
destroy_value %1 : $_0_0> { var τ_0_0 } <DerivedClassWithIVars>
return %18 : $DerivedClassWithIVars
}
struct MyStruct : P {}
struct MyStruct2 {
var x: P
init(delegate: ())
init()
}
class RootClassWithNontrivialStoredProperties {
var x, y: SomeClass
init()
}
class DerivedClassWithNontrivialStoredProperties : RootClassWithNontrivialStoredProperties {
var a, b: SomeClass
override init()
}
// I was unable to find a test case that could reproduce this since there isn't
// a way before DI today to eliminate the super.init call. I believe it may have
// come from when mandatory inlining ran very early. That being said, we should
// still dot he right thing.
//
// CHECK-LABEL: sil [ossa] @test_derived_release
// CHECK: bb0(%0 : @owned $DerivedClassWithNontrivialStoredProperties):
// CHECK-NEXT: [[SELFBOX:%[0-9]+]] = alloc_stack
// CHECK-NEXT: store
// CHECK-NEXT: [[SELF:%[0-9]+]] = load [take] [[SELFBOX]]
// CHECK-NEXT: [[METATYPE:%[0-9]+]] = metatype $@thick DerivedClassWithNontrivialStoredProperties.Type
// CHECK-NEXT: dealloc_partial_ref [[SELF]] : $DerivedClassWithNontrivialStoredProperties, [[METATYPE]] : $@thick DerivedClassWithNontrivialStoredProperties.Type
// CHECK-NEXT: dealloc_stack [[SELFBOX]]
sil [ossa] @test_derived_release : $@convention(method) (@owned DerivedClassWithNontrivialStoredProperties) -> () {
bb0(%0 : @owned $DerivedClassWithNontrivialStoredProperties):
%1 = alloc_stack $DerivedClassWithNontrivialStoredProperties
%4 = mark_uninitialized [derivedself] %1 : $*DerivedClassWithNontrivialStoredProperties
store %0 to [init] %4 : $*DerivedClassWithNontrivialStoredProperties
destroy_addr %4 : $*DerivedClassWithNontrivialStoredProperties
dealloc_stack %1 : $*DerivedClassWithNontrivialStoredProperties
%13 = tuple ()
return %13 : $()
}
// I was unable to find a test case that could reproduce this since there isn't
// a way before DI today to eliminate the super.init call. I believe it may have
// come from when mandatory inlining ran very early. That being said, we should
// still dot he right thing.
//
// CHECK-LABEL: sil [ossa] @test_derived_partial_release
// CHECK: bb0([[ARG:%.*]] : @owned $DerivedClassWithNontrivialStoredProperties):
//
// Initialize the self box.
// CHECK: [[SELFBOX:%[0-9]+]] = alloc_stack
// CHECK: store [[ARG]] to [init] [[SELFBOX]]
//
// Update field of self.
// CHECK: [[FIELD_VAL:%.*]] = alloc_ref $SomeClass
// CHECK: [[SELF:%[0-9]+]] = load_borrow [[SELFBOX]]
// CHECK: [[SELF_FIELD:%.*]] = ref_element_addr [[SELF]]
// CHECK: store [[FIELD_VAL]] to [init] [[SELF_FIELD]]
// CHECK: end_borrow [[SELF]]
//
// Now we destroy the stored value.
// CHECK: [[SELF:%[0-9]+]] = load_borrow [[SELFBOX]]
// CHECK: [[SELF_FIELD:%.*]] = ref_element_addr [[SELF]]
// CHECK: destroy_addr [[SELF_FIELD]]
// CHECK: end_borrow [[SELF]]
//
// And then perform dealloc_partial_ref.
// CHECK: [[SELF:%[0-9]+]] = load [take] [[SELFBOX]]
// CHECK: [[METATYPE:%[0-9]+]] = metatype $@thick DerivedClassWithNontrivialStoredProperties.Type
// CHECK: dealloc_partial_ref [[SELF]] : $DerivedClassWithNontrivialStoredProperties, [[METATYPE]] : $@thick DerivedClassWithNontrivialStoredProperties.Type
// CHECK: dealloc_stack [[SELFBOX]]
// CHECK: } // end sil function 'test_derived_partial_release'
sil [ossa] @test_derived_partial_release : $@convention(method) (@owned DerivedClassWithNontrivialStoredProperties) -> () {
bb0(%0 : @owned $DerivedClassWithNontrivialStoredProperties):
%1 = alloc_stack $DerivedClassWithNontrivialStoredProperties
%4 = mark_uninitialized [derivedself] %1 : $*DerivedClassWithNontrivialStoredProperties
store %0 to [init] %4 : $*DerivedClassWithNontrivialStoredProperties
%8 = alloc_ref $SomeClass
%9 = load_borrow %4 : $*DerivedClassWithNontrivialStoredProperties
%10 = ref_element_addr %9 : $DerivedClassWithNontrivialStoredProperties, #DerivedClassWithNontrivialStoredProperties.a
assign %8 to %10 : $*SomeClass
end_borrow %9 : $DerivedClassWithNontrivialStoredProperties
destroy_addr %4 : $*DerivedClassWithNontrivialStoredProperties
dealloc_stack %1 : $*DerivedClassWithNontrivialStoredProperties
%13 = tuple ()
return %13 : $()
}
// <rdar://problem/18199087> DI doesn't catch use of super properties lexically inside super.init call
//
// *NOTE* There is currently a SILGen ownership bug where SILGen will emit the
// end_borrow too early. This does not need to be fixed in the short term since
// we are only going to verify swift stdlibCore. But it will need to be fixed.
//
// To recreate this:
//
// class Foo {
// var x: Int
// init() {}
// init(i: Int) {}
// }
//
// class Foo2 : Foo {
// override init() {
// super.init(i: self.x) // <--- The important part.
// }
// }
//
sil [ossa] @super_init_out_of_order : $@convention(method) (@owned DerivedClassWithIVars, Int) -> @owned DerivedClassWithIVars {
bb0(%0 : @owned $DerivedClassWithIVars, %i : $Int):
%1 = alloc_box $_0_0> { var τ_0_0 } <DerivedClassWithIVars>
%1a = project_box %1 : $_0_0> { var τ_0_0 } <DerivedClassWithIVars>, 0
%3 = mark_uninitialized [derivedself] %1a : $*DerivedClassWithIVars
store %0 to [init] %3 : $*DerivedClassWithIVars
// Initialize properties in derived class.
%8 = load_borrow %3 : $*DerivedClassWithIVars
%9 = ref_element_addr %8 : $DerivedClassWithIVars, #DerivedClassWithIVars.a
assign %i to %9 : $*Int
end_borrow %8 : $DerivedClassWithIVars
// Get the super.init function information, but don't apply it.
%11 = load [take] %3 : $*DerivedClassWithIVars
%13 = upcast %11 : $DerivedClassWithIVars to $RootClassWithIVars
%14 = function_ref @superinit : $@convention(method) (@owned RootClassWithIVars) -> @owned RootClassWithIVars
// Access a super property before super.init is called.
%13a = begin_borrow %13 : $RootClassWithIVars
%13b = unchecked_ref_cast %13a : $RootClassWithIVars to $DerivedClassWithIVars
%13c = upcast %13b : $DerivedClassWithIVars to $RootClassWithIVars
%13d = ref_element_addr %13c : $RootClassWithIVars, #RootClassWithIVars.x // expected-error {{'self' used in property access 'x' before 'super.init' call}}
load [trivial] %13d : $*Int
end_borrow %13a : $RootClassWithIVars
// Call super.init.
%15 = apply %14(%13) : $@convention(method) (@owned RootClassWithIVars) -> @owned RootClassWithIVars
%16 = unchecked_ref_cast %15 : $RootClassWithIVars to $DerivedClassWithIVars
store %16 to [init] %3 : $*DerivedClassWithIVars
%18 = load [copy] %3 : $*DerivedClassWithIVars
destroy_value %1 : $_0_0> { var τ_0_0 } <DerivedClassWithIVars>
return %18 : $DerivedClassWithIVars
}