blob: be1501f9e9dbbdcfd0d8a88a77c8f9d934487535 [file] [log] [blame]
Reid Klecknereb11c412015-07-01 21:00:00 +00001// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
Reid Kleckner8819a402015-07-10 00:16:25 +00002// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
Reid Kleckner1d59f992015-01-22 01:36:17 +00003
Reid Kleckner16f9a6b2015-02-05 00:58:46 +00004void abort(void) __attribute__((noreturn));
Reid Kleckner1d59f992015-01-22 01:36:17 +00005void might_crash(void);
6void cleanup(void);
7int check_condition(void);
8void 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()
Reid Kleckneraca01db2015-02-04 22:37:07 +000018// CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
19//
20// CHECK: [[invoke_cont]]
Reid Kleckner15d152d2015-07-07 23:23:31 +000021// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
Reid Kleckner9fe7f232015-07-07 00:36:30 +000022// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
Reid Kleckneraca01db2015-02-04 22:37:07 +000023// CHECK-NEXT: ret void
24//
25// CHECK: [[lpad]]
Reid Kleckner129552b2015-10-08 01:13:52 +000026// CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
Reid Kleckner15d152d2015-07-07 23:23:31 +000027// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
David Majnemer4e52d6f2015-12-12 05:39:21 +000028// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
29// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
Reid Kleckner1d59f992015-01-22 01:36:17 +000030
Reid Kleckner9fe7f232015-07-07 00:36:30 +000031// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +000032// CHECK: call void @cleanup()
33
Reid Kleckneraca01db2015-02-04 22:37:07 +000034// Mostly check that we don't double emit 'r' which would crash.
35void decl_in_finally(void) {
36 __try {
37 might_crash();
38 } __finally {
39 int r;
40 }
41}
42
43// Ditto, don't crash double emitting 'l'.
44void label_in_finally(void) {
Reid Kleckner1d59f992015-01-22 01:36:17 +000045 __try {
46 might_crash();
47 } __finally {
48l:
49 cleanup();
50 if (check_condition())
51 goto l;
52 }
53}
Reid Kleckneraca01db2015-02-04 22:37:07 +000054
55// CHECK-LABEL: define void @label_in_finally()
56// CHECK: invoke void @might_crash()
57// CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
58//
59// CHECK: [[invoke_cont]]
Reid Kleckner15d152d2015-07-07 23:23:31 +000060// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
Reid Kleckner9fe7f232015-07-07 00:36:30 +000061// CHECK: call void @"\01?fin$0@0@label_in_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
Reid Klecknerebaf28d2015-04-14 20:59:00 +000062// CHECK: ret void
63
Reid Kleckner9fe7f232015-07-07 00:36:30 +000064// CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"({{.*}})
Reid Kleckneraca01db2015-02-04 22:37:07 +000065// CHECK: br label %[[l:[^ ]*]]
66//
67// CHECK: [[l]]
68// CHECK: call void @cleanup()
69// CHECK: call i32 @check_condition()
70// CHECK: br i1 {{.*}}, label
71// CHECK: br label %[[l]]
72
73int crashed;
74void use_abnormal_termination(void) {
75 __try {
76 might_crash();
77 } __finally {
78 crashed = __abnormal_termination();
79 }
80}
81
82// CHECK-LABEL: define void @use_abnormal_termination()
83// CHECK: invoke void @might_crash()
84// CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
85//
86// CHECK: [[invoke_cont]]
Reid Kleckner15d152d2015-07-07 23:23:31 +000087// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
Reid Kleckner9fe7f232015-07-07 00:36:30 +000088// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
Reid Klecknerebaf28d2015-04-14 20:59:00 +000089// CHECK: ret void
Reid Kleckneraca01db2015-02-04 22:37:07 +000090//
91// CHECK: [[lpad]]
Reid Kleckner129552b2015-10-08 01:13:52 +000092// CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
Reid Kleckner15d152d2015-07-07 23:23:31 +000093// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
David Majnemer4e52d6f2015-12-12 05:39:21 +000094// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
95// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
Reid Kleckner16f9a6b2015-02-05 00:58:46 +000096
Reid Kleckner9fe7f232015-07-07 00:36:30 +000097// CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} %[[abnormal:abnormal_termination]], i8* %frame_pointer)
98// CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %[[abnormal]] to i32
Reid Klecknerebaf28d2015-04-14 20:59:00 +000099// CHECK: store i32 %[[abnormal_zext]], i32* @crashed
100// CHECK-NEXT: ret void
101
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000102void noreturn_noop_finally() {
103 __try {
104 __noop();
105 } __finally {
106 abort();
107 }
108}
109
110// CHECK-LABEL: define void @noreturn_noop_finally()
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000111// CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000112// CHECK: ret void
113
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000114// CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000115// CHECK: call void @abort()
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000116// CHECK: unreachable
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000117
118void noreturn_finally() {
119 __try {
120 might_crash();
121 } __finally {
122 abort();
123 }
124}
125
126// CHECK-LABEL: define void @noreturn_finally()
127// CHECK: invoke void @might_crash()
128// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
129//
130// CHECK: [[cont]]
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000131// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000132// CHECK: ret void
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000133//
134// CHECK: [[lpad]]
Reid Kleckner129552b2015-10-08 01:13:52 +0000135// CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
David Majnemer4e52d6f2015-12-12 05:39:21 +0000136// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
137// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000138
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000139// CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000140// CHECK: call void @abort()
141// CHECK: unreachable
Nico Webere68b9f32015-02-25 16:25:00 +0000142
143int finally_with_return() {
144 __try {
145 return 42;
146 } __finally {
147 }
148}
149// CHECK-LABEL: define i32 @finally_with_return()
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000150// CHECK: call void @"\01?fin$0@0@finally_with_return@@"({{.*}})
Nico Webere68b9f32015-02-25 16:25:00 +0000151// CHECK-NEXT: ret i32 42
152
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000153// CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000154// CHECK-NOT: br i1
155// CHECK-NOT: br label
156// CHECK: ret void
157
Nico Webere68b9f32015-02-25 16:25:00 +0000158int nested___finally___finally() {
159 __try {
160 __try {
161 } __finally {
162 return 1;
163 }
164 } __finally {
165 // Intentionally no return here.
166 }
167 return 0;
168}
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000169
Nico Webere68b9f32015-02-25 16:25:00 +0000170// CHECK-LABEL: define i32 @nested___finally___finally
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000171// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000172// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
Nico Webere68b9f32015-02-25 16:25:00 +0000173//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000174// CHECK: [[outercont]]
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000175// CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000176// CHECK-NEXT: ret i32 0
Nico Weberff62a6a2015-02-26 22:34:33 +0000177//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000178// CHECK: [[lpad]]
Reid Kleckner129552b2015-10-08 01:13:52 +0000179// CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
David Majnemer4e52d6f2015-12-12 05:39:21 +0000180// CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
181// CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000182
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000183// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000184// CHECK: ret void
185
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000186// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000187// CHECK: unreachable
Nico Weberff62a6a2015-02-26 22:34:33 +0000188
Reid Kleckner129552b2015-10-08 01:13:52 +0000189// FIXME: Our behavior seems suspiciously different.
190
Nico Weberff62a6a2015-02-26 22:34:33 +0000191int nested___finally___finally_with_eh_edge() {
192 __try {
193 __try {
194 might_crash();
195 } __finally {
196 return 899;
197 }
198 } __finally {
199 // Intentionally no return here.
200 }
201 return 912;
202}
203// CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000204// CHECK: invoke void @might_crash()
205// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000206//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000207// [[invokecont]]
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000208// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
Reid Kleckner129552b2015-10-08 01:13:52 +0000209// CHECK-NEXT: to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000210//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000211// CHECK: [[outercont]]
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000212// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000213// CHECK-NEXT: ret i32 912
Nico Weberff62a6a2015-02-26 22:34:33 +0000214//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000215// CHECK: [[lpad1]]
Reid Kleckner129552b2015-10-08 01:13:52 +0000216// CHECK-NEXT: %[[innerpad:[^ ]*]] = cleanuppad
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000217// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
David Majnemer4e52d6f2015-12-12 05:39:21 +0000218// CHECK-NEXT: label %[[innercleanupretbb:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
Reid Kleckner129552b2015-10-08 01:13:52 +0000219//
220// CHECK: [[innercleanupretbb]]
David Majnemer4e52d6f2015-12-12 05:39:21 +0000221// CHECK-NEXT: cleanupret from %[[innerpad]] unwind label %[[lpad2]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000222//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000223// CHECK: [[lpad2]]
Reid Kleckner129552b2015-10-08 01:13:52 +0000224// CHECK-NEXT: %[[outerpad:[^ ]*]] = cleanuppad
David Majnemer4e52d6f2015-12-12 05:39:21 +0000225// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
226// CHECK-NEXT: cleanupret from %[[outerpad]] unwind to caller
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000227
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000228// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000229// CHECK: ret void
230
Reid Kleckner9fe7f232015-07-07 00:36:30 +0000231// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000232// CHECK: unreachable
David Majnemer25eb1652016-03-01 19:42:53 +0000233
234void finally_within_finally() {
235 __try {
236 might_crash();
237 } __finally {
238 __try {
239 might_crash();
240 } __finally {
241 }
242 }
243}
244
245// CHECK-LABEL: define void @finally_within_finally(
246// CHECK: invoke void @might_crash(
247
248// CHECK: call void @"\01?fin$0@0@finally_within_finally@@"(
249// CHECK: call void @"\01?fin$0@0@finally_within_finally@@"({{.*}}) [ "funclet"(
250
251// CHECK-LABEL: define internal void @"\01?fin$0@0@finally_within_finally@@"(
252// CHECK: invoke void @might_crash(
253
254// CHECK: call void @"\01?fin$1@0@finally_within_finally@@"(
255// CHECK: call void @"\01?fin$1@0@finally_within_finally@@"({{.*}}) [ "funclet"(
256
257// CHECK-LABEL: define internal void @"\01?fin$1@0@finally_within_finally@@"(