1// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s
2struct A {
3  A();
4  ~A();
5  void f();
6};
7
8void f1() {
9  // CHECK: call void @_ZN1AC1Ev
10  // CHECK: call void @_ZN1AD1Ev
11  (void)A();
12
13  // CHECK: call void @_ZN1AC1Ev
14  // CHECK: call void @_ZN1AD1Ev
15  A().f();
16}
17
18// Function calls
19struct B {
20  B();
21  ~B();
22};
23
24B g();
25
26void f2() {
27  // CHECK-NOT: call void @_ZN1BC1Ev
28  // CHECK: call void @_ZN1BD1Ev
29  (void)g();
30}
31
32// Member function calls
33struct C {
34  C();
35  ~C();
36
37  C f();
38};
39
40void f3() {
41  // CHECK: call void @_ZN1CC1Ev
42  // CHECK: call void @_ZN1CD1Ev
43  // CHECK: call void @_ZN1CD1Ev
44  C().f();
45}
46
47// Function call operator
48struct D {
49  D();
50  ~D();
51
52  D operator()();
53};
54
55void f4() {
56  // CHECK: call void @_ZN1DC1Ev
57  // CHECK: call void @_ZN1DD1Ev
58  // CHECK: call void @_ZN1DD1Ev
59  D()();
60}
61
62// Overloaded operators
63struct E {
64  E();
65  ~E();
66  E operator+(const E&);
67  E operator!();
68};
69
70void f5() {
71  // CHECK: call void @_ZN1EC1Ev
72  // CHECK: call void @_ZN1EC1Ev
73  // CHECK: call void @_ZN1ED1Ev
74  // CHECK: call void @_ZN1ED1Ev
75  // CHECK: call void @_ZN1ED1Ev
76  E() + E();
77
78  // CHECK: call void @_ZN1EC1Ev
79  // CHECK: call void @_ZN1ED1Ev
80  // CHECK: call void @_ZN1ED1Ev
81  !E();
82}
83
84struct F {
85  F();
86  ~F();
87  F& f();
88};
89
90void f6() {
91  // CHECK: call void @_ZN1FC1Ev
92  // CHECK: call void @_ZN1FD1Ev
93  F().f();
94}
95
96struct G {
97  G();
98  G(A);
99  ~G();
100  operator A();
101};
102
103void a(const A&);
104
105void f7() {
106  // CHECK: call void @_ZN1AC1Ev
107  // CHECK: call void @_Z1aRK1A
108  // CHECK: call void @_ZN1AD1Ev
109  a(A());
110
111  // CHECK: call void @_ZN1GC1Ev
112  // CHECK: call void @_ZN1Gcv1AEv
113  // CHECK: call void @_Z1aRK1A
114  // CHECK: call void @_ZN1AD1Ev
115  // CHECK: call void @_ZN1GD1Ev
116  a(G());
117}
118
119namespace PR5077 {
120
121struct A {
122  A();
123  ~A();
124  int f();
125};
126
127void f();
128int g(const A&);
129
130struct B {
131  int a1;
132  int a2;
133  B();
134  ~B();
135};
136
137B::B()
138  // CHECK: call void @_ZN6PR50771AC1Ev
139  // CHECK: call i32 @_ZN6PR50771A1fEv
140  // CHECK: call void @_ZN6PR50771AD1Ev
141  : a1(A().f())
142  // CHECK: call void @_ZN6PR50771AC1Ev
143  // CHECK: call i32 @_ZN6PR50771gERKNS_1AE
144  // CHECK: call void @_ZN6PR50771AD1Ev
145  , a2(g(A()))
146{
147  // CHECK: call void @_ZN6PR50771fEv
148  f();
149}
150
151struct C {
152  C();
153
154  const B& b;
155};
156
157C::C()
158  // CHECK: call void @_ZN6PR50771BC1Ev
159  : b(B()) {
160  // CHECK: call void @_ZN6PR50771fEv
161  f();
162
163  // CHECK: call void @_ZN6PR50771BD1Ev
164}
165}
166
167A f8() {
168  // CHECK: call void @_ZN1AC1Ev
169  // CHECK-NOT: call void @_ZN1AD1Ev
170  return A();
171  // CHECK: ret void
172}
173
174struct H {
175  H();
176  ~H();
177  H(const H&);
178};
179
180void f9(H h) {
181  // CHECK: call void @_ZN1HC1Ev
182  // CHECK: call void @_Z2f91H
183  // CHECK: call void @_ZN1HD1Ev
184  f9(H());
185
186  // CHECK: call void @_ZN1HC1ERKS_
187  // CHECK: call void @_Z2f91H
188  // CHECK: call void @_ZN1HD1Ev
189  f9(h);
190}
191
192void f10(const H&);
193
194void f11(H h) {
195  // CHECK: call void @_ZN1HC1Ev
196  // CHECK: call void @_Z3f10RK1H
197  // CHECK: call void @_ZN1HD1Ev
198  f10(H());
199
200  // CHECK: call void @_Z3f10RK1H
201  // CHECK-NOT: call void @_ZN1HD1Ev
202  // CHECK: ret void
203  f10(h);
204}
205
206// PR5808
207struct I {
208  I(const char *);
209  ~I();
210};
211
212// CHECK: _Z3f12v
213I f12() {
214  // CHECK: call void @_ZN1IC1EPKc
215  // CHECK-NOT: call void @_ZN1ID1Ev
216  // CHECK: ret void
217  return "Hello";
218}
219
220// PR5867
221namespace PR5867 {
222  struct S {
223    S();
224    S(const S &);
225    ~S();
226  };
227
228  void f(S, int);
229  // CHECK: define void @_ZN6PR58671gEv
230  void g() {
231    // CHECK: call void @_ZN6PR58671SC1Ev
232    // CHECK-NEXT: call void @_ZN6PR58671fENS_1SEi
233    // CHECK-NEXT: call void @_ZN6PR58671SD1Ev
234    // CHECK-NEXT: ret void
235    (f)(S(), 0);
236  }
237
238  // CHECK: define linkonce_odr void @_ZN6PR58672g2IiEEvT_
239  template<typename T>
240  void g2(T) {
241    // CHECK: call void @_ZN6PR58671SC1Ev
242    // CHECK-NEXT: call void @_ZN6PR58671fENS_1SEi
243    // CHECK-NEXT: call void @_ZN6PR58671SD1Ev
244    // CHECK-NEXT: ret void
245    (f)(S(), 0);
246  }
247
248  void h() {
249    g2(17);
250  }
251}
252
253// PR6199
254namespace PR6199 {
255  struct A { ~A(); };
256
257  struct B { operator A(); };
258
259  // CHECK: define weak_odr void @_ZN6PR61992f2IiEENS_1AET_
260  template<typename T> A f2(T) {
261    B b;
262    // CHECK: call void @_ZN6PR61991BcvNS_1AEEv
263    // CHECK-NEXT: ret void
264    return b;
265  }
266
267  template A f2<int>(int);
268
269}
270
271namespace T12 {
272
273struct A {
274  A();
275  ~A();
276  int f();
277};
278
279int& f(int);
280
281// CHECK: define void @_ZN3T121gEv
282void g() {
283  // CHECK: call void @_ZN3T121AC1Ev
284  // CHECK-NEXT: call i32 @_ZN3T121A1fEv(
285  // CHECK-NEXT: call i32* @_ZN3T121fEi(
286  // CHECK-NEXT: call void @_ZN3T121AD1Ev(
287  int& i = f(A().f());
288}
289
290}
291
292namespace PR6648 {
293  struct B {
294    ~B();
295  };
296  B foo;
297  struct D;
298  D& zed(B);
299  void foobar() {
300    // CHECK: call %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE
301    zed(foo);
302  }
303}
304
305namespace UserConvertToValue {
306  struct X {
307    X(int);
308    X(const X&);
309    ~X();
310  };
311
312  void f(X);
313
314  // CHECK: void @_ZN18UserConvertToValue1gEv()
315  void g() {
316    // CHECK: call void @_ZN18UserConvertToValue1XC1Ei
317    // CHECK: call void @_ZN18UserConvertToValue1fENS_1XE
318    // CHECK: call void @_ZN18UserConvertToValue1XD1Ev
319    // CHECK: ret void
320    f(1);
321  }
322}
323
324namespace PR7556 {
325  struct A { ~A(); };
326  struct B { int i; ~B(); };
327  struct C { int C::*pm; ~C(); };
328  // CHECK: define void @_ZN6PR75563fooEv()
329  void foo() {
330    // CHECK: call void @_ZN6PR75561AD1Ev
331    A();
332    // CHECK: call void @llvm.memset.p0i8.i64
333    // CHECK: call void @_ZN6PR75561BD1Ev
334    B();
335    // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
336    // CHECK: call void @_ZN6PR75561CD1Ev
337    C();
338    // CHECK-NEXT: ret void
339  }
340}
341
342namespace Elision {
343  struct A {
344    A(); A(const A &); ~A();
345    void *p;
346    void foo() const;
347  };
348
349  void foo();
350  A fooA();
351  void takeA(A a);
352
353  // CHECK: define void @_ZN7Elision5test0Ev()
354  void test0() {
355    // CHECK:      [[I:%.*]] = alloca [[A:%.*]], align 8
356    // CHECK-NEXT: [[J:%.*]] = alloca [[A]], align 8
357    // CHECK-NEXT: [[T0:%.*]] = alloca [[A]], align 8
358    // CHECK-NEXT: [[K:%.*]] = alloca [[A]], align 8
359    // CHECK-NEXT: [[T1:%.*]] = alloca [[A]], align 8
360
361    // CHECK-NEXT: call void @_ZN7Elision3fooEv()
362    // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[I]])
363    A i = (foo(), A());
364
365    // CHECK-NEXT: call void @_ZN7Elision4fooAEv([[A]]* sret [[T0]])
366    // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[J]])
367    // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[T0]])
368    A j = (fooA(), A());
369
370    // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[T1]])
371    // CHECK-NEXT: call void @_ZN7Elision4fooAEv([[A]]* sret [[K]])
372    // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[T1]])
373    A k = (A(), fooA());
374
375    // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[K]])
376    // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[J]])
377    // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[I]])
378  }
379
380
381  // CHECK: define void @_ZN7Elision5test1EbNS_1AE(
382  void test1(bool c, A x) {
383    // CHECK:      [[I:%.*]] = alloca [[A]], align 8
384    // CHECK-NEXT: [[J:%.*]] = alloca [[A]], align 8
385
386    // CHECK:      call void @_ZN7Elision1AC1Ev([[A]]* [[I]])
387    // CHECK:      call void @_ZN7Elision1AC1ERKS0_([[A]]* [[I]], [[A]]* [[X:%.*]])
388    A i = (c ? A() : x);
389
390    // CHECK:      call void @_ZN7Elision1AC1ERKS0_([[A]]* [[J]], [[A]]* [[X]])
391    // CHECK:      call void @_ZN7Elision1AC1Ev([[A]]* [[J]])
392    A j = (c ? x : A());
393
394    // CHECK:      call void @_ZN7Elision1AD1Ev([[A]]* [[J]])
395    // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[I]])
396  }
397
398  // CHECK: define void @_ZN7Elision5test2Ev([[A]]* noalias sret
399  A test2() {
400    // CHECK:      call void @_ZN7Elision3fooEv()
401    // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[RET:%.*]])
402    // CHECK-NEXT: ret void
403    return (foo(), A());
404  }
405
406  // CHECK: define void @_ZN7Elision5test3EiNS_1AE([[A]]* noalias sret
407  A test3(int v, A x) {
408    if (v < 5)
409    // CHECK:      call void @_ZN7Elision1AC1Ev([[A]]* [[RET:%.*]])
410    // CHECK:      call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* [[X:%.*]])
411      return (v < 0 ? A() : x);
412    else
413    // CHECK:      call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* [[X]])
414    // CHECK:      call void @_ZN7Elision1AC1Ev([[A]]* [[RET]])
415      return (v > 10 ? x : A());
416
417    // CHECK:      ret void
418  }
419
420  // CHECK: define void @_ZN7Elision5test4Ev()
421  void test4() {
422    // CHECK:      [[X:%.*]] = alloca [[A]], align 8
423    // CHECK-NEXT: [[XS:%.*]] = alloca [2 x [[A]]], align 16
424
425    // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[X]])
426    A x;
427
428    // CHECK-NEXT: [[XS0:%.*]] = getelementptr inbounds [2 x [[A]]]* [[XS]], i64 0, i64 0
429    // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[XS0]])
430    // CHECK-NEXT: [[XS1:%.*]] = getelementptr inbounds [[A]]* [[XS0]], i64 1
431    // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[XS1]], [[A]]* [[X]])
432    A xs[] = { A(), x };
433
434    // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [2 x [[A]]]* [[XS]], i32 0, i32 0
435    // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A]]* [[BEGIN]], i64 2
436    // CHECK-NEXT: br label
437    // CHECK:      [[AFTER:%.*]] = phi [[A]]*
438    // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]]* [[AFTER]], i64 -1
439    // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[CUR]])
440    // CHECK-NEXT: [[T0:%.*]] = icmp eq [[A]]* [[CUR]], [[BEGIN]]
441    // CHECK-NEXT: br i1 [[T0]],
442
443    // CHECK:      call void @_ZN7Elision1AD1Ev([[A]]* [[X]])
444  }
445
446  // rdar://problem/8433352
447  // CHECK: define void @_ZN7Elision5test5Ev([[A]]* noalias sret
448  struct B { A a; B(); };
449  A test5() {
450    // CHECK:      [[AT0:%.*]] = alloca [[A]], align 8
451    // CHECK-NEXT: [[BT0:%.*]] = alloca [[B:%.*]], align 8
452    // CHECK-NEXT: [[X:%.*]] = alloca [[A]], align 8
453    // CHECK-NEXT: [[BT1:%.*]] = alloca [[B]], align 8
454    // CHECK-NEXT: [[BT2:%.*]] = alloca [[B]], align 8
455
456    // CHECK:      call void @_ZN7Elision1BC1Ev([[B]]* [[BT0]])
457    // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT0]], i32 0, i32 0
458    // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[AT0]], [[A]]* [[AM]])
459    // CHECK-NEXT: call void @_ZN7Elision5takeAENS_1AE([[A]]* [[AT0]])
460    // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[AT0]])
461    // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT0]])
462    takeA(B().a);
463
464    // CHECK-NEXT: call void @_ZN7Elision1BC1Ev([[B]]* [[BT1]])
465    // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT1]], i32 0, i32 0
466    // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[X]], [[A]]* [[AM]])
467    // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT1]])
468    A x = B().a;
469
470    // CHECK-NEXT: call void @_ZN7Elision1BC1Ev([[B]]* [[BT2]])
471    // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT2]], i32 0, i32 0
472    // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET:%.*]], [[A]]* [[AM]])
473    // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT2]])
474    return B().a;
475
476    // CHECK:      call void @_ZN7Elision1AD1Ev([[A]]* [[X]])
477  }
478
479  // Reduced from webkit.
480  // CHECK: define void @_ZN7Elision5test6EPKNS_1CE([[C:%.*]]*
481  struct C { operator A() const; };
482  void test6(const C *x) {
483    // CHECK:      [[T0:%.*]] = alloca [[A]], align 8
484    // CHECK:      [[X:%.*]] = load [[C]]** {{%.*}}, align 8
485    // CHECK-NEXT: call void @_ZNK7Elision1CcvNS_1AEEv([[A]]* sret [[T0]], [[C]]* [[X]])
486    // CHECK-NEXT: call void @_ZNK7Elision1A3fooEv([[A]]* [[T0]])
487    // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[T0]])
488    // CHECK-NEXT: ret void
489    A(*x).foo();
490  }
491}
492
493namespace PR8623 {
494  struct A { A(int); ~A(); };
495
496  // CHECK: define void @_ZN6PR86233fooEb(
497  void foo(bool b) {
498    // CHECK:      [[TMP:%.*]] = alloca [[A:%.*]], align 1
499    // CHECK-NEXT: [[LCONS:%.*]] = alloca i1
500    // CHECK-NEXT: [[RCONS:%.*]] = alloca i1
501    // CHECK:      store i1 false, i1* [[LCONS]]
502    // CHECK-NEXT: store i1 false, i1* [[RCONS]]
503    // CHECK-NEXT: br i1
504    // CHECK:      call void @_ZN6PR86231AC1Ei([[A]]* [[TMP]], i32 2)
505    // CHECK-NEXT: store i1 true, i1* [[LCONS]]
506    // CHECK-NEXT: br label
507    // CHECK:      call void @_ZN6PR86231AC1Ei([[A]]* [[TMP]], i32 3)
508    // CHECK-NEXT: store i1 true, i1* [[RCONS]]
509    // CHECK-NEXT: br label
510    // CHECK:      load i1* [[RCONS]]
511    // CHECK-NEXT: br i1
512    // CHECK:      call void @_ZN6PR86231AD1Ev([[A]]* [[TMP]])
513    // CHECK-NEXT: br label
514    // CHECK:      load i1* [[LCONS]]
515    // CHECK-NEXT: br i1
516    // CHECK:      call void @_ZN6PR86231AD1Ev([[A]]* [[TMP]])
517    // CHECK-NEXT: br label
518    // CHECK:      ret void
519    b ? A(2) : A(3);
520  }
521}
522