blob: eeadf0d5ec59c4c64da66d7acf5849a6a9c160e9 [file] [log] [blame]
Reid Klecknerdeeddec2015-02-05 18:56:03 +00001// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
Reid Kleckner1d59f992015-01-22 01:36:17 +00002
Reid Kleckner16f9a6b2015-02-05 00:58:46 +00003void abort(void) __attribute__((noreturn));
Reid Kleckner1d59f992015-01-22 01:36:17 +00004void might_crash(void);
5void cleanup(void);
6int check_condition(void);
7void basic_finally(void) {
8 __try {
9 might_crash();
10 } __finally {
11 cleanup();
12 }
13}
14
15// CHECK-LABEL: define void @basic_finally()
16// CHECK: invoke void @might_crash()
Reid Kleckneraca01db2015-02-04 22:37:07 +000017// CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
18//
19// CHECK: [[invoke_cont]]
Nico Weberbd51a6a2015-04-10 04:33:03 +000020// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]]
21// CHECK: br label %[[finally:[^ ]*]]
22//
23// CHECK: [[finally]]
24// CHECK: call void @cleanup()
25// CHECK: load i8, i8* %[[abnormal]]
26// CHECK: icmp eq
27// CHECK: br i1 %{{.*}}, label %[[finallycont:[^ ]*]], label %[[resumecont:[^ ]*]]
28//
29// CHECK: [[finallycont]]
Reid Kleckneraca01db2015-02-04 22:37:07 +000030// CHECK-NEXT: ret void
31//
32// CHECK: [[lpad]]
33// CHECK-NEXT: landingpad
Reid Kleckner1d59f992015-01-22 01:36:17 +000034// CHECK-NEXT: cleanup
Nico Weberbd51a6a2015-04-10 04:33:03 +000035// CHECK: store i8 1, i8* %[[abnormal]]
36// CHECK: br label %[[finally]]
37//
38// CHECK: [[resumecont]]
39// CHECK: br label %[[ehresume:[^ ]*]]
40//
41// CHECK: [[ehresume]]
Reid Kleckneraca01db2015-02-04 22:37:07 +000042// CHECK: resume { i8*, i32 }
Reid Kleckner1d59f992015-01-22 01:36:17 +000043
Reid Kleckneraca01db2015-02-04 22:37:07 +000044// Mostly check that we don't double emit 'r' which would crash.
45void decl_in_finally(void) {
46 __try {
47 might_crash();
48 } __finally {
49 int r;
50 }
51}
52
53// Ditto, don't crash double emitting 'l'.
54void label_in_finally(void) {
Reid Kleckner1d59f992015-01-22 01:36:17 +000055 __try {
56 might_crash();
57 } __finally {
58l:
59 cleanup();
60 if (check_condition())
61 goto l;
62 }
63}
Reid Kleckneraca01db2015-02-04 22:37:07 +000064
65// CHECK-LABEL: define void @label_in_finally()
66// CHECK: invoke void @might_crash()
67// CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
68//
69// CHECK: [[invoke_cont]]
Nico Weberbd51a6a2015-04-10 04:33:03 +000070// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]]
71// CHECK: br label %[[finally:[^ ]*]]
72//
73// CHECK: [[finally]]
Reid Kleckneraca01db2015-02-04 22:37:07 +000074// CHECK: br label %[[l:[^ ]*]]
75//
76// CHECK: [[l]]
77// CHECK: call void @cleanup()
78// CHECK: call i32 @check_condition()
79// CHECK: br i1 {{.*}}, label
80// CHECK: br label %[[l]]
81
82int crashed;
83void use_abnormal_termination(void) {
84 __try {
85 might_crash();
86 } __finally {
87 crashed = __abnormal_termination();
88 }
89}
90
91// CHECK-LABEL: define void @use_abnormal_termination()
92// CHECK: invoke void @might_crash()
93// CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
94//
95// CHECK: [[invoke_cont]]
Nico Weberbd51a6a2015-04-10 04:33:03 +000096// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]]
97// CHECK: br label %[[finally:[^ ]*]]
98//
99// CHECK: [[finally]]
100// CHECK: load i8, i8* %[[abnormal]]
101// CHECK: zext i8 %{{.*}} to i32
102// CHECK: store i32 %{{.*}}, i32* @crashed
103// CHECK: load i8, i8* %[[abnormal]]
104// CHECK: icmp eq
105// CHECK: br i1 %{{.*}}, label %[[finallycont:[^ ]*]], label %[[resumecont:[^ ]*]]
106//
107// CHECK: [[finallycont]]
108// CHECK-NEXT: ret void
Reid Kleckneraca01db2015-02-04 22:37:07 +0000109//
110// CHECK: [[lpad]]
111// CHECK-NEXT: landingpad
112// CHECK-NEXT: cleanup
Nico Weberbd51a6a2015-04-10 04:33:03 +0000113// CHECK: store i8 1, i8* %[[abnormal]]
114// CHECK: br label %[[finally]]
115//
116// CHECK: [[resumecont]]
117// CHECK: br label %[[ehresume:[^ ]*]]
118//
119// CHECK: [[ehresume]]
Reid Kleckneraca01db2015-02-04 22:37:07 +0000120// CHECK: resume { i8*, i32 }
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000121
122void noreturn_noop_finally() {
123 __try {
124 __noop();
125 } __finally {
126 abort();
127 }
128}
129
130// CHECK-LABEL: define void @noreturn_noop_finally()
Nico Weberbd51a6a2015-04-10 04:33:03 +0000131// CHECK: store i8 0, i8* %
132// CHECK: br label %[[finally:[^ ]*]]
133// CHECK: [[finally]]
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000134// CHECK: call void @abort()
Nico Weberbd51a6a2015-04-10 04:33:03 +0000135// CHECK-NEXT: unreachable
136// CHECK-NOT: load
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000137
138void noreturn_finally() {
139 __try {
140 might_crash();
141 } __finally {
142 abort();
143 }
144}
145
146// CHECK-LABEL: define void @noreturn_finally()
147// CHECK: invoke void @might_crash()
148// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
149//
150// CHECK: [[cont]]
Nico Weberbd51a6a2015-04-10 04:33:03 +0000151// CHECK: store i8 0, i8* %
152// CHECK: br label %[[finally:[^ ]*]]
153//
154// CHECK: [[finally]]
155// CHECK: call void @abort()
156// CHECK-NEXT: unreachable
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000157//
158// CHECK: [[lpad]]
159// CHECK: landingpad
160// CHECK-NEXT: cleanup
Nico Weberbd51a6a2015-04-10 04:33:03 +0000161// CHECK: store i8 1, i8* %
162// CHECK: br label %[[finally]]
Nico Webere68b9f32015-02-25 16:25:00 +0000163
164int finally_with_return() {
165 __try {
166 return 42;
167 } __finally {
168 }
169}
170// CHECK-LABEL: define i32 @finally_with_return()
Nico Weberbd51a6a2015-04-10 04:33:03 +0000171// CHECK: store i8 0, i8* %
172// CHECK-NEXT: br label %[[finally:[^ ]*]]
173//
174// CHECK: [[finally]]
175// CHECK-NEXT: br label %[[finallycont:[^ ]*]]
176//
177// CHECK: [[finallycont]]
Nico Webere68b9f32015-02-25 16:25:00 +0000178// CHECK-NEXT: ret i32 42
179
180int nested___finally___finally() {
181 __try {
182 __try {
183 } __finally {
184 return 1;
185 }
186 } __finally {
187 // Intentionally no return here.
188 }
189 return 0;
190}
191// CHECK-LABEL: define i32 @nested___finally___finally
Nico Weberbd51a6a2015-04-10 04:33:03 +0000192// CHECK: store i8 0, i8* %
193// CHECK-NEXT: br label %[[finally:[^ ]*]]
Nico Webere68b9f32015-02-25 16:25:00 +0000194//
Nico Weberbd51a6a2015-04-10 04:33:03 +0000195// CHECK: [[finally]]
196// CHECK-NEXT: store i32 1, i32* %
197// CHECK-NEXT: store i32 1, i32* %
198// CHECK-NEXT: br label %[[cleanup:[^ ]*]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000199//
Nico Weberbd51a6a2015-04-10 04:33:03 +0000200// The finally's unreachable continuation block:
201// CHECK: store i32 0, i32* %
202// CHECK-NEXT: br label %[[cleanup]]
203//
204// CHECK: [[cleanup]]
205// CHECK-NEXT: store i8 0, i8* %
206// CHECK-NEXT: br label %[[outerfinally:[^ ]*]]
207//
208// CHECK: [[outerfinally]]
209// CHECK-NEXT: br label %[[finallycont:[^ ]*]]
210//
211// CHECK: [[finallycont]]
212// CHECK-NEXT: %[[dest:[^ ]*]] = load i32, i32* %
213// CHECK-NEXT: switch i32 %[[dest]]
214// CHECK-NEXT: i32 0, label %[[cleanupcont:[^ ]*]]
215//
216// CHECK: [[cleanupcont]]
217// CHECK-NEXT: store i32 0, i32* %
218// CHECK-NEXT: br label %[[return:[^ ]*]]
219//
220// CHECK: [[return]]
221// CHECK-NEXT: %[[reg:[^ ]*]] = load i32, i32* %
222// CHECK-NEXT: ret i32 %[[reg]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000223
224int nested___finally___finally_with_eh_edge() {
225 __try {
226 __try {
227 might_crash();
228 } __finally {
229 return 899;
230 }
231 } __finally {
232 // Intentionally no return here.
233 }
234 return 912;
235}
236// CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge
Nico Weberbd51a6a2015-04-10 04:33:03 +0000237// CHECK: invoke void @might_crash() #3
238// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000239//
Nico Weberbd51a6a2015-04-10 04:33:03 +0000240// CHECK: [[invokecont]]
241// CHECK-NEXT: store i8 0, i8* %[[abnormal:[^ ]*]]
242// CHECK-NEXT: br label %[[finally:[^ ]*]]
243
244// CHECK: [[finally]]
245// CHECK-NEXT: store i32 899, i32* %
246// CHECK-NEXT: store i32 1, i32* %
247// CHECK-NEXT: br label %[[cleanup:[^ ]*]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000248//
Nico Weberbd51a6a2015-04-10 04:33:03 +0000249// The inner finally's unreachable continuation block:
250// CHECK: store i32 0, i32* %
251// CHECK-NEXT: br label %[[cleanup]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000252//
Nico Weberbd51a6a2015-04-10 04:33:03 +0000253// CHECK: [[cleanup]]
254// CHECK-NEXT: store i8 0, i8* %
255// CHECK-NEXT: br label %[[outerfinally:[^ ]*]]
256//
257// CHECK: [[outerfinally]]
258// CHECK-NEXT: %[[abnormallocal:[^ ]*]] = load i8, i8* %[[abnormal]]
259// CHECK-NEXT: %[[reg:[^ ]*]] = icmp eq i8 %[[abnormallocal]], 0
260// CHECK-NEXT: br i1 %[[reg]], label %[[finallycont:[^ ]*]], label %[[finallyresume:[^ ]*]]
261//
262// CHECK: [[finallycont]]
263// CHECK-NEXT: %[[dest:[^ ]*]] = load i32, i32* %
264// CHECK-NEXT: switch i32 %[[dest]]
265// CHECK-NEXT: i32 0, label %[[cleanupcont:[^ ]*]]
266//
267// CHECK: [[cleanupcont]]
268// CHECK-NEXT: store i32 912, i32* %
269// CHECK-NEXT: br label %[[return:[^ ]*]]
270//
271//
272// CHECK: [[lpad]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000273// CHECK-NEXT: landingpad
274// CHECK-NEXT: cleanup
Nico Weberbd51a6a2015-04-10 04:33:03 +0000275// CHECK: store i8 1, i8* %[[abnormal]]
276// CHECK: br label %[[finally]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000277//
Nico Weberbd51a6a2015-04-10 04:33:03 +0000278// The inner finally's unreachable resume block:
279// CHECK: store i8 1, i8* %[[abnormal]]
280// CHECK-NEXT: br label %[[outerfinally]]
281//
282// CHECK: [[finallyresume]]
283// CHECK-NEXT: br label %[[ehresume:[^ ]*]]
284//
285// CHECK: [[return]]
286// CHECK-NEXT: %[[reg:[^ ]*]] = load i32, i32* %
287// CHECK-NEXT: ret i32 %[[reg]]
288//
289// The ehresume block, not reachable either.
290// CHECK: [[ehresume]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000291// CHECK: resume