• 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: 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.localaddress()
61 // CHECK: call void @"\01?fin$0@0@label_in_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
62 // CHECK: ret void
63 
64 // CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"({{.*}})
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.localaddress()
88 // CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
89 // CHECK: ret void
90 //
91 // CHECK: [[lpad]]
92 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
93 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
94 // CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
95 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
96 
97 // CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} %[[abnormal:abnormal_termination]], i8* %frame_pointer)
98 // CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %[[abnormal]] to i32
99 // CHECK: store i32 %[[abnormal_zext]], i32* @crashed
100 // CHECK-NEXT: ret void
101 
noreturn_noop_finally()102 void noreturn_noop_finally() {
103   __try {
104     __noop();
105   } __finally {
106     abort();
107   }
108 }
109 
110 // CHECK-LABEL: define void @noreturn_noop_finally()
111 // CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
112 // CHECK: ret void
113 
114 // CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}})
115 // CHECK: call void @abort()
116 // CHECK: unreachable
117 
noreturn_finally()118 void noreturn_finally() {
119   __try {
120     might_crash();
121   } __finally {
122     abort();
123   }
124 }
125 
126 // CHECK-LABEL: define void @noreturn_finally()
127 // CHECK: invoke void @might_crash()
128 // CHECK:     to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
129 //
130 // CHECK: [[cont]]
131 // CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
132 // CHECK: ret void
133 //
134 // CHECK: [[lpad]]
135 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
136 // CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
137 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
138 
139 // CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
140 // CHECK: call void @abort()
141 // CHECK: unreachable
142 
finally_with_return()143 int finally_with_return() {
144   __try {
145     return 42;
146   } __finally {
147   }
148 }
149 // CHECK-LABEL: define i32 @finally_with_return()
150 // CHECK: call void @"\01?fin$0@0@finally_with_return@@"({{.*}})
151 // CHECK-NEXT: ret i32 42
152 
153 // CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"({{.*}})
154 // CHECK-NOT: br i1
155 // CHECK-NOT: br label
156 // CHECK: ret void
157 
nested___finally___finally()158 int nested___finally___finally() {
159   __try {
160     __try {
161     } __finally {
162       return 1;
163     }
164   } __finally {
165     // Intentionally no return here.
166   }
167   return 0;
168 }
169 
170 // CHECK-LABEL: define i32 @nested___finally___finally
171 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
172 // CHECK:          to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
173 //
174 // CHECK: [[outercont]]
175 // CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
176 // CHECK-NEXT: ret i32 0
177 //
178 // CHECK: [[lpad]]
179 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
180 // CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
181 // CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
182 
183 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
184 // CHECK: ret void
185 
186 // CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"({{.*}})
187 // CHECK: unreachable
188 
189 // FIXME: Our behavior seems suspiciously different.
190 
nested___finally___finally_with_eh_edge()191 int nested___finally___finally_with_eh_edge() {
192   __try {
193     __try {
194       might_crash();
195     } __finally {
196       return 899;
197     }
198   } __finally {
199     // Intentionally no return here.
200   }
201   return 912;
202 }
203 // CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge
204 // CHECK: invoke void @might_crash()
205 // CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]]
206 //
207 // [[invokecont]]
208 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
209 // CHECK-NEXT:       to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
210 //
211 // CHECK: [[outercont]]
212 // CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
213 // CHECK-NEXT: ret i32 912
214 //
215 // CHECK: [[lpad1]]
216 // CHECK-NEXT: %[[innerpad:[^ ]*]] = cleanuppad
217 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
218 // CHECK-NEXT:    label %[[innercleanupretbb:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
219 //
220 // CHECK: [[innercleanupretbb]]
221 // CHECK-NEXT: cleanupret from %[[innerpad]] unwind label %[[lpad2]]
222 //
223 // CHECK: [[lpad2]]
224 // CHECK-NEXT: %[[outerpad:[^ ]*]] = cleanuppad
225 // CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
226 // CHECK-NEXT: cleanupret from %[[outerpad]] unwind to caller
227 
228 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
229 // CHECK: ret void
230 
231 // CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
232 // CHECK: unreachable
233