1// RUN: %clang_cc1 -emit-llvm -O1 -o - %s | FileCheck %s
2// RUN: %clang_cc1 -emit-llvm -O1 -fcxx-exceptions -fexceptions -o - %s | FileCheck --check-prefix=CHECK-EH %s
3
4// Test code generation for the named return value optimization.
5class X {
6public:
7  X();
8  X(const X&);
9  ~X();
10};
11
12// CHECK: define void @_Z5test0v
13// CHECK-EH: define void @_Z5test0v
14X test0() {
15  X x;
16  // CHECK:          call {{.*}} @_ZN1XC1Ev
17  // CHECK-NEXT:     ret void
18
19  // CHECK-EH:       call {{.*}} @_ZN1XC1Ev
20  // CHECK-EH-NEXT:  ret void
21  return x;
22}
23
24// CHECK: define void @_Z5test1b(
25// CHECK-EH: define void @_Z5test1b(
26X test1(bool B) {
27  // CHECK:      tail call {{.*}} @_ZN1XC1Ev
28  // CHECK-NEXT: ret void
29  X x;
30  if (B)
31    return (x);
32  return x;
33  // CHECK-EH:      tail call {{.*}} @_ZN1XC1Ev
34  // CHECK-EH-NEXT: ret void
35}
36
37// CHECK: define void @_Z5test2b
38// CHECK-EH: define void @_Z5test2b
39X test2(bool B) {
40  // No NRVO.
41
42  X x;
43  X y;
44  if (B)
45    return y;
46  return x;
47
48  // CHECK: call {{.*}} @_ZN1XC1Ev
49  // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev
50  // CHECK: call {{.*}} @_ZN1XC1ERKS_
51  // CHECK: call {{.*}} @_ZN1XC1ERKS_
52  // CHECK: call {{.*}} @_ZN1XD1Ev
53  // CHECK: call {{.*}} @_ZN1XD1Ev
54  // CHECK: ret void
55
56  // The block ordering in the -fexceptions IR is unfortunate.
57
58  // CHECK-EH:      call {{.*}} @_ZN1XC1Ev
59  // CHECK-EH-NEXT: invoke {{.*}} @_ZN1XC1Ev
60  // -> %invoke.cont, %lpad
61
62  // %invoke.cont:
63  // CHECK-EH:      br i1
64  // -> %if.then, %if.end
65
66  // %if.then: returning 'x'
67  // CHECK-EH:      invoke {{.*}} @_ZN1XC1ERKS_
68  // -> %cleanup, %lpad1
69
70  // %lpad: landing pad for ctor of 'y', dtor of 'y'
71  // CHECK-EH:      [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
72  // CHECK-EH-NEXT:   cleanup
73  // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 0
74  // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 1
75  // CHECK-EH-NEXT: br label
76  // -> %eh.cleanup
77
78  // %lpad1: landing pad for return copy ctors, EH cleanup for 'y'
79  // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
80  // -> %eh.cleanup, %terminate.lpad
81
82  // %if.end: returning 'y'
83  // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
84  // -> %cleanup, %lpad1
85
86  // %cleanup: normal cleanup for 'y'
87  // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
88  // -> %invoke.cont11, %lpad
89
90  // %invoke.cont11: normal cleanup for 'x'
91  // CHECK-EH:      call {{.*}} @_ZN1XD1Ev
92  // CHECK-EH-NEXT: ret void
93
94  // %eh.cleanup:  EH cleanup for 'x'
95  // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
96  // -> %invoke.cont17, %terminate.lpad
97
98  // %invoke.cont17: rethrow block for %eh.cleanup.
99  // This really should be elsewhere in the function.
100  // CHECK-EH:      resume { i8*, i32 }
101
102  // %terminate.lpad: terminate landing pad.
103  // CHECK-EH:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
104  // CHECK-EH-NEXT:   catch i8* null
105  // CHECK-EH-NEXT: call void @_ZSt9terminatev()
106  // CHECK-EH-NEXT: unreachable
107
108}
109
110X test3(bool B) {
111  // FIXME: We don't manage to apply NRVO here, although we could.
112  {
113    X y;
114    return y;
115  }
116  X x;
117  return x;
118}
119
120extern "C" void exit(int) throw();
121
122// CHECK: define void @_Z5test4b
123X test4(bool B) {
124  {
125    // CHECK: tail call {{.*}} @_ZN1XC1Ev
126    X x;
127    // CHECK: br i1
128    if (B)
129      return x;
130  }
131  // CHECK: tail call {{.*}} @_ZN1XD1Ev
132  // CHECK: tail call void @exit(i32 1)
133  exit(1);
134}
135
136#ifdef __EXCEPTIONS
137// CHECK-EH: define void @_Z5test5
138void may_throw();
139X test5() {
140  try {
141    may_throw();
142  } catch (X x) {
143    // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
144    // CHECK-EH: call void @__cxa_end_catch()
145    // CHECK-EH: ret void
146    return x;
147  }
148}
149#endif
150