1 // RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
2 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
3
4 void abort(void) __attribute__((noreturn));
5 void might_crash(void);
6 void cleanup(void);
7 int check_condition(void);
basic_finally(void)8 void basic_finally(void) {
9 __try {
10 might_crash();
11 } __finally {
12 cleanup();
13 }
14 }
15
16 // CHECK-LABEL: define void @basic_finally()
17 // CHECK: invoke void @might_crash()
18 // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
19 //
20 // CHECK: [[invoke_cont]]
21 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
22 // CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
23 // CHECK-NEXT: ret void
24 //
25 // CHECK: [[lpad]]
26 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
27 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
28 // CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
29 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
30
31 // CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{.*}})
32 // CHECK-SAME: [[finally_attrs:#[0-9]+]]
33 // CHECK: call void @cleanup()
34
35 // Mostly check that we don't double emit 'r' which would crash.
decl_in_finally(void)36 void decl_in_finally(void) {
37 __try {
38 might_crash();
39 } __finally {
40 int r;
41 }
42 }
43
44 // Ditto, don't crash double emitting 'l'.
label_in_finally(void)45 void label_in_finally(void) {
46 __try {
47 might_crash();
48 } __finally {
49 l:
50 cleanup();
51 if (check_condition())
52 goto l;
53 }
54 }
55
56 // CHECK-LABEL: define void @label_in_finally()
57 // CHECK: invoke void @might_crash()
58 // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
59 //
60 // CHECK: [[invoke_cont]]
61 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
62 // CHECK: call void @"\01?fin$0@0@label_in_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
63 // CHECK: ret void
64
65 // CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"({{.*}})
66 // CHECK-SAME: [[finally_attrs]]
67 // CHECK: br label %[[l:[^ ]*]]
68 //
69 // CHECK: [[l]]
70 // CHECK: call void @cleanup()
71 // CHECK: call i32 @check_condition()
72 // CHECK: br i1 {{.*}}, label
73 // CHECK: br label %[[l]]
74
75 int crashed;
use_abnormal_termination(void)76 void use_abnormal_termination(void) {
77 __try {
78 might_crash();
79 } __finally {
80 crashed = __abnormal_termination();
81 }
82 }
83
84 // CHECK-LABEL: define void @use_abnormal_termination()
85 // CHECK: invoke void @might_crash()
86 // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
87 //
88 // CHECK: [[invoke_cont]]
89 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
90 // CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
91 // CHECK: ret void
92 //
93 // CHECK: [[lpad]]
94 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
95 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
96 // CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
97 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
98
99 // CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} %[[abnormal:abnormal_termination]], i8* %frame_pointer)
100 // CHECK-SAME: [[finally_attrs]]
101 // CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %[[abnormal]] to i32
102 // CHECK: store i32 %[[abnormal_zext]], i32* @crashed
103 // CHECK-NEXT: ret void
104
noreturn_noop_finally()105 void noreturn_noop_finally() {
106 __try {
107 __noop();
108 } __finally {
109 abort();
110 }
111 }
112
113 // CHECK-LABEL: define void @noreturn_noop_finally()
114 // CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
115 // CHECK: ret void
116
117 // CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
118 // CHECK-SAME: [[finally_attrs]]
119 // CHECK: call void @abort()
120 // CHECK: unreachable
121
noreturn_finally()122 void noreturn_finally() {
123 __try {
124 might_crash();
125 } __finally {
126 abort();
127 }
128 }
129
130 // CHECK-LABEL: define void @noreturn_finally()
131 // CHECK: invoke void @might_crash()
132 // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
133 //
134 // CHECK: [[cont]]
135 // CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
136 // CHECK: ret void
137 //
138 // CHECK: [[lpad]]
139 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
140 // CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
141 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
142
143 // CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
144 // CHECK-SAME: [[finally_attrs]]
145 // CHECK: call void @abort()
146 // CHECK: unreachable
147
finally_with_return()148 int finally_with_return() {
149 __try {
150 return 42;
151 } __finally {
152 }
153 }
154 // CHECK-LABEL: define i32 @finally_with_return()
155 // CHECK: call void @"\01?fin$0@0@finally_with_return@@"({{.*}})
156 // CHECK-NEXT: ret i32 42
157
158 // CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"({{.*}})
159 // CHECK-SAME: [[finally_attrs]]
160 // CHECK-NOT: br i1
161 // CHECK-NOT: br label
162 // CHECK: ret void
163
nested___finally___finally()164 int nested___finally___finally() {
165 __try {
166 __try {
167 } __finally {
168 return 1;
169 }
170 } __finally {
171 // Intentionally no return here.
172 }
173 return 0;
174 }
175
176 // CHECK-LABEL: define i32 @nested___finally___finally
177 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
178 // CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
179 //
180 // CHECK: [[outercont]]
181 // CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
182 // CHECK-NEXT: ret i32 0
183 //
184 // CHECK: [[lpad]]
185 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
186 // CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
187 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
188
189 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
190 // CHECK-SAME: [[finally_attrs]]
191 // CHECK: ret void
192
193 // CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
194 // CHECK-SAME: [[finally_attrs]]
195 // CHECK: unreachable
196
197 // FIXME: Our behavior seems suspiciously different.
198
nested___finally___finally_with_eh_edge()199 int nested___finally___finally_with_eh_edge() {
200 __try {
201 __try {
202 might_crash();
203 } __finally {
204 return 899;
205 }
206 } __finally {
207 // Intentionally no return here.
208 }
209 return 912;
210 }
211 // CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge
212 // CHECK: invoke void @might_crash()
213 // CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]]
214 //
215 // [[invokecont]]
216 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
217 // CHECK-NEXT: to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
218 //
219 // CHECK: [[outercont]]
220 // CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
221 // CHECK-NEXT: ret i32 912
222 //
223 // CHECK: [[lpad1]]
224 // CHECK-NEXT: %[[innerpad:[^ ]*]] = cleanuppad
225 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
226 // CHECK-NEXT: label %[[innercleanupretbb:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
227 //
228 // CHECK: [[innercleanupretbb]]
229 // CHECK-NEXT: cleanupret from %[[innerpad]] unwind label %[[lpad2]]
230 //
231 // CHECK: [[lpad2]]
232 // CHECK-NEXT: %[[outerpad:[^ ]*]] = cleanuppad
233 // CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
234 // CHECK-NEXT: cleanupret from %[[outerpad]] unwind to caller
235
236 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
237 // CHECK-SAME: [[finally_attrs]]
238 // CHECK: ret void
239
240 // CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
241 // CHECK-SAME: [[finally_attrs]]
242 // CHECK: unreachable
243
finally_within_finally()244 void finally_within_finally() {
245 __try {
246 might_crash();
247 } __finally {
248 __try {
249 might_crash();
250 } __finally {
251 }
252 }
253 }
254
255 // CHECK-LABEL: define void @finally_within_finally(
256 // CHECK: invoke void @might_crash(
257
258 // CHECK: call void @"\01?fin$0@0@finally_within_finally@@"(
259 // CHECK: call void @"\01?fin$0@0@finally_within_finally@@"({{.*}}) [ "funclet"(
260
261 // CHECK-LABEL: define internal void @"\01?fin$0@0@finally_within_finally@@"({{[^)]*}})
262 // CHECK-SAME: [[finally_attrs]]
263 // CHECK: invoke void @might_crash(
264
265 // CHECK: call void @"\01?fin$1@0@finally_within_finally@@"(
266 // CHECK: call void @"\01?fin$1@0@finally_within_finally@@"({{.*}}) [ "funclet"(
267
268 // CHECK-LABEL: define internal void @"\01?fin$1@0@finally_within_finally@@"({{[^)]*}})
269 // CHECK-SAME: [[finally_attrs]]
270
271 // Look for the absence of noinline. Enum attributes come first, so check that
272 // a string attribute is the first to verify that no enum attributes are
273 // present.
274 // CHECK: attributes [[finally_attrs]] = { "{{.*}}" }
275