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