[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / CodeGen / exceptions-seh-finally.c
blob6a09a04568f3d651b3251a7a4be0be4fab5ea654
1 // RUN: %clang_cc1 -no-opaque-pointers %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -O1 -disable-llvm-passes -o - | FileCheck %s
2 // RUN: %clang_cc1 -no-opaque-pointers %s -triple i686-pc-win32 -fms-extensions -emit-llvm -O1 -disable-llvm-passes -o - | FileCheck %s
3 // RUN: %clang_cc1 -no-opaque-pointers %s -triple aarch64-windows -fms-extensions -emit-llvm -O1 -disable-llvm-passes -o - | FileCheck %s
4 // NOTE: we're passing "-O1 -disable-llvm-passes" to avoid adding optnone and noinline everywhere.
6 void abort(void) __attribute__((noreturn));
7 void might_crash(void);
8 void cleanup(void);
9 int check_condition(void);
10 void basic_finally(void) {
11 __try {
12 might_crash();
13 } __finally {
14 cleanup();
18 // CHECK-LABEL: define dso_local void @basic_finally()
19 // CHECK: invoke void @might_crash()
20 // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
22 // CHECK: [[invoke_cont]]
23 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
24 // CHECK: call void @"?fin$0@0@basic_finally@@"({{i8 noundef( zeroext)?}} 0, i8* noundef %[[fp]])
25 // CHECK-NEXT: ret void
27 // CHECK: [[lpad]]
28 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
29 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
30 // CHECK: call void @"?fin$0@0@basic_finally@@"({{i8 noundef( zeroext)?}} 1, i8* noundef %[[fp]])
31 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
33 // CHECK: define internal void @"?fin$0@0@basic_finally@@"({{.*}})
34 // CHECK-SAME: [[finally_attrs:#[0-9]+]]
35 // CHECK: call void @cleanup()
37 // Mostly check that we don't double emit 'r' which would crash.
38 void decl_in_finally(void) {
39 __try {
40 might_crash();
41 } __finally {
42 int r;
46 // Ditto, don't crash double emitting 'l'.
47 void label_in_finally(void) {
48 __try {
49 might_crash();
50 } __finally {
52 cleanup();
53 if (check_condition())
54 goto l;
58 // CHECK-LABEL: define dso_local void @label_in_finally()
59 // CHECK: invoke void @might_crash()
60 // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
62 // CHECK: [[invoke_cont]]
63 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
64 // CHECK: call void @"?fin$0@0@label_in_finally@@"({{i8 noundef( zeroext)?}} 0, i8* noundef %[[fp]])
65 // CHECK: ret void
67 // CHECK: define internal void @"?fin$0@0@label_in_finally@@"({{.*}})
68 // CHECK-SAME: [[finally_attrs]]
69 // CHECK: br label %[[l:[^ ]*]]
71 // CHECK: [[l]]
72 // CHECK: call void @cleanup()
73 // CHECK: call i32 @check_condition()
74 // CHECK: br i1 {{.*}}, label
75 // CHECK: br label %[[l]]
77 int crashed;
78 void use_abnormal_termination(void) {
79 __try {
80 might_crash();
81 } __finally {
82 crashed = __abnormal_termination();
86 // CHECK-LABEL: define dso_local void @use_abnormal_termination()
87 // CHECK: invoke void @might_crash()
88 // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
90 // CHECK: [[invoke_cont]]
91 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
92 // CHECK: call void @"?fin$0@0@use_abnormal_termination@@"({{i8 noundef( zeroext)?}} 0, i8* noundef %[[fp]])
93 // CHECK: ret void
95 // CHECK: [[lpad]]
96 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
97 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
98 // CHECK: call void @"?fin$0@0@use_abnormal_termination@@"({{i8 noundef( zeroext)?}} 1, i8* noundef %[[fp]])
99 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
101 // CHECK: define internal void @"?fin$0@0@use_abnormal_termination@@"({{i8 noundef( zeroext)?}} %[[abnormal:abnormal_termination]], i8* noundef %frame_pointer)
102 // CHECK-SAME: [[finally_attrs]]
103 // CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %[[abnormal]] to i32
104 // CHECK: store i32 %[[abnormal_zext]], i32* @crashed
105 // CHECK-NEXT: ret void
107 void noreturn_noop_finally(void) {
108 __try {
109 __noop();
110 } __finally {
111 abort();
115 // CHECK-LABEL: define dso_local void @noreturn_noop_finally()
116 // CHECK: call void @"?fin$0@0@noreturn_noop_finally@@"({{.*}})
117 // CHECK: ret void
119 // CHECK: define internal void @"?fin$0@0@noreturn_noop_finally@@"({{.*}})
120 // CHECK-SAME: [[finally_attrs]]
121 // CHECK: call void @abort()
122 // CHECK: unreachable
124 void noreturn_finally(void) {
125 __try {
126 might_crash();
127 } __finally {
128 abort();
132 // CHECK-LABEL: define dso_local void @noreturn_finally()
133 // CHECK: invoke void @might_crash()
134 // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
136 // CHECK: [[cont]]
137 // CHECK: call void @"?fin$0@0@noreturn_finally@@"({{.*}})
138 // CHECK: ret void
140 // CHECK: [[lpad]]
141 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
142 // CHECK: call void @"?fin$0@0@noreturn_finally@@"({{.*}})
143 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
145 // CHECK: define internal void @"?fin$0@0@noreturn_finally@@"({{.*}})
146 // CHECK-SAME: [[finally_attrs]]
147 // CHECK: call void @abort()
148 // CHECK: unreachable
150 int finally_with_return(void) {
151 __try {
152 return 42;
153 } __finally {
156 // CHECK-LABEL: define dso_local i32 @finally_with_return()
157 // CHECK: call void @"?fin$0@0@finally_with_return@@"({{.*}})
158 // CHECK-NEXT: ret i32 42
160 // CHECK: define internal void @"?fin$0@0@finally_with_return@@"({{.*}})
161 // CHECK-SAME: [[finally_attrs]]
162 // CHECK-NOT: br i1
163 // CHECK-NOT: br label
164 // CHECK: ret void
166 int nested___finally___finally(void) {
167 __try {
168 __try {
169 } __finally {
170 return 1;
172 } __finally {
173 // Intentionally no return here.
175 return 0;
178 // CHECK-LABEL: define dso_local i32 @nested___finally___finally
179 // CHECK: invoke void @"?fin$1@0@nested___finally___finally@@"({{.*}})
180 // CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
182 // CHECK: [[outercont]]
183 // CHECK: call void @"?fin$0@0@nested___finally___finally@@"({{.*}})
184 // CHECK-NEXT: ret i32 0
186 // CHECK: [[lpad]]
187 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
188 // CHECK: call void @"?fin$0@0@nested___finally___finally@@"({{.*}})
189 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
191 // CHECK-LABEL: define internal void @"?fin$0@0@nested___finally___finally@@"({{.*}})
192 // CHECK-SAME: [[finally_attrs]]
193 // CHECK: ret void
195 // CHECK-LABEL: define internal void @"?fin$1@0@nested___finally___finally@@"({{.*}})
196 // CHECK-SAME: [[finally_attrs]]
197 // CHECK: unreachable
199 // FIXME: Our behavior seems suspiciously different.
201 int nested___finally___finally_with_eh_edge(void) {
202 __try {
203 __try {
204 might_crash();
205 } __finally {
206 return 899;
208 } __finally {
209 // Intentionally no return here.
211 return 912;
213 // CHECK-LABEL: define dso_local i32 @nested___finally___finally_with_eh_edge
214 // CHECK: invoke void @might_crash()
215 // CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]]
217 // [[invokecont]]
218 // CHECK: invoke void @"?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
219 // CHECK-NEXT: to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
221 // CHECK: [[outercont]]
222 // CHECK: call void @"?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
223 // CHECK-NEXT: ret i32 912
225 // CHECK: [[lpad1]]
226 // CHECK-NEXT: %[[innerpad:[^ ]*]] = cleanuppad
227 // CHECK: invoke void @"?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
228 // CHECK-NEXT: label %[[innercleanupretbb:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
230 // CHECK: [[innercleanupretbb]]
231 // CHECK-NEXT: cleanupret from %[[innerpad]] unwind label %[[lpad2]]
233 // CHECK: [[lpad2]]
234 // CHECK-NEXT: %[[outerpad:[^ ]*]] = cleanuppad
235 // CHECK: call void @"?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
236 // CHECK-NEXT: cleanupret from %[[outerpad]] unwind to caller
238 // CHECK-LABEL: define internal void @"?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
239 // CHECK-SAME: [[finally_attrs]]
240 // CHECK: ret void
242 // CHECK-LABEL: define internal void @"?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
243 // CHECK-SAME: [[finally_attrs]]
244 // CHECK: unreachable
246 void finally_within_finally(void) {
247 __try {
248 might_crash();
249 } __finally {
250 __try {
251 might_crash();
252 } __finally {
257 // CHECK-LABEL: define dso_local void @finally_within_finally(
258 // CHECK: invoke void @might_crash(
260 // CHECK: call void @"?fin$0@0@finally_within_finally@@"(
261 // CHECK: call void @"?fin$0@0@finally_within_finally@@"({{.*}}) [ "funclet"(
263 // CHECK-LABEL: define internal void @"?fin$0@0@finally_within_finally@@"({{[^)]*}})
264 // CHECK-SAME: [[finally_attrs]]
265 // CHECK: invoke void @might_crash(
267 // CHECK: call void @"?fin$1@0@finally_within_finally@@"(
268 // CHECK: call void @"?fin$1@0@finally_within_finally@@"({{.*}}) [ "funclet"(
270 // CHECK-LABEL: define internal void @"?fin$1@0@finally_within_finally@@"({{[^)]*}})
271 // CHECK-SAME: [[finally_attrs]]
273 void cleanup_with_func(const char *);
274 void finally_with_func(void) {
275 __try {
276 might_crash();
277 } __finally {
278 cleanup_with_func(__func__);
282 // CHECK-LABEL: define internal void @"?fin$0@0@finally_with_func@@"({{[^)]*}})
283 // CHECK: call void @cleanup_with_func(i8* noundef getelementptr inbounds ([18 x i8], [18 x i8]* @"??_C@_0BC@COAGBPGM@finally_with_func?$AA@", i{{32|64}} 0, i{{32|64}} 0))
285 // Look for the absence of noinline. nounwind is expected; any further
286 // attributes should be string attributes.
287 // CHECK: attributes [[finally_attrs]] = { nounwind "{{.*}}" }