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
test2(bool B)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: 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
test3(bool B)120 X 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
134 extern "C" void exit(int) throw();
135
136 // CHECK-LABEL: define void @_Z5test4b
test4(bool B)137 X 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
152 void may_throw();
test5()153 X 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
test6()167 X 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
test7(bool b)178 X 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
test8(bool b)189 X 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
test9()201 Y<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