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