mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
emission instead of hand coded magic. Eliminating special cases allows simplifying other parts of the compiler, and this probably helps the error handling initiative as well. This uses the (horrible) new null_class instruction to properly model rebinding of self. The code that SILGen was producing before was wildly incorrect and we only got lucky that it seemed to work in most cases before. NFC except that SILGen tests see the new null_class instructions, and we get better location info for 'return nil' for obscure reasons that don't really matter. Swift SVN r27530
135 lines
5.0 KiB
Swift
135 lines
5.0 KiB
Swift
// RUN: %target-swift-frontend -emit-silgen %s | FileCheck %s
|
|
|
|
// Test that we emit a call to super.init at the end of the initializer, when none has been previously added.
|
|
|
|
class Parent {
|
|
init() {}
|
|
}
|
|
|
|
class SomeDerivedClass : Parent {
|
|
var y: Int
|
|
func foo() {}
|
|
|
|
override init() {
|
|
y = 42
|
|
// CHECK-LABEL: sil hidden @_TFC30auto_generated_super_init_call16SomeDerivedClasscfMS0_FT_S0_ : $@convention(method) (@owned SomeDerivedClass) -> @owned SomeDerivedClass
|
|
// CHECK: integer_literal $Builtin.Int2048, 42
|
|
// CHECK: [[SELFLOAD:%[0-9]+]] = load [[SELF:%[0-9]+]] : $*SomeDerivedClass
|
|
// CHECK-NEXT: [[PARENT:%[0-9]+]] = upcast [[SELFLOAD]] : $SomeDerivedClass to $Parent
|
|
// CHECK-NEXT: function_ref auto_generated_super_init_call.Parent.init
|
|
// CHECK-NEXT: [[INITCALL1:%[0-9]+]] = function_ref @_TFC30auto_generated_super_init_call6ParentcfMS0_FT_S0_
|
|
// CHECK-NEXT: [[RES1:%[0-9]+]] = apply [[INITCALL1]]([[PARENT]])
|
|
// CHECK-NEXT: = null_class $SomeDerivedClass
|
|
// CHECK-NEXT: store {{.*}} to [[SELF]] : $*SomeDerivedClass
|
|
// CHECK-NEXT: [[DOWNCAST:%[0-9]+]] = unchecked_ref_cast [[RES1]] : $Parent to $SomeDerivedClass
|
|
// CHECK-NEXT: store [[DOWNCAST]] to [[SELF]] : $*SomeDerivedClass
|
|
}
|
|
|
|
init(x: Int) {
|
|
y = x
|
|
// CHECK-LABEL: sil hidden @_TFC30auto_generated_super_init_call16SomeDerivedClasscfMS0_FT1xSi_S0_ : $@convention(method) (Int, @owned SomeDerivedClass) -> @owned SomeDerivedClass
|
|
// CHECK: function_ref @_TFC30auto_generated_super_init_call6ParentcfMS0_FT_S0_ : $@convention(method) (@owned Parent) -> @owned Parent
|
|
}
|
|
|
|
init(b: Bool) {
|
|
if b {
|
|
y = 0
|
|
return
|
|
} else {
|
|
y = 10
|
|
}
|
|
return
|
|
// Check that we are emittng the super.init expr into the epilog block.
|
|
|
|
// CHECK-LABEL: sil hidden @_TFC30auto_generated_super_init_call16SomeDerivedClasscfMS0_FT1bSb_S0_ : $@convention(method) (Bool, @owned SomeDerivedClass) -> @owned SomeDerivedClass
|
|
// CHECK: function_ref @_TFC30auto_generated_super_init_call6ParentcfMS0_FT_S0_ : $@convention(method) (@owned Parent) -> @owned Parent
|
|
// CHECK-NEXT: apply
|
|
// CHECK-NEXT: = null_class $SomeDerivedClass
|
|
// CHECK-NEXT: store {{.*}} to {{.*}} : $*SomeDerivedClass
|
|
// CHECK-NEXT: unchecked_ref_cast
|
|
// CHECK-NEXT: store
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: strong_retain
|
|
// CHECK-NEXT: strong_release
|
|
// CHECK-NEXT: return
|
|
}
|
|
|
|
// One init has a call to super init. Make sure we don't instert more than one.
|
|
init(b: Bool, i: Int) {
|
|
if (b) {
|
|
y = i
|
|
} else {
|
|
y = 0
|
|
}
|
|
|
|
super.init()
|
|
// CHECK-LABEL: sil hidden @_TFC30auto_generated_super_init_call16SomeDerivedClasscfMS0_FT1bSb1iSi_S0_ : $@convention(method) (Bool, Int, @owned SomeDerivedClass) -> @owned SomeDerivedClass
|
|
// CHECK: function_ref @_TFC30auto_generated_super_init_call6ParentcfMS0_FT_S0_ : $@convention(method) (@owned Parent) -> @owned Parent
|
|
// CHECK-NOT: function_ref @_TFC30auto_generated_super_init_call6ParentcfMS0_FT_S0_
|
|
// CHECK: return
|
|
}
|
|
}
|
|
|
|
// Check that we do call super.init.
|
|
class HasNoIVars : Parent {
|
|
override init() {
|
|
// CHECK-LABEL: sil hidden @_TFC30auto_generated_super_init_call10HasNoIVarscfMS0_FT_S0_ : $@convention(method) (@owned HasNoIVars) -> @owned HasNoIVars
|
|
// CHECK: function_ref @_TFC30auto_generated_super_init_call6ParentcfMS0_FT_S0_
|
|
}
|
|
}
|
|
|
|
// Check that we don't call super.init.
|
|
class ParentLess {
|
|
var y: Int
|
|
init() {
|
|
y = 0
|
|
}
|
|
}
|
|
|
|
class Grandparent {
|
|
init() {}
|
|
}
|
|
// This should have auto-generated default initializer.
|
|
class ParentWithNoExplicitInit : Grandparent {
|
|
}
|
|
// Check that we add a call to super.init.
|
|
class ChildOfParentWithNoExplicitInit : ParentWithNoExplicitInit {
|
|
var y: Int
|
|
override init() {
|
|
y = 10
|
|
// CHECK-LABEL: sil hidden @_TFC30auto_generated_super_init_call31ChildOfParentWithNoExplicitInitcfMS0_FT_S0_
|
|
// CHECK: function_ref @_TFC30auto_generated_super_init_call24ParentWithNoExplicitInitcfMS0_FT_S0_ : $@convention(method) (@owned ParentWithNoExplicitInit) -> @owned ParentWithNoExplicitInit
|
|
}
|
|
}
|
|
|
|
// This should have auto-generated default initializer.
|
|
class ParentWithNoExplicitInit2 : Grandparent {
|
|
var i: Int = 0
|
|
}
|
|
// Check that we add a call to super.init.
|
|
class ChildOfParentWithNoExplicitInit2 : ParentWithNoExplicitInit2 {
|
|
var y: Int
|
|
override init() {
|
|
y = 10
|
|
// CHECK-LABEL: sil hidden @_TFC30auto_generated_super_init_call32ChildOfParentWithNoExplicitInit2cfMS0_FT_S0_
|
|
// CHECK: function_ref @_TFC30auto_generated_super_init_call25ParentWithNoExplicitInit2cfMS0_FT_S0_ : $@convention(method) (@owned ParentWithNoExplicitInit2) -> @owned ParentWithNoExplicitInit2
|
|
}
|
|
}
|
|
|
|
// Do not insert the call nor warn - the user should call init(5).
|
|
class ParentWithNoDefaultInit {
|
|
var i: Int
|
|
init(x: Int) {
|
|
i = x
|
|
}
|
|
}
|
|
class ChildOfParentWithNoDefaultInit : ParentWithNoDefaultInit {
|
|
var y: Int
|
|
init() {
|
|
// CHECK-LABEL: sil hidden @_TFC30auto_generated_super_init_call30ChildOfParentWithNoDefaultInitcfMS0_FT_S0_ : $@convention(method) (@owned ChildOfParentWithNoDefaultInit) -> @owned ChildOfParentWithNoDefaultInit
|
|
// CHECK: bb0
|
|
// CHECK-NOT: apply
|
|
// CHECK: return
|
|
}
|
|
}
|