xref: /minix3/external/bsd/llvm/dist/clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp (revision ebfedea0ce5bbe81e252ddf32d732e40fb633fae)
1 // RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -fdump-vtable-layouts -o %t.ll > %t
2 // RUN: FileCheck --check-prefix=EMITS-VFTABLE %s < %t.ll
3 // RUN: FileCheck --check-prefix=NO-VFTABLE %s < %t.ll
4 // RUN: FileCheck --check-prefix=CHECK-A %s < %t
5 // RUN: FileCheck --check-prefix=CHECK-B %s < %t
6 // RUN: FileCheck --check-prefix=CHECK-C %s < %t
7 // RUN: FileCheck --check-prefix=CHECK-D %s < %t
8 // RUN: FileCheck --check-prefix=CHECK-E %s < %t
9 // RUN: FileCheck --check-prefix=CHECK-F %s < %t
10 // RUN: FileCheck --check-prefix=CHECK-G %s < %t
11 // RUN: FileCheck --check-prefix=CHECK-I %s < %t
12 // RUN: FileCheck --check-prefix=CHECK-J %s < %t
13 // RUN: FileCheck --check-prefix=CHECK-K %s < %t
14 // RUN: FileCheck --check-prefix=CHECK-L %s < %t
15 // RUN: FileCheck --check-prefix=CHECK-M %s < %t
16 // RUN: FileCheck --check-prefix=CHECK-N %s < %t
17 
18 struct A {
19   // CHECK-A: VFTable for 'A' (3 entries)
20   // CHECK-A-NEXT: 0 | void A::f()
21   // CHECK-A-NEXT: 1 | void A::g()
22   // CHECK-A-NEXT: 2 | void A::h()
23   // CHECK-A: VFTable indices for 'A' (3 entries)
24   // CHECK-A-NEXT: 0 | void A::f()
25   // CHECK-A-NEXT: 1 | void A::g()
26   // CHECK-A-NEXT: 2 | void A::h()
27 
28   virtual void f();
29   virtual void g();
30   virtual void h();
31   int ia;
32 };
33 A a;
34 // EMITS-VFTABLE-DAG: @"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*]
35 
36 struct B : A {
37   // CHECK-B: VFTable for 'A' in 'B' (5 entries)
38   // CHECK-B-NEXT: 0 | void B::f()
39   // CHECK-B-NEXT: 1 | void A::g()
40   // CHECK-B-NEXT: 2 | void A::h()
41   // CHECK-B-NEXT: 3 | void B::i()
42   // CHECK-B-NEXT: 4 | void B::j()
43   // CHECK-B: VFTable indices for 'B' (3 entries)
44   // CHECK-B-NEXT: 0 | void B::f()
45   // CHECK-B-NEXT: 3 | void B::i()
46   // CHECK-B-NEXT: 4 | void B::j()
47 
48   virtual void f();  // overrides A::f()
49   virtual void i();
50   virtual void j();
51 };
52 B b;
53 // EMITS-VFTABLE-DAG: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*]
54 
55 struct C {
56   // CHECK-C: VFTable for 'C' (2 entries)
57   // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
58   // CHECK-C-NEXT: 1 | void C::f()
59   // CHECK-C: VFTable indices for 'C' (2 entries).
60   // CHECK-C-NEXT: 0 | C::~C() [scalar deleting]
61   // CHECK-C-NEXT: 1 | void C::f()
62 
63   virtual ~C();
64   virtual void f();
65 };
66 void C::f() {}
67 // NO-VFTABLE-NOT: @"\01??_7C@@6B@"
68 
69 struct D {
70   // CHECK-D: VFTable for 'D' (2 entries)
71   // CHECK-D-NEXT: 0 | void D::f()
72   // CHECK-D-NEXT: 1 | D::~D() [scalar deleting]
73   // CHECK-D: VFTable indices for 'D' (2 entries)
74   // CHECK-D-NEXT: 0 | void D::f()
75   // CHECK-D-NEXT: 1 | D::~D() [scalar deleting]
76 
77   virtual void f();
78   virtual ~D();
79 };
80 D d;
81 // EMITS-VFTABLE-DAG: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*]
82 
83 struct E : A {
84   // CHECK-E: VFTable for 'A' in 'E' (5 entries)
85   // CHECK-E-NEXT: 0 | void A::f()
86   // CHECK-E-NEXT: 1 | void A::g()
87   // CHECK-E-NEXT: 2 | void A::h()
88   // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
89   // CHECK-E-NEXT: 4 | void E::i()
90   // CHECK-E: VFTable indices for 'E' (2 entries).
91   // CHECK-E-NEXT: 3 | E::~E() [scalar deleting]
92   // CHECK-E-NEXT: 4 | void E::i()
93 
94   // ~E would be the key method, but it isn't used, and MS ABI has no key
95   // methods.
96   virtual ~E();
97   virtual void i();
98 };
99 void E::i() {}
100 // NO-VFTABLE-NOT: @"\01??_7E@@6B@"
101 
102 struct F : A {
103   // CHECK-F: VFTable for 'A' in 'F' (5 entries)
104   // CHECK-F-NEXT: 0 | void A::f()
105   // CHECK-F-NEXT: 1 | void A::g()
106   // CHECK-F-NEXT: 2 | void A::h()
107   // CHECK-F-NEXT: 3 | void F::i()
108   // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
109   // CHECK-F: VFTable indices for 'F' (2 entries).
110   // CHECK-F-NEXT: 3 | void F::i()
111   // CHECK-F-NEXT: 4 | F::~F() [scalar deleting]
112 
113   virtual void i();
114   virtual ~F();
115 };
116 F f;
117 // EMITS-VFTABLE-DAG: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant [5 x i8*]
118 
119 struct G : E {
120   // CHECK-G: VFTable for 'A' in 'E' in 'G' (6 entries)
121   // CHECK-G-NEXT: 0 | void G::f()
122   // CHECK-G-NEXT: 1 | void A::g()
123   // CHECK-G-NEXT: 2 | void A::h()
124   // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
125   // CHECK-G-NEXT: 4 | void E::i()
126   // CHECK-G-NEXT: 5 | void G::j()
127   // CHECK-G: VFTable indices for 'G' (3 entries).
128   // CHECK-G-NEXT: 0 | void G::f()
129   // CHECK-G-NEXT: 3 | G::~G() [scalar deleting]
130   // CHECK-G-NEXT: 5 | void G::j()
131 
132   virtual void f();  // overrides A::f()
133   virtual ~G();
134   virtual void j();
135 };
136 void G::j() {}
137 // NO-VFTABLE-NOT: @"\01??_7G@@6B@"
138 
139 // Test that the usual Itanium-style key method does not emit a vtable.
140 struct H {
141   virtual void f();
142 };
143 void H::f() {}
144 // NO-VFTABLE-NOT: @"\01??_7H@@6B@"
145 
146 struct Empty { };
147 
148 struct I : Empty {
149   // CHECK-I: VFTable for 'I' (2 entries)
150   // CHECK-I-NEXT: 0 | void I::f()
151   // CHECK-I-NEXT: 1 | void I::g()
152   virtual void f();
153   virtual void g();
154 };
155 
156 I i;
157 
158 struct J {
159   // CHECK-J: VFTable for 'J' (6 entries)
160   // CHECK-J-NEXT: 0 | void J::foo(long)
161   // CHECK-J-NEXT: 1 | void J::foo(int)
162   // CHECK-J-NEXT: 2 | void J::foo(short)
163   // CHECK-J-NEXT: 3 | void J::bar(long)
164   // CHECK-J-NEXT: 4 | void J::bar(int)
165   // CHECK-J-NEXT: 5 | void J::bar(short)
166   virtual void foo(short);
167   virtual void bar(short);
168   virtual void foo(int);
169   virtual void bar(int);
170   virtual void foo(long);
171   virtual void bar(long);
172 };
173 
174 J j;
175 
176 struct K : J {
177   // CHECK-K: VFTable for 'J' in 'K' (9 entries)
178   // CHECK-K-NEXT: 0 | void J::foo(long)
179   // CHECK-K-NEXT: 1 | void J::foo(int)
180   // CHECK-K-NEXT: 2 | void J::foo(short)
181   // CHECK-K-NEXT: 3 | void J::bar(long)
182   // CHECK-K-NEXT: 4 | void J::bar(int)
183   // CHECK-K-NEXT: 5 | void J::bar(short)
184   // CHECK-K-NEXT: 6 | void K::bar(double)
185   // CHECK-K-NEXT: 7 | void K::bar(float)
186   // CHECK-K-NEXT: 8 | void K::foo(float)
187   virtual void bar(float);
188   virtual void foo(float);
189   virtual void bar(double);
190 };
191 
192 K k;
193 
194 struct L : J {
195   // CHECK-L: VFTable for 'J' in 'L' (9 entries)
196   // CHECK-L-NEXT: 0 | void J::foo(long)
197   // CHECK-L-NEXT: 1 | void L::foo(int)
198   // CHECK-L-NEXT: 2 | void J::foo(short)
199   // CHECK-L-NEXT: 3 | void J::bar(long)
200   // CHECK-L-NEXT: 4 | void J::bar(int)
201   // CHECK-L-NEXT: 5 | void J::bar(short)
202   // CHECK-L-NEXT: 6 | void L::foo(float)
203   // CHECK-L-NEXT: 7 | void L::bar(double)
204   // CHECK-L-NEXT: 8 | void L::bar(float)
205 
206   // This case is interesting. Since the J::foo(int) override is the first method in
207   // the class, foo(float) precedes the bar(double) and bar(float) in the vftable.
208   virtual void foo(int);
209   virtual void bar(float);
210   virtual void foo(float);
211   virtual void bar(double);
212 };
213 
214 L l;
215 
216 struct M : J {
217   // CHECK-M: VFTable for 'J' in 'M' (11 entries)
218   // CHECK-M-NEXT:  0 | void J::foo(long)
219   // CHECK-M-NEXT:  1 | void M::foo(int)
220   // CHECK-M-NEXT:  2 | void J::foo(short)
221   // CHECK-M-NEXT:  3 | void J::bar(long)
222   // CHECK-M-NEXT:  4 | void J::bar(int)
223   // CHECK-M-NEXT:  5 | void J::bar(short)
224   // CHECK-M-NEXT:  6 | void M::foo(float)
225   // CHECK-M-NEXT:  7 | void M::spam(long)
226   // CHECK-M-NEXT:  8 | void M::spam(int)
227   // CHECK-M-NEXT:  9 | void M::bar(double)
228   // CHECK-M-NEXT: 10 | void M::bar(float)
229 
230   virtual void foo(int);
231   virtual void spam(int);
232   virtual void bar(float);
233   virtual void bar(double);
234   virtual void foo(float);
235   virtual void spam(long);
236 };
237 
238 M m;
239 
240 struct N {
241   // CHECK-N: VFTable for 'N' (4 entries)
242   // CHECK-N-NEXT: 0 | void N::operator+(int)
243   // CHECK-N-NEXT: 1 | void N::operator+(short)
244   // CHECK-N-NEXT: 2 | void N::operator*(int)
245   // CHECK-N-NEXT: 3 | void N::operator*(short)
246   virtual void operator+(short);
247   virtual void operator*(short);
248   virtual void operator+(int);
249   virtual void operator*(int);
250 };
251 
252 N n;
253