blob: a315379d525e0bc77baeec77b38cafcdb988d58e [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]]
Reid Kleckner11859af2015-04-10 17:34:52 +000020// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
21// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext false, 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 Kleckner11859af2015-04-10 17:34:52 +000027// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
28// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext true, i8* %[[fp]])
Reid Kleckneraca01db2015-02-04 22:37:07 +000029// CHECK: resume { i8*, i32 }
Reid Kleckner1d59f992015-01-22 01:36:17 +000030
Reid Kleckner11859af2015-04-10 17:34:52 +000031// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
32// 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 Kleckner11859af2015-04-10 17:34:52 +000060// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
61// CHECK: call void @"\01?fin$0@0@label_in_finally@@"(i1 zeroext false, i8* %[[fp]])
62// CHECK: ret void
63
64// CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"(i1 zeroext %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 Kleckner11859af2015-04-10 17:34:52 +000087// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
88// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext false, i8* %[[fp]])
89// CHECK: ret void
Reid Kleckneraca01db2015-02-04 22:37:07 +000090//
91// CHECK: [[lpad]]
92// CHECK-NEXT: landingpad
93// CHECK-NEXT: cleanup
Reid Kleckner11859af2015-04-10 17:34:52 +000094// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
95// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext true, i8* %[[fp]])
Reid Kleckneraca01db2015-02-04 22:37:07 +000096// CHECK: resume { i8*, i32 }
Reid Kleckner16f9a6b2015-02-05 00:58:46 +000097
Reid Kleckner11859af2015-04-10 17:34:52 +000098// CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
99// CHECK: %[[abnormal_zext:[^ ]*]] = zext i1 %abnormal_termination to i32
100// 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()
Reid Kleckner11859af2015-04-10 17:34:52 +0000112// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
113// CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"(i1 zeroext false, i8* %[[fp]])
114// CHECK: ret void
115
116// CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000117// CHECK: call void @abort()
Reid Kleckner11859af2015-04-10 17:34:52 +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]]
Reid Kleckner11859af2015-04-10 17:34:52 +0000133// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
134// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext false, i8* %[[fp]])
135// CHECK: ret void
Reid Kleckner16f9a6b2015-02-05 00:58:46 +0000136//
137// CHECK: [[lpad]]
138// CHECK: landingpad
139// CHECK-NEXT: cleanup
Reid Kleckner11859af2015-04-10 17:34:52 +0000140// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
141// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext true, i8* %[[fp]])
142// CHECK: resume { i8*, i32 }
143
144// CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
145// 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()
Reid Kleckner11859af2015-04-10 17:34:52 +0000155// CHECK: alloca i32
156// CHECK-NEXT: store i32
157// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
158// CHECK-NEXT: call void @"\01?fin$0@0@finally_with_return@@"(i1 zeroext false, i8* %[[fp]])
Nico Webere68b9f32015-02-25 16:25:00 +0000159// CHECK-NEXT: ret i32 42
160
Reid Kleckner11859af2015-04-10 17:34:52 +0000161// CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
162// CHECK-NOT: br i1
163// CHECK-NOT: br label
164// CHECK: ret void
165
Nico Webere68b9f32015-02-25 16:25:00 +0000166int nested___finally___finally() {
167 __try {
168 __try {
169 } __finally {
170 return 1;
171 }
172 } __finally {
173 // Intentionally no return here.
174 }
175 return 0;
176}
Reid Kleckner11859af2015-04-10 17:34:52 +0000177
Nico Webere68b9f32015-02-25 16:25:00 +0000178// CHECK-LABEL: define i32 @nested___finally___finally
Reid Kleckner11859af2015-04-10 17:34:52 +0000179// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
180// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]])
181// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
Nico Webere68b9f32015-02-25 16:25:00 +0000182//
Reid Kleckner11859af2015-04-10 17:34:52 +0000183// CHECK: [[outercont]]
184// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
185// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]])
186// CHECK-NEXT: ret i32 0
Nico Weberff62a6a2015-02-26 22:34:33 +0000187//
Reid Kleckner11859af2015-04-10 17:34:52 +0000188// CHECK: [[lpad]]
189// CHECK-NEXT: landingpad
190// CHECK-NEXT: cleanup
191// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
192// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext true, i8* %[[fp]])
193
194// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
195// CHECK: ret void
196
197// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
198// CHECK: unreachable
Nico Weberff62a6a2015-02-26 22:34:33 +0000199
200int nested___finally___finally_with_eh_edge() {
201 __try {
202 __try {
203 might_crash();
204 } __finally {
205 return 899;
206 }
207 } __finally {
208 // Intentionally no return here.
209 }
210 return 912;
211}
212// CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge
Reid Kleckner11859af2015-04-10 17:34:52 +0000213// CHECK: invoke void @might_crash()
214// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000215//
Reid Kleckner11859af2015-04-10 17:34:52 +0000216// [[invokecont]]
217// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
218// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext false, i8* %[[fp]])
219// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000220//
Reid Kleckner11859af2015-04-10 17:34:52 +0000221// CHECK: [[outercont]]
222// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
223// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext false, i8* %[[fp]])
224// CHECK-NEXT: ret i32 912
Nico Weberff62a6a2015-02-26 22:34:33 +0000225//
Reid Kleckner11859af2015-04-10 17:34:52 +0000226// CHECK: [[lpad1]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000227// CHECK-NEXT: landingpad
228// CHECK-NEXT: cleanup
Reid Kleckner11859af2015-04-10 17:34:52 +0000229// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
230// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext true, i8* %[[fp]])
231// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2]]
Nico Weberff62a6a2015-02-26 22:34:33 +0000232//
Reid Kleckner11859af2015-04-10 17:34:52 +0000233// CHECK: [[lpad2]]
234// CHECK-NEXT: landingpad
235// CHECK-NEXT: cleanup
236// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
237// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext true, i8* %[[fp]])
Nico Weberff62a6a2015-02-26 22:34:33 +0000238// CHECK: resume
Reid Kleckner11859af2015-04-10 17:34:52 +0000239
240// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
241// CHECK: ret void
242
243// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
244// CHECK: unreachable