blob: 99fc383af79f8454228a0878a3c447b81d1dae67 [file] [log] [blame]
// RUN: %target-sil-opt -enable-sil-verify-all %s -specdevirt | FileCheck %s
sil_stage canonical
@objc class MyNSObject {}
private class Base : MyNSObject {
override init()
@inline(never) func foo()
}
private class Sub : Base {
override init()
@inline(never) override func foo()
}
sil private [noinline] @_TBaseFooFun : $@convention(method) (@guaranteed Base) -> () {
bb0(%0 : $Base):
%1 = tuple()
return %1 : $()
}
sil private [noinline] @_TSubFooFun : $@convention(method) (@guaranteed Sub) -> () {
bb0(%0 : $Sub):
%1 = tuple()
return %1 : $()
}
sil_vtable Base {
#Base.foo!1: _TBaseFooFun
}
sil_vtable Sub {
#Base.foo!1: _TSubFooFun
}
sil @test_objc_ancestry : $@convention(thin) (@guaranteed Base) -> () {
bb0(%0: $Base):
%1 = class_method %0 : $Base, #Base.foo!1 : (Base) -> () -> () , $@convention(method) (@guaranteed Base) -> ()
%2 = apply %1(%0) : $@convention(method) (@guaranteed Base) -> ()
%3 = tuple()
return %3 : $()
}
// Make sure we leave the generic method call because an objc derived class can be extended at runtime.
// CHECK-LABEL: sil @test_objc_ancestry
// CHECK: bb0
// CHECK: [[METH:%.*]] = class_method %0 : $Base, #Base.foo!1 : (Base) -> () -> () , $@convention(method) (@guaranteed Base) -> ()
// CHECK: checked_cast_br [exact] %0 : $Base to $Base, bb{{.*}}, bb[[CHECK2:[0-9]+]]
// CHECK: bb[[CHECK2]]{{.*}}:
// CHECK: checked_cast_br [exact] %0 : $Base to $Sub, bb{{.*}}, bb[[GENCALL:[0-9]+]]
// CHECK: bb[[GENCALL]]{{.*}}:
// CHECK: apply [[METH]]
struct MyValue {}
private class Generic<T> : MyNSObject {
override init()
}
private class Base2 : Generic<MyValue> {
override init()
@inline(never) func foo()
}
private class Sub2 : Base2 {
override init()
@inline(never) override func foo()
}
sil private [noinline] @_TBase2FooFun : $@convention(method) (@guaranteed Base2) -> () {
bb0(%0 : $Base2):
%1 = tuple()
return %1 : $()
}
sil private [noinline] @_TSub2FooFun : $@convention(method) (@guaranteed Sub2) -> () {
bb0(%0 : $Sub2):
%1 = tuple()
return %1 : $()
}
sil_vtable Base2 {
#Base2.foo!1: _TBase2FooFun
}
sil_vtable Sub2 {
#Base2.foo!1: _TSub2FooFun
}
sil @test_objc_ancestry2 : $@convention(thin) (@guaranteed Base2) -> () {
bb0(%0: $Base2):
%1 = class_method %0 : $Base2, #Base2.foo!1 : (Base2) -> () -> () , $@convention(method) (@guaranteed Base2) -> ()
%2 = apply %1(%0) : $@convention(method) (@guaranteed Base2) -> ()
%3 = tuple()
return %3 : $()
}
// CHECK-LABEL: sil @test_objc_ancestry2
// CHECK: bb0
// CHECK: [[METH:%.*]] = class_method %0 : $Base2, #Base2.foo!1 : (Base2) -> () -> () , $@convention(method) (@guaranteed Base2) -> ()
// CHECK: checked_cast_br [exact] %0 : $Base2 to $Base2, bb{{.*}}, bb[[CHECK2:[0-9]+]]
// CHECK: bb[[CHECK2]]{{.*}}:
// CHECK: checked_cast_br [exact] %0 : $Base2 to $Sub2, bb{{.*}}, bb[[GENCALL:[0-9]+]]
// CHECK: bb[[GENCALL]]{{.*}}:
// CHECK: apply [[METH]]