1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
// 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())
|