blob: 40e26c92abb3063d788f1dd1c653bed361c23a83 [file] [log] [blame]
// RUN: %target-swift-frontend -emit-sil -O %s | %FileCheck %s
// Check that devirtualizer can properly handle concrete non-generic subclasses
// of generic classes.
// It should not crash on them.
public class Base<T> {
func foo() -> Int32 {
return 1
}
func boo() -> Int32 {
return 11
}
}
public class Derived: Base<Int> {
override func foo() -> Int32 {
return 2
}
}
// CHECK-LABEL: sil [noinline] @$s41devirt_concrete_subclass_of_generic_class5test1s5Int32VyF
@inline(never)
public func test1() -> Int32 {
let o = Derived()
return o.foo() + o.boo()
}
@inline(never)
public func test2(_ o: Derived) -> Int32 {
return o.foo() + o.boo()
}
@inline(never)
public func test3() -> Int32 {
let o: Base<Int> = Derived()
return o.foo() + o.boo()
}
@inline(never)
public func test4(_ o: Base<Int>) -> Int32 {
return o.foo() + o.boo()
}
@inline(never)
public func test5<T>(_ o: Base<T>) -> Int32 {
return o.foo() + o.boo()
}
print(test1())
print(test2(Derived()))
print(test3())
print(test4(Derived()))
print(test5(Derived()))
// Check that we handle indirect devirtualization through an intermediate
// method. rdar://problem/24993618
private class IndirectMethodCall<T> {
func bug() {
overrideMe()
}
@inline(never)
func overrideMe() { }
}
private class IndirectChildConcrete: IndirectMethodCall<Int> {
@inline(never)
override func overrideMe() { }
}
private class IndirectChildTuple<U>: IndirectMethodCall<(U, U)> {
@inline(never)
override func overrideMe() { }
}
private class IndirectChildTupleConcrete: IndirectChildTuple<Int> {
@inline(never)
override func overrideMe() { }
}
private class IndirectChildMeta<U>: IndirectMethodCall<U.Type> {
@inline(never)
override func overrideMe() { }
}
private class IndirectChildMetaConcrete: IndirectChildMeta<Int> {
@inline(never)
override func overrideMe() { }
}
private class IndirectChildBoundGeneric<U>: IndirectMethodCall<Array<U>> {
@inline(never)
override func overrideMe() { }
}
private class IndirectChildBoundGenericConcrete:
IndirectChildBoundGeneric<Int> {
@inline(never)
override func overrideMe() { }
}
private class IndirectChildFunction<U>: IndirectMethodCall<(U) -> U> {
@inline(never)
override func overrideMe() { }
}
private class IndirectChildFunctionConcrete: IndirectChildFunction<Int> {
@inline(never)
override func overrideMe() { }
}
// CHECK-LABEL: sil {{.*}} @{{.*}}test6
@inline(never)
func test6() {
// CHECK: function_ref @{{.*}}IndirectChildConcrete{{.*}}overrideMe
IndirectChildConcrete().bug()
// CHECK: function_ref @{{.*}}IndirectChildTuple{{.*}}overrideMe
IndirectChildTuple<Int>().bug()
// CHECK: function_ref @{{.*}}IndirectChildTupleConcrete{{.*}}overrideMe
IndirectChildTupleConcrete().bug()
// CHECK: function_ref @{{.*}}IndirectChildMeta{{.*}}overrideMe
IndirectChildMeta<Int>().bug()
// CHECK: function_ref @{{.*}}IndirectChildMetaConcrete{{.*}}overrideMe
IndirectChildMetaConcrete().bug()
// CHECK: function_ref @{{.*}}IndirectChildBoundGeneric{{.*}}overrideMe
IndirectChildBoundGeneric<Int>().bug()
// CHECK: function_ref @{{.*}}IndirectChildBoundGenericConcrete{{.*}}overrideMe
IndirectChildBoundGenericConcrete().bug()
// CHECK: function_ref @{{.*}}IndirectChildFunction{{.*}}overrideMe
IndirectChildFunction<Int>().bug()
// CHECK: function_ref @{{.*}}IndirectChildFunctionConcrete{{.*}}overrideMe
IndirectChildFunctionConcrete().bug()
}
print(test6())