Files
swift-mirror/test/SILOptimizer/definite_init_markuninitialized_derivedself.sil
Michael Gottesman f854547c55 [ownership] Enable ownership verification by default.
I also removed the -verify-sil-ownership flag in favor of a disable flag
-disable-sil-ownership-verifier. I used this on only two tests that still need
work to get them to pass with ownership, but whose problems are well understood,
small corner cases. I am going to fix them in follow on commits. I detail them
below:

1. SILOptimizer/definite_init_inout_super_init.swift. This is a test case where
DI is supposed to error. The only problem is that we crash before we error since
the code emitting by SILGen to trigger this error does not pass ownership
invariants. I have spoken with JoeG about this and he suggested that I fix this
earlier in the compiler. Since we do not run the ownership verifier without
asserts enabled, this should not affect compiler users. Given that it has
triggered DI errors previously I think it is safe to disable ownership here.

2. PrintAsObjC/extensions.swift. In this case, the signature generated by type
lowering for one of the thunks here uses an unsafe +0 return value instead of
doing an autorelease return. The ownership checker rightly flags this leak. This
is going to require either an AST level change or a change to TypeLowering. I
think it is safe to turn this off since it is such a corner case that it was
found by a test that has nothing to do with it.

rdar://43398898
2019-03-25 00:11:52 -07:00

280 lines
10 KiB
Plaintext

// 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
}