source: doc/working/exception/impl/test-main.c@ 6e09f211

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since 6e09f211 was 6a48cc9, checked in by Andrew Beach <ajbeach@…>, 8 years ago

More tests for the exception library.

  • Property mode set to 100644
File size: 8.5 KB
Line 
1#include "exception.h"
2
3// Use: gcc -fexceptions -Wall -Werror -g exception.c test-main.c
4
5#include <stdio.h>
6#include <stdbool.h>
7
8// Translation Helpers:
9#define CLEANUP(function) \
10 struct __cleanup_hook __hidden_hook __attribute__((cleanup(function)))
11
12#define SET_UP_RESUME_NODE(handler_function) \
13 struct __try_resume_node node \
14 __attribute__((cleanup(__try_resume_node_delete))); \
15 __try_resume_node_new(&node, handler_function)
16
17void __try_resume_node_new(struct __try_resume_node * node,
18 _Bool (*handler)(exception except)) {
19 node->next = shared_stack.top_resume;
20 shared_stack.top_resume = node;
21 node->try_to_handle = handler;
22}
23
24void __try_resume_node_delete(struct __try_resume_node * node) {
25 shared_stack.top_resume = node->next;
26}
27
28// Local Print On Exit:
29struct raii_base_type {
30 const char * area;
31};
32
33void raii_dtor(struct raii_base_type * this) {
34 printf("Exiting: %s\n", this->area);
35}
36
37#define raii_t __attribute__((cleanup(raii_dtor))) struct raii_base_type
38
39// ===========================================================================
40// Runtime code (post-translation).
41void terminate(int except_value) {
42 raii_t a = {"terminate function"};
43 __throw_terminate(except_value);
44 printf("terminate returned\n");
45}
46
47void resume(int except_value) {
48 raii_t a = {"resume function"};
49 __throw_resume(except_value);
50 printf("resume returned\n");
51}
52
53// Termination Test: Two handlers: no catch, catch
54void bar() {
55 raii_t a = {"bar function"};
56 {
57 void bar_try1() {
58 terminate(4);
59 }
60 void bar_catch1(int index, exception except) {
61 switch(except) {
62 case 1:
63 printf("bar caught exception 3.\n");
64 break;
65 default:
66 printf("INVALID INDEX in bar: %d (%d)\n", index, except);
67 }
68 }
69 int bar_match1(exception except) {
70 if (3 == except) {
71 return 1;
72 } else {
73 return 0;
74 }
75 }
76 __try_terminate(bar_try1, bar_catch1, bar_match1);
77 }
78}
79
80void foo() {
81 raii_t a = {"foo function"};
82 {
83 void foo_try1() {
84 bar();
85 }
86 void foo_catch1(int index, exception except) {
87 switch(index) {
88 case 1:
89 printf("foo caught exception 4.\n");
90 break;
91 case 2:
92 printf("foo caught exception 2.\n");
93 break;
94 default:
95 printf("INVALID INDEX in foo: %d (%d)\n", index, except);
96 }
97 }
98 int foo_match1(exception except) {
99 if (4 == except) {
100 return 1;
101 } else if (2 == except) {
102 return 2;
103 } else {
104 return 0;
105 }
106 }
107 __try_terminate(foo_try1, foo_catch1, foo_match1);
108 }
109}
110
111// Resumption Two Handler Test: no catch, catch.
112void beta() {
113 raii_t a = {"beta function"};
114 {
115 bool beta_handle1(exception except) {
116 if (3 == except) {
117 printf("beta caught exception 3\n");
118 return true;
119 } else {
120 return false;
121 }
122 }
123 struct __try_resume_node node
124 __attribute__((cleanup(__try_resume_node_delete)));
125 __try_resume_node_new(&node, beta_handle1);
126 {
127 resume(4);
128 }
129 }
130}
131void alpha() {
132 raii_t a = {"alpha function"};
133 {
134 bool alpha_handle1(exception except) {
135 if (2 == except) {
136 printf("alpha caught exception 2\n");
137 return true;
138 } else if (4 == except) {
139 printf("alpha caught exception 4\n");
140 return true;
141 } else {
142 return false;
143 }
144 }
145 struct __try_resume_node node
146 __attribute__((cleanup(__try_resume_node_delete)));
147 __try_resume_node_new(&node, alpha_handle1);
148 {
149 beta();
150 }
151 }
152}
153
154// Finally Test:
155void farewell() {
156 {
157 void farewell_finally1() {
158 printf("See you next time\n");
159 }
160 struct __cleanup_hook __hidden_hook
161 __attribute__((cleanup(farewell_finally1)));
162 {
163 printf("walk out of farewell\n");
164 }
165 }
166}
167
168// Resume-to-Terminate Test:
169void fallback() {
170 {
171 void fallback_try1() {
172 resume(1);
173 }
174 void fallback_catch1(int index, exception except) {
175 switch (index) {
176 case 1:
177 printf("fallback caught termination 1\n");
178 break;
179 default:
180 printf("INVALID INDEX in fallback: %d (%d)\n", index, except);
181 }
182 }
183 int fallback_match1(exception except) {
184 if (1 == except) {
185 return 1;
186 } else {
187 return 0;
188 }
189 }
190 __try_terminate(fallback_try1, fallback_catch1, fallback_match1);
191 }
192}
193
194// Terminate Throw New Exception:
195void terminate_swap() {
196 raii_t a = {"terminate_swap"};
197 {
198 void fn_try1() {
199 terminate(2);
200 }
201 void fn_catch1(int index, exception except) {
202 switch (index) {
203 case 1:
204 terminate(1);
205 break;
206 default:
207 printf("INVALID INDEX in terminate_swap: %d (%d)\n",
208 index, except);
209 }
210 }
211 int fn_match1(exception except) {
212 if (2 == except) {
213 return 1;
214 } else {
215 return 0;
216 }
217 }
218 __try_terminate(fn_try1, fn_catch1, fn_match1);
219 }
220}
221
222void terminate_swapped() {
223 raii_t a = {"terminate_swapped"};
224 {
225 void fn_try1() {
226 terminate_swap();
227 }
228 void fn_catch1(int index, exception except) {
229 switch (index) {
230 case 1:
231 printf("terminate_swapped caught exception 1\n");
232 break;
233 default:
234 printf("INVALID INDEX in terminate_swapped: %d (%d)\n",
235 index, except);
236 }
237 }
238 int fn_match1(exception except) {
239 if (1 == except) {
240 return 1;
241 } else {
242 return 0;
243 }
244 }
245 __try_terminate(fn_try1, fn_catch1, fn_match1);
246 }
247}
248
249// Resume Throw New Exception:
250void resume_swap() {
251 raii_t a = {"terminate_swap"};
252 {
253 bool fn_handle1(exception except) {
254 if (2 == except) {
255 resume(1);
256 return true;
257 } else {
258 return false;
259 }
260 }
261 struct __try_resume_node node
262 __attribute__((cleanup(__try_resume_node_delete)));
263 __try_resume_node_new(&node, fn_handle1);
264 {
265 resume(2);
266 }
267 }
268}
269
270void resume_swapped() {
271 {
272 bool fn_handle1(exception except) {
273 if (1 == except) {
274 printf("resume_swapped caught exception 1\n");
275 return true;
276 } else {
277 return false;
278 }
279 }
280 struct __try_resume_node node
281 __attribute__((cleanup(__try_resume_node_delete)));
282 __try_resume_node_new(&node, fn_handle1);
283 {
284 resume_swap();
285 }
286 }
287}
288
289// Terminate Rethrow:
290// I don't have an implementation for this.
291
292// Resume Rethrow:
293void reresume() {
294 {
295 bool reresume_handle1(exception except) {
296 if (1 == except) {
297 printf("reresume 1 caught exception 1\n");
298 return true;
299 } else {
300 return false;
301 }
302 }
303 struct __try_resume_node node
304 __attribute__((cleanup(__try_resume_node_delete)));
305 __try_resume_node_new(&node, reresume_handle1);
306 {
307 bool reresume_handle2(exception except) {
308 if (1 == except) {
309 printf("reresume 2 caught and rethrows exception 1\n");
310 return false;
311 } else {
312 return false;
313 }
314 }
315 struct __try_resume_node node
316 __attribute__((cleanup(__try_resume_node_delete)));
317 __try_resume_node_new(&node, reresume_handle2);
318 {
319 resume(1);
320 }
321 }
322 }
323}
324
325// Terminate-Resume interaction:
326void fum() {
327 // terminate block, call resume
328 {
329 void fum_try1() {
330 resume(3);
331 }
332 void fum_catch1(int index, exception except) {
333 switch (index) {
334 case 1:
335 printf("fum caught exception 3\n");
336 break;
337 default:
338 printf("INVALID INDEX in fum: %d (%d)\n", index, except);
339 }
340 }
341 int fum_match1(exception except) {
342 if (3 == except) {
343 return 1;
344 } else {
345 return 0;
346 }
347 }
348 __try_terminate(fum_try1, fum_catch1, fum_match1);
349 }
350}
351
352void foe() {
353 // resume block, call terminate
354 {
355 bool foe_handle1(exception except) {
356 if (3 == except) {
357 printf("foe caught exception 3\n");
358 return true;
359 } else {
360 return false;
361 }
362 }
363 struct __try_resume_node node
364 __attribute__((cleanup(__try_resume_node_delete)));
365 __try_resume_node_new(&node, foe_handle1);
366 {
367 terminate(3);
368 }
369 }
370}
371
372void fy() {
373 // terminate block calls fum, call foe
374 {
375 void fy_try1() {
376 foe();
377 }
378 void fy_catch1(int index, exception except) {
379 switch (index) {
380 case 1:
381 printf("fy caught exception 3\n");
382 fum();
383 break;
384 default:
385 printf("INVALID INDEX in fy: %d (%d)\n", index, except);
386 }
387 }
388 int fy_match1(exception except) {
389 if (3 == except) {
390 return 1;
391 } else {
392 return 0;
393 }
394 }
395 __try_terminate(fy_try1, fy_catch1, fy_match1);
396 }
397}
398
399void fee() {
400 // resume block, call fy
401 {
402 bool fee_handle1(exception except) {
403 if (3 == except) {
404 printf("fee caught exception 3\n");
405 return true;
406 } else {
407 return false;
408 }
409 }
410 struct __try_resume_node node
411 __attribute__((cleanup(__try_resume_node_delete)));
412 __try_resume_node_new(&node, fee_handle1);
413 {
414 fy();
415 }
416 }
417}
418
419
420// main: choose which tests to run
421int main(int argc, char * argv[]) {
422 raii_t a = {"main function"};
423
424 foo(); printf("\n");
425 alpha(); printf("\n");
426 farewell(); printf("\n");
427 fallback(); printf("\n");
428 terminate_swapped(); printf("\n");
429 resume_swapped(); printf("\n");
430 reresume(); printf("\n");
431 fee(); printf("\n");
432 // Uncaught termination test.
433 terminate(7);
434}
Note: See TracBrowser for help on using the repository browser.