• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
2 
3 void abort(void) __attribute__((noreturn));
4 void might_crash(void);
5 void cleanup(void);
6 int check_condition(void);
basic_finally(void)7 void 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()
17 // CHECK:     to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
18 //
19 // CHECK: [[invoke_cont]]
20 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
21 // CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext false, i8* %[[fp]])
22 // CHECK-NEXT: ret void
23 //
24 // CHECK: [[lpad]]
25 // CHECK-NEXT: landingpad
26 // CHECK-NEXT: cleanup
27 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
28 // CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext true, i8* %[[fp]])
29 // CHECK: resume { i8*, i32 }
30 
31 // CHECK: define internal void @"\01?fin$0@0@basic_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
32 // CHECK: call void @cleanup()
33 
34 // Mostly check that we don't double emit 'r' which would crash.
decl_in_finally(void)35 void 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'.
label_in_finally(void)44 void label_in_finally(void) {
45   __try {
46     might_crash();
47   } __finally {
48 l:
49     cleanup();
50     if (check_condition())
51       goto l;
52   }
53 }
54 
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]]
60 // 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)
65 // 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 
73 int crashed;
use_abnormal_termination(void)74 void 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]]
87 // 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
90 //
91 // CHECK: [[lpad]]
92 // CHECK-NEXT: landingpad
93 // CHECK-NEXT: cleanup
94 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
95 // CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext true, i8* %[[fp]])
96 // CHECK: resume { i8*, i32 }
97 
98 // 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 
noreturn_noop_finally()103 void noreturn_noop_finally() {
104   __try {
105     __noop();
106   } __finally {
107     abort();
108   }
109 }
110 
111 // CHECK-LABEL: define void @noreturn_noop_finally()
112 // 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)
117 // CHECK: call void @abort()
118 // CHECK: unreachable
119 
noreturn_finally()120 void 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]]
133 // 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
136 //
137 // CHECK: [[lpad]]
138 // CHECK: landingpad
139 // CHECK-NEXT: cleanup
140 // 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
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: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
156 // CHECK-NEXT: call void @"\01?fin$0@0@finally_with_return@@"(i1 zeroext false, i8* %[[fp]])
157 // CHECK-NEXT: ret i32 42
158 
159 // CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
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: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
178 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]])
179 // CHECK:          to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
180 //
181 // CHECK: [[outercont]]
182 // CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
183 // CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]])
184 // CHECK-NEXT: ret i32 0
185 //
186 // CHECK: [[lpad]]
187 // CHECK-NEXT: landingpad
188 // CHECK-NEXT: cleanup
189 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
190 // CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext true, i8* %[[fp]])
191 
192 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
193 // CHECK: ret void
194 
195 // CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
196 // CHECK: unreachable
197 
nested___finally___finally_with_eh_edge()198 int 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
211 // CHECK: invoke void @might_crash()
212 // CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]]
213 //
214 // [[invokecont]]
215 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
216 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext false, i8* %[[fp]])
217 // CHECK:          to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
218 //
219 // CHECK: [[outercont]]
220 // CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
221 // CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext false, i8* %[[fp]])
222 // CHECK-NEXT: ret i32 912
223 //
224 // CHECK: [[lpad1]]
225 // CHECK-NEXT: landingpad
226 // CHECK-NEXT: cleanup
227 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
228 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext true, i8* %[[fp]])
229 // CHECK:          to label %[[outercont:[^ ]*]] unwind label %[[lpad2]]
230 //
231 // CHECK: [[lpad2]]
232 // CHECK-NEXT: landingpad
233 // CHECK-NEXT: cleanup
234 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
235 // CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext true, i8* %[[fp]])
236 // CHECK: resume
237 
238 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
239 // CHECK: ret void
240 
241 // CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
242 // CHECK: unreachable
243