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