vtable-layout.cpp revision 76f1aa7658c34532785e6f44c99af65f3e4bd194
1// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm-only -fdump-vtable-layouts 2>&1 | FileCheck %s
2namespace Test1 {
3
4// CHECK:      Vtable for 'Test1::A' (3 entries).
5// CHECK-NEXT:   0 | offset_to_top (0)
6// CHECK-NEXT:   1 | Test1::A RTTI
7// CHECK-NEXT:       -- (Test1::A, 0) vtable address --
8// CHECK-NEXT:   2 | void Test1::A::f()
9struct A {
10  virtual void f();
11};
12void A::f() { }
13
14}
15
16namespace Test2 {
17
18// This is a smoke test of the vtable dumper.
19// CHECK:      Vtable for 'Test2::A' (9 entries).
20// CHECK-NEXT:   0 | offset_to_top (0)
21// CHECK-NEXT:   1 | Test2::A RTTI
22// CHECK-NEXT:       -- (Test2::A, 0) vtable address --
23// CHECK-NEXT:   2 | void Test2::A::f()
24// CHECK-NEXT:   3 | void Test2::A::f() const
25// CHECK-NEXT:   4 | Test2::A *Test2::A::g(int)
26// CHECK-NEXT:   5 | Test2::A::~A() [complete]
27// CHECK-NEXT:   6 | Test2::A::~A() [deleting]
28// CHECK-NEXT:   7 | void Test2::A::h()
29// CHECK-NEXT:   8 | Test2::A &Test2::A::operator=(Test2::A const &)
30struct A {
31  virtual void f();
32  virtual void f() const;
33
34  virtual A* g(int a);
35  virtual ~A();
36  virtual void h();
37  virtual A& operator=(const A&);
38};
39void A::f() { }
40
41// Another simple vtable dumper test.
42
43// CHECK:     Vtable for 'Test2::B' (6 entries).
44// CHECK-NEXT:  0 | offset_to_top (0)
45// CHECK-NEXT:  1 | Test2::B RTTI
46// CHECK-NEXT:    -- (Test2::B, 0) vtable address --
47// CHECK-NEXT:  2 | void Test2::B::f()
48// CHECK-NEXT:  3 | void Test2::B::g() [pure]
49// CHECK-NEXT:  4 | Test2::B::~B() [complete] [pure]
50// CHECK-NEXT:  5 | Test2::B::~B() [deleting] [pure]
51struct B {
52  virtual void f();
53  virtual void g() = 0;
54  virtual ~B() = 0;
55};
56void B::f() { }
57
58}
59
60namespace Test3 {
61
62// If a function in a derived class overrides a function in a primary base,
63// then the function should not have an entry in the derived class (unless the return
64// value requires adjusting).
65
66// CHECK:      Vtable for 'Test3::A' (3 entries).
67// CHECK-NEXT:   0 | offset_to_top (0)
68// CHECK-NEXT:   1 | Test3::A RTTI
69// CHECK-NEXT:       -- (Test3::A, 0) vtable address --
70// CHECK-NEXT:   2 | void Test3::A::f()
71struct A {
72  virtual void f();
73};
74void A::f() { }
75
76// CHECK:     Vtable for 'Test3::B' (4 entries).
77// CHECK-NEXT:  0 | offset_to_top (0)
78// CHECK-NEXT:  1 | Test3::B RTTI
79// CHECK-NEXT:      -- (Test3::A, 0) vtable address --
80// CHECK-NEXT:      -- (Test3::B, 0) vtable address --
81// CHECK-NEXT:  2 | void Test3::B::f()
82// CHECK-NEXT:  3 | void Test3::B::g()
83struct B : A {
84  virtual void f();
85  virtual void g();
86};
87void B::f() { }
88
89// CHECK:     Vtable for 'Test3::C' (5 entries).
90// CHECK-NEXT:  0 | offset_to_top (0)
91// CHECK-NEXT:  1 | Test3::C RTTI
92// CHECK-NEXT:     -- (Test3::A, 0) vtable address --
93// CHECK-NEXT:     -- (Test3::C, 0) vtable address --
94// CHECK-NEXT:  2 | void Test3::A::f()
95// CHECK-NEXT:  3 | void Test3::C::g()
96// CHECK-NEXT:  4 | void Test3::C::h()
97struct C : A {
98  virtual void g();
99  virtual void h();
100};
101void C::g() { }
102
103// CHECK:     Vtable for 'Test3::D' (5 entries).
104// CHECK-NEXT:  0 | offset_to_top (0)
105// CHECK-NEXT:  1 | Test3::D RTTI
106// CHECK-NEXT:     -- (Test3::A, 0) vtable address --
107// CHECK-NEXT:     -- (Test3::B, 0) vtable address --
108// CHECK-NEXT:     -- (Test3::D, 0) vtable address --
109// CHECK-NEXT:  2 | void Test3::D::f()
110// CHECK-NEXT:  3 | void Test3::D::g()
111// CHECK-NEXT:  4 | void Test3::D::h()
112struct D : B {
113  virtual void f();
114  virtual void g();
115  virtual void h();
116};
117
118void D::f() { }
119}
120
121namespace Test4 {
122
123// Test non-virtual result adjustments.
124
125struct R1 { int r1; };
126struct R2 { int r2; };
127struct R3 : R1, R2 { int r3; };
128
129struct A {
130  virtual R2 *f();
131};
132
133// CHECK:     Vtable for 'Test4::B' (4 entries).
134// CHECK-NEXT:  0 | offset_to_top (0)
135// CHECK-NEXT:  1 | Test4::B RTTI
136// CHECK-NEXT:      -- (Test4::A, 0) vtable address --
137// CHECK-NEXT:      -- (Test4::B, 0) vtable address --
138// CHECK-NEXT:  2 | Test4::R3 *Test4::B::f()
139// CHECK-NEXT:      [return adjustment: 4 non-virtual]
140// CHECK-NEXT:  3 | Test4::R3 *Test4::B::f()
141
142struct B : A {
143  virtual R3 *f();
144};
145R3 *B::f() { return 0; }
146
147// Test virtual result adjustments.
148struct V1 { int v1; };
149struct V2 : virtual V1 { int v1; };
150
151struct C {
152  virtual V1 *f();
153};
154
155// CHECK:     Vtable for 'Test4::D' (4 entries).
156// CHECK-NEXT:   0 | offset_to_top (0)
157// CHECK-NEXT:   1 | Test4::D RTTI
158// CHECK-NEXT:       -- (Test4::C, 0) vtable address --
159// CHECK-NEXT:       -- (Test4::D, 0) vtable address --
160// CHECK-NEXT:   2 | Test4::V2 *Test4::D::f()
161// CHECK-NEXT:       [return adjustment: 0 non-virtual, -24 vbase offset offset]
162// CHECK-NEXT:   3 | Test4::V2 *Test4::D::f()
163struct D : C {
164  virtual V2 *f();
165};
166V2 *D::f() { return 0; };
167
168// Virtual result adjustments with an additional non-virtual adjustment.
169struct V3 : virtual R3 { int r3; };
170
171// CHECK:     Vtable for 'Test4::E' (4 entries).
172// CHECK-NEXT:   0 | offset_to_top (0)
173// CHECK-NEXT:   1 | Test4::E RTTI
174// CHECK-NEXT:       -- (Test4::A, 0) vtable address --
175// CHECK-NEXT:       -- (Test4::E, 0) vtable address --
176// CHECK-NEXT:   2 | Test4::V3 *Test4::E::f()
177// CHECK-NEXT:       [return adjustment: 4 non-virtual, -24 vbase offset offset]
178// CHECK-NEXT:   3 | Test4::V3 *Test4::E::f()
179
180struct E : A {
181  virtual V3 *f();
182};
183V3 *E::f() { return 0;}
184
185// Test that a pure virtual member doesn't get a thunk.
186
187// CHECK:     Vtable for 'Test4::F' (5 entries).
188// CHECK-NEXT:   0 | offset_to_top (0)
189// CHECK-NEXT:   1 | Test4::F RTTI
190// CHECK-NEXT:       -- (Test4::A, 0) vtable address --
191// CHECK-NEXT:       -- (Test4::F, 0) vtable address --
192// CHECK-NEXT:   2 | Test4::R3 *Test4::F::f() [pure]
193// CHECK-NEXT:   3 | void Test4::F::g()
194// CHECK-NEXT:   4 | Test4::R3 *Test4::F::f() [pure]
195struct F : A {
196  virtual void g();
197  virtual R3 *f() = 0;
198};
199void F::g() { }
200
201}
202
203namespace Test5 {
204
205// Simple secondary vtables without this-adjustments.
206struct A {
207  virtual void f();
208  virtual void g();
209  int a;
210};
211
212struct B1 : A {
213  virtual void f();
214  int b1;
215};
216
217struct B2 : A {
218  virtual void g();
219  int b2;
220};
221
222// CHECK:     Vtable for 'Test5::C' (9 entries).
223// CHECK-NEXT:   0 | offset_to_top (0)
224// CHECK-NEXT:   1 | Test5::C RTTI
225// CHECK-NEXT:       -- (Test5::A, 0) vtable address --
226// CHECK-NEXT:       -- (Test5::B1, 0) vtable address --
227// CHECK-NEXT:       -- (Test5::C, 0) vtable address --
228// CHECK-NEXT:   2 | void Test5::B1::f()
229// CHECK-NEXT:   3 | void Test5::A::g()
230// CHECK-NEXT:   4 | void Test5::C::h()
231// CHECK-NEXT:   5 | offset_to_top (-16)
232// CHECK-NEXT:   6 | Test5::C RTTI
233// CHECK-NEXT:       -- (Test5::A, 16) vtable address --
234// CHECK-NEXT:       -- (Test5::B2, 16) vtable address --
235// CHECK-NEXT:   7 | void Test5::A::f()
236// CHECK-NEXT:   8 | void Test5::B2::g()
237struct C : B1, B2 {
238  virtual void h();
239};
240void C::h() { }
241}
242
243// For now, just verify this doesn't crash.
244namespace test0 {
245  struct Obj {};
246
247  struct Base {           virtual const Obj *foo() = 0; };
248  struct Derived : Base { virtual       Obj *foo() { return new Obj(); } };
249
250  void test(Derived *D) { D->foo(); }
251}
252