1 // RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-NONOPT %s
2 // RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -debug-info-kind=standalone -dwarf-version=5 -munwind-tables -emit-llvm -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-NONOPT --check-prefix=CHECK-DBG %s
3 // RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - -O1 -disable-llvm-passes | FileCheck --check-prefix=CHECK --check-prefix=CHECK-OPT %s
4 
5 namespace Test1 {
6 
7 // Check that we emit a non-virtual thunk for C::f.
8 
9 struct A {
10   virtual void f();
11 };
12 
13 struct B {
14   virtual void f();
15 };
16 
17 struct C : A, B {
18   virtual void c();
19 
20   virtual void f();
21 };
22 
23 // CHECK-LABEL: define void @_ZThn8_N5Test11C1fEv(
24 // CHECK-DBG-NOT: dbg.declare
25 // CHECK: ret void
26 void C::f() { }
27 
28 }
29 
30 namespace Test2 {
31 
32 // Check that we emit a thunk for B::f since it's overriding a virtual base.
33 
34 struct A {
35   virtual void f();
36 };
37 
38 struct B : virtual A {
39   virtual void b();
40   virtual void f();
41 };
42 
43 // CHECK-LABEL: define void @_ZTv0_n24_N5Test21B1fEv(
44 // CHECK-DBG-NOT: dbg.declare
45 // CHECK: ret void
46 void B::f() { }
47 
48 }
49 
50 namespace Test3 {
51 
52 // Check that we emit a covariant thunk for B::f.
53 
54 struct V1 { };
55 struct V2 : virtual V1 { };
56 
57 struct A {
58   virtual V1 *f();
59 };
60 
61 struct B : A {
62   virtual void b();
63 
64   virtual V2 *f();
65 };
66 
67 // CHECK: define %{{.*}}* @_ZTch0_v0_n24_N5Test31B1fEv(
68 V2 *B::f() { return 0; }
69 
70 }
71 
72 namespace Test4 {
73 
74 // Check that the thunk for 'C::f' has the same visibility as the function itself.
75 
76 struct A {
77   virtual void f();
78 };
79 
80 struct B {
81   virtual void f();
82 };
83 
84 struct __attribute__((visibility("protected"))) C : A, B {
85   virtual void c();
86 
87   virtual void f();
88 };
89 
90 // CHECK-LABEL: define protected void @_ZThn8_N5Test41C1fEv(
91 // CHECK-DBG-NOT: dbg.declare
92 // CHECK: ret void
93 void C::f() { }
94 
95 }
96 
97 // Check that the thunk gets internal linkage.
98 namespace Test4B {
99   struct A {
100     virtual void f();
101   };
102 
103   struct B {
104     virtual void f();
105   };
106 
107   namespace {
108     struct C : A, B {
109       virtual void c();
110       virtual void f();
111     };
112   }
113   void C::c() {}
114   void C::f() {}
115 
116   // Force C::f to be used.
117   void f() {
118     C c;
119     c.f();
120   }
121 }
122 
123 namespace Test5 {
124 
125 // Check that the thunk for 'B::f' gets the same linkage as the function itself.
126 struct A {
127   virtual void f();
128 };
129 
130 struct B : virtual A {
131   virtual void f() { }
132 };
133 
134 void f(B b) {
135   b.f();
136 }
137 }
138 
139 namespace Test6 {
140   struct X {
141     X();
142     X(const X&);
143     X &operator=(const X&);
144     ~X();
145   };
146 
147   struct P {
148     P();
149     P(const P&);
150     ~P();
151     X first;
152     X second;
153   };
154 
155   P getP();
156 
157   struct Base1 {
158     int i;
159 
160     virtual X f() { return X(); }
161   };
162 
163   struct Base2 {
164     float real;
165 
166     virtual X f() { return X(); }
167   };
168 
169   struct Thunks : Base1, Base2 {
170     long l;
171 
172     virtual X f();
173   };
174 
175   // CHECK-LABEL: define void @_ZThn16_N5Test66Thunks1fEv
176 	// CHECK-DBG-NOT: dbg.declare
177   // CHECK-NOT: memcpy
178   // CHECK: {{call void @_ZN5Test66Thunks1fEv.*sret}}
179   // CHECK: ret void
180   X Thunks::f() { return X(); }
181 }
182 
183 namespace Test7 {
184   // PR7188
185   struct X {
186     X();
187     X(const X&);
188     X &operator=(const X&);
189     ~X();
190   };
191 
192   struct Small { short s; };
193   struct Large {
194     char array[1024];
195   };
196 
197   class A {
198   protected:
199     virtual void foo() = 0;
200   };
201 
202   class B : public A {
203   protected:
204     virtual void bar() = 0;
205   };
206 
207   class C : public A  {
208   protected:
209     virtual void baz(X, X&, _Complex float, Small, Small&, Large) = 0;
210   };
211 
212   class D : public B,
213             public C {
214 
215     void foo() {}
216     void bar() {}
217     void baz(X, X&, _Complex float, Small, Small&, Large);
218   };
219 
220   void D::baz(X, X&, _Complex float, Small, Small&, Large) { }
221 
222   // CHECK-LABEL: define void @_ZThn8_N5Test71D3bazENS_1XERS1_CfNS_5SmallERS4_NS_5LargeE(
223   // CHECK-DBG-NOT: dbg.declare
224   // CHECK-NOT: memcpy
225   // CHECK: ret void
226   void testD() { D d; }
227 }
228 
229 namespace Test8 {
230   struct NonPOD { ~NonPOD(); int x, y, z; };
231   struct A { virtual void foo(); };
232   struct B { virtual void bar(NonPOD); };
233   struct C : A, B { virtual void bar(NonPOD); static void helper(NonPOD); };
234 
235   // CHECK: define void @_ZN5Test81C6helperENS_6NonPODE([[NONPODTYPE:%.*]]*
236   void C::helper(NonPOD var) {}
237 
238   // CHECK-LABEL: define void @_ZThn8_N5Test81C3barENS_6NonPODE(
239   // CHECK-DBG-NOT: dbg.declare
240   // CHECK-NOT: load [[NONPODTYPE]], [[NONPODTYPE]]*
241   // CHECK-NOT: memcpy
242   // CHECK: ret void
243   void C::bar(NonPOD var) {}
244 }
245 
246 // PR7241: Emitting thunks for a method shouldn't require the vtable for
247 // that class to be emitted.
248 namespace Test9 {
249   struct A { virtual ~A() { } };
250   struct B : A { virtual void test() const {} };
251   struct C : B { C(); ~C(); };
252   struct D : C { D() {} };
253   void test() {
254     D d;
255   }
256 }
257 
258 namespace Test10 {
259   struct A { virtual void foo(); };
260   struct B { virtual void foo(); };
261   struct C : A, B { void foo() {} };
262 
263   // Test later.
264   void test() {
265     C c;
266   }
267 }
268 
269 // PR7611
270 namespace Test11 {
271   struct A {             virtual A* f(); };
272   struct B : virtual A { virtual A* f(); };
273   struct C : B         { virtual C* f(); };
274   C* C::f() { return 0; }
275 
276   //  C::f itself.
277   // CHECK: define {{.*}} @_ZN6Test111C1fEv(
278 
279   //  The this-adjustment and return-adjustment thunk required when
280   //  C::f appears in a vtable where A is at a nonzero offset from C.
281   // CHECK: define {{.*}} @_ZTcv0_n24_v0_n32_N6Test111C1fEv(
282   // CHECK-DBG-NOT: dbg.declare
283   // CHECK: ret
284 
285   //  The return-adjustment thunk required when C::f appears in a vtable
286   //  where A is at a zero offset from C.
287   // CHECK: define {{.*}} @_ZTch0_v0_n32_N6Test111C1fEv(
288   // CHECK-DBG-NOT: dbg.declare
289   // CHECK: ret
290 }
291 
292 // Varargs thunk test.
293 namespace Test12 {
294   struct A {
295     virtual A* f(int x, ...);
296   };
297   struct B {
298     virtual B* f(int x, ...);
299   };
300   struct C : A, B {
301     virtual void c();
302     virtual C* f(int x, ...);
303   };
304   C* C::f(int x, ...) { return this; }
305 
306   // C::f
307   // CHECK: define {{.*}} @_ZN6Test121C1fEiz
308 
309   // Varargs thunk; check that both the this and covariant adjustments
310   // are generated.
311   // CHECK: define {{.*}} @_ZTchn8_h8_N6Test121C1fEiz
312   // CHECK-DBG-NOT: dbg.declare
313   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -8
314   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 8
315 }
316 
317 // PR13832
318 namespace Test13 {
319   struct B1 {
320     virtual B1 &foo1();
321   };
322   struct Pad1 {
323     virtual ~Pad1();
324   };
325   struct Proxy1 : Pad1, B1 {
326     virtual ~Proxy1();
327   };
328   struct D : virtual Proxy1 {
329     virtual ~D();
330     virtual D &foo1();
331   };
332   D& D::foo1() {
333     return *this;
334   }
335   // CHECK: define {{.*}} @_ZTcvn8_n32_v8_n24_N6Test131D4foo1Ev
336   // CHECK-DBG-NOT: dbg.declare
337   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -8
338   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -32
339   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -24
340   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 8
341   // CHECK: ret %"struct.Test13::D"*
342 }
343 
344 namespace Test14 {
345   class A {
346     virtual void f();
347   };
348   class B {
349     virtual void f();
350   };
351   class C : public A, public B  {
352     virtual void f();
353   };
354   void C::f() {
355   }
356   // CHECK: define void @_ZThn8_N6Test141C1fEv({{.*}}) unnamed_addr [[NUW:#[0-9]+]]
357   // CHECK-DBG-NOT: dbg.declare
358   // CHECK: ret void
359 }
360 
361 // Varargs non-covariant thunk test.
362 // PR18098
363 namespace Test15 {
364   struct A {
365     virtual ~A();
366   };
367   struct B {
368     virtual void f(int x, ...);
369   };
370   struct C : A, B {
371     virtual void c();
372     virtual void f(int x, ...);
373   };
374   void C::c() {}
375 
376   // C::c
377   // CHECK: declare void @_ZN6Test151C1fEiz
378   // non-virtual thunk to C::f
379   // CHECK: declare void @_ZThn8_N6Test151C1fEiz
380 }
381 
382 namespace Test16 {
383 struct A {
384   virtual ~A();
385 };
386 struct B {
387   virtual void foo();
388 };
389 struct C : public A, public B {
390   void foo() {}
391 };
392 struct D : public C {
393   ~D();
394 };
395 D::~D() {}
396 // CHECK: define linkonce_odr void @_ZThn8_N6Test161C3fooEv({{.*}}) {{.*}} comdat
397 // CHECK-DBG-NOT: dbg.declare
398 // CHECK: ret void
399 }
400 
401 /**** The following has to go at the end of the file ****/
402 
403 // checking without opt
404 // CHECK-NONOPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
405 // CHECK-NONOPT-NOT: comdat
406 
407 // This is from Test5:
408 // CHECK-NONOPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
409 
410 // This is from Test10:
411 // CHECK-NONOPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
412 // CHECK-NONOPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
413 
414 // Checking with opt
415 // CHECK-OPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(%"struct.Test4B::(anonymous namespace)::C"* %this) unnamed_addr #0 align 2
416 
417 // This is from Test5:
418 // CHECK-OPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
419 
420 // This is from Test10:
421 // CHECK-OPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
422 // CHECK-OPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
423 
424 // CHECK-NONOPT: attributes [[NUW]] = { noinline nounwind optnone uwtable{{.*}} }
425 // CHECK-OPT: attributes [[NUW]] = { nounwind uwtable{{.*}} }
426