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 // CHECK: define void @_Z5test0v
13 // CHECK-EH: define void @_Z5test0v
test0()14 X test0() {
15 X x;
16 // CHECK: call {{.*}} @_ZN1XC1Ev
17 // CHECK-NEXT: ret void
18
19 // CHECK-EH: call {{.*}} @_ZN1XC1Ev
20 // CHECK-EH-NEXT: ret void
21 return x;
22 }
23
24 // CHECK: define void @_Z5test1b(
25 // CHECK-EH: define void @_Z5test1b(
test1(bool B)26 X test1(bool B) {
27 // CHECK: tail call {{.*}} @_ZN1XC1Ev
28 // CHECK-NEXT: ret void
29 X x;
30 if (B)
31 return (x);
32 return x;
33 // CHECK-EH: tail call {{.*}} @_ZN1XC1Ev
34 // CHECK-EH-NEXT: ret void
35 }
36
37 // CHECK: define void @_Z5test2b
38 // CHECK-EH: define void @_Z5test2b
test2(bool B)39 X test2(bool B) {
40 // No NRVO.
41
42 X x;
43 X y;
44 if (B)
45 return y;
46 return x;
47
48 // CHECK: call {{.*}} @_ZN1XC1Ev
49 // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev
50 // CHECK: call {{.*}} @_ZN1XC1ERKS_
51 // CHECK: call {{.*}} @_ZN1XC1ERKS_
52 // CHECK: call {{.*}} @_ZN1XD1Ev
53 // CHECK: call {{.*}} @_ZN1XD1Ev
54 // CHECK: ret void
55
56 // The block ordering in the -fexceptions IR is unfortunate.
57
58 // CHECK-EH: call {{.*}} @_ZN1XC1Ev
59 // CHECK-EH-NEXT: invoke {{.*}} @_ZN1XC1Ev
60 // -> %invoke.cont, %lpad
61
62 // %invoke.cont:
63 // CHECK-EH: br i1
64 // -> %if.then, %if.end
65
66 // %if.then: returning 'x'
67 // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
68 // -> %cleanup, %lpad1
69
70 // %lpad: landing pad for ctor of 'y', dtor of 'y'
71 // CHECK-EH: [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
72 // CHECK-EH-NEXT: cleanup
73 // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 0
74 // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 1
75 // CHECK-EH-NEXT: br label
76 // -> %eh.cleanup
77
78 // %lpad1: landing pad for return copy ctors, EH cleanup for 'y'
79 // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
80 // -> %eh.cleanup, %terminate.lpad
81
82 // %if.end: returning 'y'
83 // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
84 // -> %cleanup, %lpad1
85
86 // %cleanup: normal cleanup for 'y'
87 // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
88 // -> %invoke.cont11, %lpad
89
90 // %invoke.cont11: normal cleanup for 'x'
91 // CHECK-EH: call {{.*}} @_ZN1XD1Ev
92 // CHECK-EH-NEXT: ret void
93
94 // %eh.cleanup: EH cleanup for 'x'
95 // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
96 // -> %invoke.cont17, %terminate.lpad
97
98 // %invoke.cont17: rethrow block for %eh.cleanup.
99 // This really should be elsewhere in the function.
100 // CHECK-EH: resume { i8*, i32 }
101
102 // %terminate.lpad: terminate landing pad.
103 // CHECK-EH: [[T0:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
104 // CHECK-EH-NEXT: catch i8* null
105 // CHECK-EH-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
106 // CHECK-EH-NEXT: call void @__clang_call_terminate(i8* [[T1]]) [[NR_NUW:#[0-9]+]]
107 // CHECK-EH-NEXT: unreachable
108
109 }
110
test3(bool B)111 X test3(bool B) {
112 // FIXME: We don't manage to apply NRVO here, although we could.
113 {
114 X y;
115 return y;
116 }
117 X x;
118 return x;
119 }
120
121 extern "C" void exit(int) throw();
122
123 // CHECK: define void @_Z5test4b
test4(bool B)124 X test4(bool B) {
125 {
126 // CHECK: tail call {{.*}} @_ZN1XC1Ev
127 X x;
128 // CHECK: br i1
129 if (B)
130 return x;
131 }
132 // CHECK: tail call {{.*}} @_ZN1XD1Ev
133 // CHECK: tail call void @exit(i32 1)
134 exit(1);
135 }
136
137 #ifdef __EXCEPTIONS
138 // CHECK-EH: define void @_Z5test5
139 void may_throw();
test5()140 X test5() {
141 try {
142 may_throw();
143 } catch (X x) {
144 // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
145 // CHECK-EH: call void @__cxa_end_catch()
146 // CHECK-EH: ret void
147 return x;
148 }
149 }
150 #endif
151
152 // rdar://problem/10430868
153 // CHECK: define void @_Z5test6v
test6()154 X test6() {
155 X a __attribute__((aligned(8)));
156 return a;
157 // CHECK: [[A:%.*]] = alloca [[X:%.*]], align 8
158 // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* [[A]])
159 // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* [[A]])
160 // CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* [[A]])
161 // CHECK-NEXT: ret void
162 }
163
164 // CHECK-EH: attributes [[NR_NUW]] = { noreturn nounwind }
165