blob: 345d514611e30e1273647013f4fe82ca99758486 [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 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]]
Reid Klecknereb11c412015-07-01 21:00:00 +000020// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
Nico Webere4f974c2015-07-02 06:10:53 +000021// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i8 0, i8* %[[fp]])
Reid Kleckneraca01db2015-02-04 22:37:07 +000022// CHECK-NEXT: ret void
23//
24// CHECK: [[lpad]]
25// CHECK-NEXT: landingpad
Reid Kleckner1d59f992015-01-22 01:36:17 +000026// CHECK-NEXT: cleanup
Reid Klecknereb11c412015-07-01 21:00:00 +000027// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
Nico Webere4f974c2015-07-02 06:10:53 +000028// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i8 1, i8* %[[fp]])
Reid Kleckneraca01db2015-02-04 22:37:07 +000029// CHECK: resume { i8*, i32 }
Reid Kleckner1d59f992015-01-22 01:36:17 +000030
Nico Webere4f974c2015-07-02 06:10:53 +000031// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
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 Klecknereb11c412015-07-01 21:00:00 +000060// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
Nico Webere4f974c2015-07-02 06:10:53 +000061// CHECK: call void @"\01?fin$0@0@label_in_finally@@"(i8 0, i8* %[[fp]])
Reid Klecknerebaf28d2015-04-14 20:59:00 +000062// CHECK: ret void
63
Nico Webere4f974c2015-07-02 06:10:53 +000064// CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
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 Klecknereb11c412015-07-01 21:00:00 +000087// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
Nico Webere4f974c2015-07-02 06:10:53 +000088// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i8 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]]
92// CHECK-NEXT: landingpad
93// CHECK-NEXT: cleanup
Reid Klecknereb11c412015-07-01 21:00:00 +000094// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
Nico Webere4f974c2015-07-02 06:10:53 +000095// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i8 1, i8* %[[fp]])
Reid Kleckneraca01db2015-02-04 22:37:07 +000096// CHECK: resume { i8*, i32 }
Reid Kleckner16f9a6b2015-02-05 00:58:46 +000097
Nico Webere4f974c2015-07-02 06:10:53 +000098// CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"(i8 %abnormal_termination, i8* %frame_pointer)
99// CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %abnormal_termination to i32
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000100// CHECK: store i32 %[[abnormal_zext]], i32* @crashed
101// CHECK-NEXT: ret void
102
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000103void noreturn_noop_finally() {
104 __try {
105 __noop();
106 } __finally {
107 abort();
108 }
109}
110
111// CHECK-LABEL: define void @noreturn_noop_finally()
Nico Webere4f974c2015-07-02 06:10:53 +0000112// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
113// CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"(i8 0, i8* %[[fp]])
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000114// CHECK: ret void
115
Nico Webere4f974c2015-07-02 06:10:53 +0000116// CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000117// CHECK: call void @abort()
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000118// CHECK: unreachable
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000119
120void noreturn_finally() {
121 __try {
122 might_crash();
123 } __finally {
124 abort();
125 }
126}
127
128// CHECK-LABEL: define void @noreturn_finally()
129// CHECK: invoke void @might_crash()
130// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
131//
132// CHECK: [[cont]]
Nico Webere4f974c2015-07-02 06:10:53 +0000133// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
134// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i8 0, i8* %[[fp]])
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000135// CHECK: ret void
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000136//
137// CHECK: [[lpad]]
138// CHECK: landingpad
139// CHECK-NEXT: cleanup
Nico Webere4f974c2015-07-02 06:10:53 +0000140// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
141// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i8 1, i8* %[[fp]])
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000142// CHECK: resume { i8*, i32 }
143
Nico Webere4f974c2015-07-02 06:10:53 +0000144// CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000145// CHECK: call void @abort()
146// CHECK: unreachable
Nico Webere68b9f32015-02-25 16:25:00 +0000147
148int finally_with_return() {
149 __try {
150 return 42;
151 } __finally {
152 }
153}
154// CHECK-LABEL: define i32 @finally_with_return()
Nico Webere4f974c2015-07-02 06:10:53 +0000155// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
156// CHECK-NEXT: call void @"\01?fin$0@0@finally_with_return@@"(i8 0, i8* %[[fp]])
Nico Webere68b9f32015-02-25 16:25:00 +0000157// CHECK-NEXT: ret i32 42
158
Nico Webere4f974c2015-07-02 06:10:53 +0000159// CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"(i8 %abnormal_termination, i8* %frame_pointer)
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000160// CHECK-NOT: br i1
161// CHECK-NOT: br label
162// CHECK: ret void
163
Nico Webere68b9f32015-02-25 16:25:00 +0000164int 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}
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000175
Nico Webere68b9f32015-02-25 16:25:00 +0000176// CHECK-LABEL: define i32 @nested___finally___finally
Nico Webere4f974c2015-07-02 06:10:53 +0000177// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
178// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i8 0, i8* %[[fp]])
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000179// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
Nico Webere68b9f32015-02-25 16:25:00 +0000180//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000181// CHECK: [[outercont]]
Nico Webere4f974c2015-07-02 06:10:53 +0000182// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
183// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i8 0, i8* %[[fp]])
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000184// CHECK-NEXT: ret i32 0
Nico Weberff62a6a2015-02-26 22:34:33 +0000185//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000186// CHECK: [[lpad]]
187// CHECK-NEXT: landingpad
188// CHECK-NEXT: cleanup
Nico Webere4f974c2015-07-02 06:10:53 +0000189// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
190// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000191
Nico Webere4f974c2015-07-02 06:10:53 +0000192// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000193// CHECK: ret void
194
Nico Webere4f974c2015-07-02 06:10:53 +0000195// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000196// CHECK: unreachable
Nico Weberff62a6a2015-02-26 22:34:33 +0000197
198int nested___finally___finally_with_eh_edge() {
199 __try {
200 __try {
201 might_crash();
202 } __finally {
203 return 899;
204 }
205 } __finally {
206 // Intentionally no return here.
207 }
208 return 912;
209}
210// CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000211// CHECK: invoke void @might_crash()
212// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000213//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000214// [[invokecont]]
Nico Webere4f974c2015-07-02 06:10:53 +0000215// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
216// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i8 0, i8* %[[fp]])
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000217// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000218//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000219// CHECK: [[outercont]]
Nico Webere4f974c2015-07-02 06:10:53 +0000220// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
221// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i8 0, i8* %[[fp]])
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000222// CHECK-NEXT: ret i32 912
Nico Weberff62a6a2015-02-26 22:34:33 +0000223//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000224// CHECK: [[lpad1]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000225// CHECK-NEXT: landingpad
226// CHECK-NEXT: cleanup
Nico Webere4f974c2015-07-02 06:10:53 +0000227// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
228// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i8 1, i8* %[[fp]])
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000229// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000230//
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000231// CHECK: [[lpad2]]
232// CHECK-NEXT: landingpad
233// CHECK-NEXT: cleanup
Nico Webere4f974c2015-07-02 06:10:53 +0000234// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
235// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i8 1, i8* %[[fp]])
Nico Weberff62a6a2015-02-26 22:34:33 +0000236// CHECK: resume
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000237
Nico Webere4f974c2015-07-02 06:10:53 +0000238// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i8 %abnormal_termination, i8* %frame_pointer)
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000239// CHECK: ret void
240
Nico Webere4f974c2015-07-02 06:10:53 +0000241// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i8 %abnormal_termination, i8* %frame_pointer)
Reid Klecknerebaf28d2015-04-14 20:59:00 +0000242// CHECK: unreachable