Files
swift-mirror/test/SILGen/auto_generated_super_init_call.swift
Chris Lattner fd69300bdf rework lowering of 'self' in class init methods to use normal cleanups and variable
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
2015-04-21 16:43:46 +00:00

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