xref: /llvm-project/clang/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp (revision f94bbfed7cf08f60e20756dce8965d2c6ed70ea1)
1 // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
2 
3 // See Test9 for test description.
4 // CHECK: @_ZTTN5Test91BE = linkonce_odr unnamed_addr constant
5 namespace Test1 {
6 
7 // Check that we don't initialize the vtable pointer in A::~A(), since the destructor body is trivial.
8 struct A {
9   virtual void f();
10   ~A();
11 };
12 
13 // CHECK-LABEL: define{{.*}} void @_ZN5Test11AD2Ev
14 // CHECK-NOT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5Test11AE, i64 0, i64 2), ptr
~A()15 A::~A()
16 {
17 }
18 
19 }
20 
21 namespace Test2 {
22 
23 // Check that we do initialize the vtable pointer in A::~A() since the destructor body isn't trivial.
24 struct A {
25   virtual void f();
26   ~A();
27 };
28 
29 // CHECK-LABEL: define{{.*}} void @_ZN5Test21AD2Ev
30 // CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test21AE, i32 0, i32 0, i32 2), ptr
~A()31 A::~A() {
32   f();
33 }
34 
35 }
36 
37 namespace Test3 {
38 
39 // Check that we don't initialize the vtable pointer in A::~A(), since the destructor body is trivial
40 // and Field's destructor body is also trivial.
41 struct Field {
~FieldTest3::Field42   ~Field() { }
43 };
44 
45 struct A {
46   virtual void f();
47   ~A();
48 
49   Field field;
50 };
51 
52 // CHECK-LABEL: define{{.*}} void @_ZN5Test31AD2Ev
53 // CHECK-NOT: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test31AE, i32 0, i32 0, i32 2), ptr
~A()54 A::~A() {
55 
56 }
57 
58 }
59 
60 namespace Test4 {
61 
62 // Check that we do initialize the vtable pointer in A::~A(), since Field's destructor body
63 // isn't trivial.
64 
65 void f();
66 
67 struct Field {
~FieldTest4::Field68   ~Field() { f(); }
69 };
70 
71 struct A {
72   virtual void f();
73   ~A();
74 
75   Field field;
76 };
77 
78 // CHECK-LABEL: define{{.*}} void @_ZN5Test41AD2Ev
79 // CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test41AE, i32 0, i32 0, i32 2), ptr
~A()80 A::~A()
81 {
82 }
83 
84 }
85 
86 namespace Test5 {
87 
88 // Check that we do initialize the vtable pointer in A::~A(), since Field's destructor isn't
89 // available in this translation unit.
90 
91 struct Field {
92   ~Field();
93 };
94 
95 struct A {
96   virtual void f();
97   ~A();
98 
99   Field field;
100 };
101 
102 // CHECK-LABEL: define{{.*}} void @_ZN5Test51AD2Ev
103 // CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test51AE, i32 0, i32 0, i32 2), ptr
~A()104 A::~A()
105 {
106 }
107 
108 }
109 
110 namespace Test6 {
111 
112 // Check that we do initialize the vtable pointer in A::~A(), since Field has a member
113 // variable with a non-trivial destructor body.
114 
115 struct NonTrivialDestructorBody {
116   ~NonTrivialDestructorBody();
117 };
118 
119 struct Field {
120   NonTrivialDestructorBody nonTrivialDestructorBody;
121 };
122 
123 struct A {
124   virtual void f();
125   ~A();
126 
127   Field field;
128 };
129 
130 // CHECK-LABEL: define{{.*}} void @_ZN5Test61AD2Ev
131 // CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test61AE, i32 0, i32 0, i32 2), ptr
~A()132 A::~A()
133 {
134 }
135 
136 }
137 
138 namespace Test7 {
139 
140 // Check that we do initialize the vtable pointer in A::~A(), since Field has a base
141 // class with a non-trivial destructor body.
142 
143 struct NonTrivialDestructorBody {
144   ~NonTrivialDestructorBody();
145 };
146 
147 struct Field : NonTrivialDestructorBody { };
148 
149 struct A {
150   virtual void f();
151   ~A();
152 
153   Field field;
154 };
155 
156 // CHECK-LABEL: define{{.*}} void @_ZN5Test71AD2Ev
157 // CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test71AE, i32 0, i32 0, i32 2), ptr
~A()158 A::~A()
159 {
160 }
161 
162 }
163 
164 namespace Test8 {
165 
166 // Check that we do initialize the vtable pointer in A::~A(), since Field has a virtual base
167 // class with a non-trivial destructor body.
168 
169 struct NonTrivialDestructorBody {
170   ~NonTrivialDestructorBody();
171 };
172 
173 struct Field : virtual NonTrivialDestructorBody { };
174 
175 struct A {
176   virtual void f();
177   ~A();
178 
179   Field field;
180 };
181 
182 // CHECK-LABEL: define{{.*}} void @_ZN5Test81AD2Ev
183 // CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test81AE, i32 0, i32 0, i32 2), ptr
~A()184 A::~A()
185 {
186 }
187 
188 }
189 
190 namespace Test9 {
191 
192 // Check that we emit a VTT for B, even though we don't initialize the vtable pointer in the destructor.
~ATest9::A193 struct A { virtual ~A () { } };
194 struct B : virtual A {};
195 struct C : virtual B {
196   virtual ~C();
197 };
~C()198 C::~C() {}
199 
200 }
201 
202 namespace Test10 {
203 
204 // Check that we don't initialize the vtable pointer in A::~A(), since the class has an anonymous union which
205 // never has its destructor invoked.
206 struct A {
207     virtual void f();
208     ~A();
209 
210     union
211     {
212         int i;
213         unsigned u;
214     };
215 };
216 
217 // CHECK-LABEL: define{{.*}} void @_ZN6Test101AD2Ev
218 // CHECK-NOT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN6Test101AE, i32 0, inrange i32 0, i32 2), ptr
~A()219 A::~A() {
220 }
221 
222 }
223 
224 namespace Test11 {
225 
226 // Check that we don't initialize the vtable pointer in A::~A(), even if the base class has a non trivial destructor.
227 struct Field {
228     ~Field();
229 };
230 
231 struct A : public Field {
232     virtual void f();
233     ~A();
234 };
235 
236 // CHECK-LABEL: define{{.*}} void @_ZN6Test111AD2Ev
237 // CHECK-NOT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN6Test111AE, i32 0, inrange i32 0, i32 2), ptr
~A()238 A::~A() {
239 }
240 
241 }
242 
243 namespace Test12 {
244 
245 // Check that we don't initialize the vtable pointer in A::~A(), since the class has an anonymous struct with trivial fields.
246 struct A {
247     virtual void f();
248     ~A();
249 
250     struct
251     {
252         int i;
253         unsigned u;
254     };
255 };
256 
257 // CHECK-LABEL: define{{.*}} void @_ZN6Test121AD2Ev
258 // CHECK-NOT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN6Test121AE, i32 0, inrange i32 0, i32 2), ptr
~A()259 A::~A() {
260 }
261 
262 }
263