blob: 64b3ffdf187113a3fe4e96aae12c6e577b391ba3 [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]]
20// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]]
21// CHECK: br label %[[finally:[^ ]*]]
22//
23// CHECK: [[finally]]
Reid Kleckner1d59f992015-01-22 01:36:17 +000024// CHECK: call void @cleanup()
Reid Kleckneraca01db2015-02-04 22:37:07 +000025// CHECK: load i8* %[[abnormal]]
26// CHECK: icmp eq
27// CHECK: br i1 %{{.*}}, label %[[finallycont:[^ ]*]], label %[[resumecont:[^ ]*]]
Reid Kleckner1d59f992015-01-22 01:36:17 +000028//
Reid Kleckneraca01db2015-02-04 22:37:07 +000029// CHECK: [[finallycont]]
30// CHECK-NEXT: ret void
31//
32// CHECK: [[lpad]]
33// CHECK-NEXT: landingpad
Reid Kleckner1d59f992015-01-22 01:36:17 +000034// CHECK-NEXT: cleanup
Reid Kleckneraca01db2015-02-04 22:37:07 +000035// CHECK: store i8 1, i8* %[[abnormal]]
36// CHECK: br label %[[finally]]
Reid Kleckner1d59f992015-01-22 01:36:17 +000037//
Reid Kleckneraca01db2015-02-04 22:37:07 +000038// CHECK: [[resumecont]]
39// CHECK: br label %[[ehresume:[^ ]*]]
40//
41// CHECK: [[ehresume]]
42// 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]]
70// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]]
71// CHECK: br label %[[finally:[^ ]*]]
72//
73// CHECK: [[finally]]
74// 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]]
96// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]]
97// CHECK: br label %[[finally:[^ ]*]]
98//
99// CHECK: [[finally]]
100// CHECK: load i8* %[[abnormal]]
101// CHECK: zext i8 %{{.*}} to i32
102// CHECK: store i32 %{{.*}}, i32* @crashed
103// CHECK: load i8* %[[abnormal]]
104// CHECK: icmp eq
105// CHECK: br i1 %{{.*}}, label %[[finallycont:[^ ]*]], label %[[resumecont:[^ ]*]]
106//
107// CHECK: [[finallycont]]
108// CHECK-NEXT: ret void
109//
110// CHECK: [[lpad]]
111// CHECK-NEXT: landingpad
112// CHECK-NEXT: cleanup
113// CHECK: store i8 1, i8* %[[abnormal]]
114// CHECK: br label %[[finally]]
115//
116// CHECK: [[resumecont]]
117// CHECK: br label %[[ehresume:[^ ]*]]
118//
119// CHECK: [[ehresume]]
120// 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()
131// CHECK: store i8 0, i8* %
132// CHECK: br label %[[finally:[^ ]*]]
133// CHECK: [[finally]]
134// CHECK: call void @abort()
135// CHECK-NEXT: unreachable
136// CHECK-NOT: load
137
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]]
151// CHECK: store i8 0, i8* %
152// CHECK: br label %[[finally:[^ ]*]]
153//
154// CHECK: [[finally]]
155// CHECK: call void @abort()
156// CHECK-NEXT: unreachable
157//
158// CHECK: [[lpad]]
159// CHECK: landingpad
160// CHECK-NEXT: cleanup
161// 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()
171// 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]]
178// 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
192// CHECK: store i8 0, i8* %
193// CHECK-NEXT: br label %[[finally:[^ ]*]]
194//
195// CHECK: [[finally]]
196// CHECK-NEXT: store i32 1, i32* %
197// CHECK-NEXT: store i8 0, i8* %
198// CHECK-NEXT: br label %[[outerfinally:[^ ]*]]
199//
200// CHECK: [[outerfinally]]
201// CHECK-NEXT: br label %[[finallycont:[^ ]*]]
202//
203// CHECK: [[finallycont]]
204// CHECK-NEXT: ret i32 1