1 // RUN: %clang_cc1 -fno-rtti %s -emit-llvm -o %t -triple=i386-pc-win32 -fdump-vtable-layouts 2>&1 | FileCheck --check-prefix=VFTABLES %s
2 // RUN: FileCheck --check-prefix=GLOBALS %s < %t
3 // RUN: FileCheck --check-prefix=CODEGEN %s < %t
4 
5 namespace test1 {
6 
7 // Some covariant types.
8 struct A { int a; };
9 struct B { int b; };
10 struct C : A, B { int c; };
11 struct D : C { int d; };
12 struct E : D { int e; };
13 
14 // One base class and two overrides, all with covariant return types.
15 struct H     { virtual B *foo(); };
16 struct I : H { virtual C *foo(); };
17 struct J : I { virtual D *foo(); J(); };
18 struct K : J { virtual E *foo(); K(); };
19 
20 J::J() {}
21 
22 // VFTABLES-LABEL: VFTable for 'test1::H' in 'test1::I' in 'test1::J' (3 entries).
23 // VFTABLES:    0 | test1::D *test1::J::foo()
24 // VFTABLES:         [return adjustment: 4 non-virtual]
25 // VFTABLES:    1 | test1::D *test1::J::foo()
26 // VFTABLES:    2 | test1::D *test1::J::foo()
27 
28 // GLOBALS-LABEL: @"\01??_7J@test1@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*]
29 // GLOBALS: @"\01?foo@J@test1@@QAEPAUB@2@XZ"
30 // GLOBALS: @"\01?foo@J@test1@@QAEPAUC@2@XZ"
31 // GLOBALS: @"\01?foo@J@test1@@QAEPAUD@2@XZ"
32 // FIXME: Should be UAEPAUD.
33 
34 K::K() {}
35 
36 // VFTABLES-LABEL: VFTable for 'test1::H' in 'test1::I' in 'test1::J' in 'test1::K' (4 entries).
37 // VFTABLES:   0 | test1::E *test1::K::foo()
38 // VFTABLES:        [return adjustment: 4 non-virtual]
39 // VFTABLES:   1 | test1::E *test1::K::foo()
40 // VFTABLES:   2 | test1::E *test1::K::foo()
41 // VFTABLES:   3 | test1::E *test1::K::foo()
42 
43 // Only B to C requires adjustment, but we get 3 thunks in K's vftable, two of
44 // which are trivial.
45 // GLOBALS-LABEL: @"\01??_7K@test1@@6B@" = linkonce_odr unnamed_addr constant [4 x i8*]
46 // GLOBALS: @"\01?foo@K@test1@@QAEPAUB@2@XZ"
47 // GLOBALS: @"\01?foo@K@test1@@QAEPAUC@2@XZ"
48 // GLOBALS: @"\01?foo@K@test1@@QAEPAUD@2@XZ"
49 // GLOBALS: @"\01?foo@K@test1@@QAEPAUE@2@XZ"
50 // FIXME: Should be UAEPAUE.
51 
52 //  This thunk has a return adjustment.
53 // CODEGEN-LABEL: define {{.*}} @"\01?foo@K@test1@@QAEPAUB@2@XZ"
54 // CODEGEN: call {{.*}} @"\01?foo@K@test1@@UAEPAUE@2@XZ"
55 // CODEGEN: icmp {{.*}}, null
56 // CODEGEN: getelementptr
57 // CODEGEN: ret
58 
59 //  These two don't.
60 // CODEGEN-LABEL: define {{.*}} @"\01?foo@K@test1@@QAEPAUC@2@XZ"
61 // CODEGEN: call {{.*}} @"\01?foo@K@test1@@UAEPAUE@2@XZ"
62 // CODEGEN-NEXT: ret
63 
64 // CODEGEN-LABEL: define {{.*}} @"\01?foo@K@test1@@QAEPAUD@2@XZ"
65 // CODEGEN: call {{.*}} @"\01?foo@K@test1@@UAEPAUE@2@XZ"
66 // CODEGEN-NEXT: ret
67 
68 }
69 
70 namespace test2 {
71 
72 // Covariant types.  D* is not trivially convertible to C*.
73 struct A { int a; };
74 struct B { int b; };
75 struct C : B { int c; };
76 struct D : A, C { int d; };
77 struct E : D { int e; };
78 
79 // J's foo will require an adjusting thunk, and K will require a trivial thunk.
80 struct H     { virtual B *foo(); };
81 struct I : H { virtual C *foo(); };
82 struct J : I { virtual D *foo(); J(); };
83 struct K : J { virtual E *foo(); K(); };
84 
85 J::J() {}
86 
87 // VFTABLES-LABEL: VFTable for 'test2::H' in 'test2::I' in 'test2::J' (2 entries).
88 // VFTABLES:    0 | test2::D *test2::J::foo()
89 // VFTABLES:         [return adjustment: 4 non-virtual]
90 // VFTABLES:    1 | test2::D *test2::J::foo()
91 
92 // GLOBALS-LABEL: @"\01??_7J@test2@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*]
93 
94 K::K() {}
95 
96 // VFTABLES-LABEL: VFTable for 'test2::H' in 'test2::I' in 'test2::J' in 'test2::K' (3 entries).
97 // VFTABLES:    0 | test2::E *test2::K::foo()
98 // VFTABLES:         [return adjustment: 4 non-virtual]
99 // VFTABLES:    1 | test2::E *test2::K::foo()
100 // VFTABLES:    2 | test2::E *test2::K::foo()
101 
102 // GLOBALS-LABEL: @"\01??_7K@test2@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*]
103 
104 }
105