// 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 { func foo() -> Int32 { return 1 } func boo() -> Int32 { return 11 } } public class Derived: Base { override func foo() -> Int32 { return 2 } } // CHECK-LABEL: sil [noinline] @_T041devirt_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 = Derived() return o.foo() + o.boo() } @inline(never) public func test4(_ o: Base) -> Int32 { return o.foo() + o.boo() } @inline(never) public func test5(_ o: Base) -> 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 { func bug() { overrideMe() } @inline(never) func overrideMe() { } } private class IndirectChildConcrete: IndirectMethodCall { @inline(never) override func overrideMe() { } } private class IndirectChildTuple: IndirectMethodCall<(U, U)> { @inline(never) override func overrideMe() { } } private class IndirectChildTupleConcrete: IndirectChildTuple { @inline(never) override func overrideMe() { } } private class IndirectChildMeta: IndirectMethodCall { @inline(never) override func overrideMe() { } } private class IndirectChildMetaConcrete: IndirectChildMeta { @inline(never) override func overrideMe() { } } private class IndirectChildBoundGeneric: IndirectMethodCall> { @inline(never) override func overrideMe() { } } private class IndirectChildBoundGenericConcrete: IndirectChildBoundGeneric { @inline(never) override func overrideMe() { } } private class IndirectChildFunction: IndirectMethodCall<(U) -> U> { @inline(never) override func overrideMe() { } } private class IndirectChildFunctionConcrete: IndirectChildFunction { @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().bug() // CHECK: function_ref @{{.*}}IndirectChildTupleConcrete{{.*}}overrideMe IndirectChildTupleConcrete().bug() // CHECK: function_ref @{{.*}}IndirectChildMeta{{.*}}overrideMe IndirectChildMeta().bug() // CHECK: function_ref @{{.*}}IndirectChildMetaConcrete{{.*}}overrideMe IndirectChildMetaConcrete().bug() // CHECK: function_ref @{{.*}}IndirectChildBoundGeneric{{.*}}overrideMe IndirectChildBoundGeneric().bug() // CHECK: function_ref @{{.*}}IndirectChildBoundGenericConcrete{{.*}}overrideMe IndirectChildBoundGenericConcrete().bug() // CHECK: function_ref @{{.*}}IndirectChildFunction{{.*}}overrideMe IndirectChildFunction().bug() // CHECK: function_ref @{{.*}}IndirectChildFunctionConcrete{{.*}}overrideMe IndirectChildFunctionConcrete().bug() } print(test6())