• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
2 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
3 
4 void abort(void) __attribute__((noreturn));
5 void might_crash(void);
6 void cleanup(void);
7 int check_condition(void);
basic_finally(void)8 void 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()
18 // CHECK:     to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
19 //
20 // CHECK: [[invoke_cont]]
21 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
22 // CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
23 // CHECK-NEXT: ret void
24 //
25 // CHECK: [[lpad]]
26 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
27 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
28 // CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
29 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
30 
31 // CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{.*}})
32 // CHECK-SAME: [[finally_attrs:#[0-9]+]]
33 // CHECK: call void @cleanup()
34 
35 // Mostly check that we don't double emit 'r' which would crash.
decl_in_finally(void)36 void decl_in_finally(void) {
37   __try {
38     might_crash();
39   } __finally {
40     int r;
41   }
42 }
43 
44 // Ditto, don't crash double emitting 'l'.
label_in_finally(void)45 void label_in_finally(void) {
46   __try {
47     might_crash();
48   } __finally {
49 l:
50     cleanup();
51     if (check_condition())
52       goto l;
53   }
54 }
55 
56 // CHECK-LABEL: define void @label_in_finally()
57 // CHECK: invoke void @might_crash()
58 // CHECK:     to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
59 //
60 // CHECK: [[invoke_cont]]
61 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
62 // CHECK: call void @"\01?fin$0@0@label_in_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
63 // CHECK: ret void
64 
65 // CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"({{.*}})
66 // CHECK-SAME: [[finally_attrs]]
67 // CHECK: br label %[[l:[^ ]*]]
68 //
69 // CHECK: [[l]]
70 // CHECK: call void @cleanup()
71 // CHECK: call i32 @check_condition()
72 // CHECK: br i1 {{.*}}, label
73 // CHECK: br label %[[l]]
74 
75 int crashed;
use_abnormal_termination(void)76 void use_abnormal_termination(void) {
77   __try {
78     might_crash();
79   } __finally {
80     crashed = __abnormal_termination();
81   }
82 }
83 
84 // CHECK-LABEL: define void @use_abnormal_termination()
85 // CHECK: invoke void @might_crash()
86 // CHECK:     to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
87 //
88 // CHECK: [[invoke_cont]]
89 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
90 // CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
91 // CHECK: ret void
92 //
93 // CHECK: [[lpad]]
94 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
95 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
96 // CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
97 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
98 
99 // CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} %[[abnormal:abnormal_termination]], i8* %frame_pointer)
100 // CHECK-SAME: [[finally_attrs]]
101 // CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %[[abnormal]] to i32
102 // CHECK: store i32 %[[abnormal_zext]], i32* @crashed
103 // CHECK-NEXT: ret void
104 
noreturn_noop_finally()105 void noreturn_noop_finally() {
106   __try {
107     __noop();
108   } __finally {
109     abort();
110   }
111 }
112 
113 // CHECK-LABEL: define void @noreturn_noop_finally()
114 // CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
115 // CHECK: ret void
116 
117 // CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
118 // CHECK-SAME: [[finally_attrs]]
119 // CHECK: call void @abort()
120 // CHECK: unreachable
121 
noreturn_finally()122 void noreturn_finally() {
123   __try {
124     might_crash();
125   } __finally {
126     abort();
127   }
128 }
129 
130 // CHECK-LABEL: define void @noreturn_finally()
131 // CHECK: invoke void @might_crash()
132 // CHECK:     to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
133 //
134 // CHECK: [[cont]]
135 // CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
136 // CHECK: ret void
137 //
138 // CHECK: [[lpad]]
139 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
140 // CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
141 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
142 
143 // CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
144 // CHECK-SAME: [[finally_attrs]]
145 // CHECK: call void @abort()
146 // CHECK: unreachable
147 
finally_with_return()148 int finally_with_return() {
149   __try {
150     return 42;
151   } __finally {
152   }
153 }
154 // CHECK-LABEL: define i32 @finally_with_return()
155 // CHECK: call void @"\01?fin$0@0@finally_with_return@@"({{.*}})
156 // CHECK-NEXT: ret i32 42
157 
158 // CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"({{.*}})
159 // CHECK-SAME: [[finally_attrs]]
160 // CHECK-NOT: br i1
161 // CHECK-NOT: br label
162 // CHECK: ret void
163 
nested___finally___finally()164 int 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 }
175 
176 // CHECK-LABEL: define i32 @nested___finally___finally
177 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
178 // CHECK:          to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
179 //
180 // CHECK: [[outercont]]
181 // CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
182 // CHECK-NEXT: ret i32 0
183 //
184 // CHECK: [[lpad]]
185 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
186 // CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
187 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
188 
189 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
190 // CHECK-SAME: [[finally_attrs]]
191 // CHECK: ret void
192 
193 // CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
194 // CHECK-SAME: [[finally_attrs]]
195 // CHECK: unreachable
196 
197 // FIXME: Our behavior seems suspiciously different.
198 
nested___finally___finally_with_eh_edge()199 int nested___finally___finally_with_eh_edge() {
200   __try {
201     __try {
202       might_crash();
203     } __finally {
204       return 899;
205     }
206   } __finally {
207     // Intentionally no return here.
208   }
209   return 912;
210 }
211 // CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge
212 // CHECK: invoke void @might_crash()
213 // CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]]
214 //
215 // [[invokecont]]
216 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
217 // CHECK-NEXT:       to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
218 //
219 // CHECK: [[outercont]]
220 // CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
221 // CHECK-NEXT: ret i32 912
222 //
223 // CHECK: [[lpad1]]
224 // CHECK-NEXT: %[[innerpad:[^ ]*]] = cleanuppad
225 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
226 // CHECK-NEXT:    label %[[innercleanupretbb:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
227 //
228 // CHECK: [[innercleanupretbb]]
229 // CHECK-NEXT: cleanupret from %[[innerpad]] unwind label %[[lpad2]]
230 //
231 // CHECK: [[lpad2]]
232 // CHECK-NEXT: %[[outerpad:[^ ]*]] = cleanuppad
233 // CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
234 // CHECK-NEXT: cleanupret from %[[outerpad]] unwind to caller
235 
236 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
237 // CHECK-SAME: [[finally_attrs]]
238 // CHECK: ret void
239 
240 // CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
241 // CHECK-SAME: [[finally_attrs]]
242 // CHECK: unreachable
243 
finally_within_finally()244 void finally_within_finally() {
245   __try {
246     might_crash();
247   } __finally {
248     __try {
249       might_crash();
250     } __finally {
251     }
252   }
253 }
254 
255 // CHECK-LABEL: define void @finally_within_finally(
256 // CHECK: invoke void @might_crash(
257 
258 // CHECK: call void @"\01?fin$0@0@finally_within_finally@@"(
259 // CHECK: call void @"\01?fin$0@0@finally_within_finally@@"({{.*}}) [ "funclet"(
260 
261 // CHECK-LABEL: define internal void @"\01?fin$0@0@finally_within_finally@@"({{[^)]*}})
262 // CHECK-SAME: [[finally_attrs]]
263 // CHECK: invoke void @might_crash(
264 
265 // CHECK: call void @"\01?fin$1@0@finally_within_finally@@"(
266 // CHECK: call void @"\01?fin$1@0@finally_within_finally@@"({{.*}}) [ "funclet"(
267 
268 // CHECK-LABEL: define internal void @"\01?fin$1@0@finally_within_finally@@"({{[^)]*}})
269 // CHECK-SAME: [[finally_attrs]]
270 
271 // Look for the absence of noinline. Enum attributes come first, so check that
272 // a string attribute is the first to verify that no enum attributes are
273 // present.
274 // CHECK: attributes [[finally_attrs]] = { "{{.*}}" }
275