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