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