| // RUN: %target-sil-opt -enable-sil-ownership -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 @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 @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 @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 @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 @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 @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 @super_init_out_of_order : $@convention(method) (@owned DerivedClassWithIVars, Int) -> @owned DerivedClassWithIVars { |
| bb0(%0 : @owned $DerivedClassWithIVars, %i : @trivial $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 |
| } |