1// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -o - %s | FileCheck %s
2// RUN: %clang_cc1 -triple i386-unknown-unknown -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
12template<typename T> struct Y {
13  Y();
14  static Y f() {
15    Y y;
16    return y;
17  }
18};
19
20// CHECK-LABEL: define void @_Z5test0v
21// CHECK-EH-LABEL: define void @_Z5test0v
22X test0() {
23  X x;
24  // CHECK:          call {{.*}} @_ZN1XC1Ev
25  // CHECK-NEXT:     ret void
26
27  // CHECK-EH:       call {{.*}} @_ZN1XC1Ev
28  // CHECK-EH-NEXT:  ret void
29  return x;
30}
31
32// CHECK-LABEL: define void @_Z5test1b(
33// CHECK-EH-LABEL: define void @_Z5test1b(
34X test1(bool B) {
35  // CHECK:      tail call {{.*}} @_ZN1XC1Ev
36  // CHECK-NEXT: ret void
37  X x;
38  if (B)
39    return (x);
40  return x;
41  // CHECK-EH:      tail call {{.*}} @_ZN1XC1Ev
42  // CHECK-EH-NEXT: ret void
43}
44
45// CHECK-LABEL: define void @_Z5test2b
46// CHECK-EH-LABEL: define void @_Z5test2b
47X test2(bool B) {
48  // No NRVO.
49
50  X x;
51  X y;
52  if (B)
53    return y;
54  return x;
55
56  // CHECK: call {{.*}} @_ZN1XC1Ev
57  // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev
58  // CHECK: call {{.*}} @_ZN1XC1ERKS_
59  // CHECK: call {{.*}} @_ZN1XC1ERKS_
60  // CHECK: call {{.*}} @_ZN1XD1Ev
61  // CHECK: call {{.*}} @_ZN1XD1Ev
62  // CHECK: ret void
63
64  // The block ordering in the -fexceptions IR is unfortunate.
65
66  // CHECK-EH:      call {{.*}} @_ZN1XC1Ev
67  // CHECK-EH-NEXT: invoke {{.*}} @_ZN1XC1Ev
68  // -> %invoke.cont, %lpad
69
70  // %invoke.cont:
71  // CHECK-EH:      br i1
72  // -> %if.then, %if.end
73
74  // %if.then: returning 'x'
75  // CHECK-EH:      invoke {{.*}} @_ZN1XC1ERKS_
76  // -> %cleanup, %lpad1
77
78  // %lpad: landing pad for ctor of 'y', dtor of 'y'
79  // CHECK-EH:      [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
80  // CHECK-EH-NEXT:   cleanup
81  // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 0
82  // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 1
83  // CHECK-EH-NEXT: br label
84  // -> %eh.cleanup
85
86  // %lpad1: landing pad for return copy ctors, EH cleanup for 'y'
87  // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
88  // -> %eh.cleanup, %terminate.lpad
89
90  // %if.end: returning 'y'
91  // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
92  // -> %cleanup, %lpad1
93
94  // %cleanup: normal cleanup for 'y'
95  // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
96  // -> %invoke.cont11, %lpad
97
98  // %invoke.cont11: normal cleanup for 'x'
99  // CHECK-EH:      call {{.*}} @_ZN1XD1Ev
100  // CHECK-EH-NEXT: ret void
101
102  // %eh.cleanup:  EH cleanup for 'x'
103  // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
104  // -> %invoke.cont17, %terminate.lpad
105
106  // %invoke.cont17: rethrow block for %eh.cleanup.
107  // This really should be elsewhere in the function.
108  // CHECK-EH:      resume { i8*, i32 }
109
110  // %terminate.lpad: terminate landing pad.
111  // CHECK-EH:      [[T0:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
112  // CHECK-EH-NEXT:   catch i8* null
113  // CHECK-EH-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
114  // CHECK-EH-NEXT: call void @__clang_call_terminate(i8* [[T1]]) [[NR_NUW:#[0-9]+]]
115  // CHECK-EH-NEXT: unreachable
116
117}
118
119// CHECK-LABEL: define void @_Z5test3b
120X test3(bool B) {
121  // CHECK: tail call {{.*}} @_ZN1XC1Ev
122  // CHECK-NOT: call {{.*}} @_ZN1XC1ERKS_
123  // CHECK: call {{.*}} @_ZN1XC1Ev
124  // CHECK: call {{.*}} @_ZN1XC1ERKS_
125  if (B) {
126    X y;
127    return y;
128  }
129  // FIXME: we should NRVO this variable too.
130  X x;
131  return x;
132}
133
134extern "C" void exit(int) throw();
135
136// CHECK-LABEL: define void @_Z5test4b
137X test4(bool B) {
138  {
139    // CHECK: tail call {{.*}} @_ZN1XC1Ev
140    X x;
141    // CHECK: br i1
142    if (B)
143      return x;
144  }
145  // CHECK: tail call {{.*}} @_ZN1XD1Ev
146  // CHECK: tail call void @exit(i32 1)
147  exit(1);
148}
149
150#ifdef __EXCEPTIONS
151// CHECK-EH-LABEL: define void @_Z5test5
152void may_throw();
153X test5() {
154  try {
155    may_throw();
156  } catch (X x) {
157    // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
158    // CHECK-EH: call void @__cxa_end_catch()
159    // CHECK-EH: ret void
160    return x;
161  }
162}
163#endif
164
165// rdar://problem/10430868
166// CHECK-LABEL: define void @_Z5test6v
167X test6() {
168  X a __attribute__((aligned(8)));
169  return a;
170  // CHECK:      [[A:%.*]] = alloca [[X:%.*]], align 8
171  // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* [[A]])
172  // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* nonnull [[A]])
173  // CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* [[A]])
174  // CHECK-NEXT: ret void
175}
176
177// CHECK-LABEL: define void @_Z5test7b
178X test7(bool b) {
179  // CHECK: tail call {{.*}} @_ZN1XC1Ev
180  // CHECK-NEXT: ret
181  if (b) {
182    X x;
183    return x;
184  }
185  return X();
186}
187
188// CHECK-LABEL: define void @_Z5test8b
189X test8(bool b) {
190  // CHECK: tail call {{.*}} @_ZN1XC1Ev
191  // CHECK-NEXT: ret
192  if (b) {
193    X x;
194    return x;
195  } else {
196    X y;
197    return y;
198  }
199}
200
201Y<int> test9() {
202  Y<int>::f();
203}
204
205// CHECK-LABEL: define linkonce_odr void @_ZN1YIiE1fEv
206// CHECK: tail call {{.*}} @_ZN1YIiEC1Ev
207
208// CHECK-EH: attributes [[NR_NUW]] = { noreturn nounwind }
209