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