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

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 cc3e4d0 was 35ba584c, checked in by Andrew Beach <ajbeach@…>, 8 years ago

Added rethrow to translation.
Implemend and tested termination rethrowing.

  • Property mode set to 100644
File size: 9.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.
291void reterminate() {
292 {
293 void fn_try1() {
294 void fn_try2() {
295 terminate(1);
296 }
297 void fn_catch2(int index, exception except) {
298 switch (index) {
299 case 1:
300 printf("reterminate 2 caught and "
301 "will rethrow exception 1\n");
302 __rethrow_terminate();
303 break;
304 default:
305 printf("INVALID INDEX in reterminate 2: %d (%d)\n",
306 index, except);
307 }
308 }
309 int fn_match2(exception except) {
310 if (1 == except) {
311 return 1;
312 } else {
313 return 0;
314 }
315 }
316 __try_terminate(fn_try2, fn_catch2, fn_match2);
317 }
318 void fn_catch1(int index, exception except) {
319 switch (index) {
320 case 1:
321 printf("reterminate 1 caught exception 1\n");
322 break;
323 default:
324 printf("INVALID INDEX in reterminate 1: %d (%d)\n",
325 index, except);
326 }
327 }
328 int fn_match1(exception except) {
329 if (1 == except) {
330 return 1;
331 } else {
332 return 0;
333 }
334 }
335 __try_terminate(fn_try1, fn_catch1, fn_match1);
336 }
337}
338
339// Resume Rethrow:
340void reresume() {
341 {
342 bool reresume_handle1(exception except) {
343 if (1 == except) {
344 printf("reresume 1 caught exception 1\n");
345 return true;
346 } else {
347 return false;
348 }
349 }
350 struct __try_resume_node node
351 __attribute__((cleanup(__try_resume_node_delete)));
352 __try_resume_node_new(&node, reresume_handle1);
353 {
354 bool reresume_handle2(exception except) {
355 if (1 == except) {
356 printf("reresume 2 caught and rethrows exception 1\n");
357 return false;
358 } else {
359 return false;
360 }
361 }
362 struct __try_resume_node node
363 __attribute__((cleanup(__try_resume_node_delete)));
364 __try_resume_node_new(&node, reresume_handle2);
365 {
366 resume(1);
367 }
368 }
369 }
370}
371
372// Terminate-Resume interaction:
373void fum() {
374 // terminate block, call resume
375 {
376 void fum_try1() {
377 resume(3);
378 }
379 void fum_catch1(int index, exception except) {
380 switch (index) {
381 case 1:
382 printf("fum caught exception 3\n");
383 break;
384 default:
385 printf("INVALID INDEX in fum: %d (%d)\n", index, except);
386 }
387 }
388 int fum_match1(exception except) {
389 if (3 == except) {
390 return 1;
391 } else {
392 return 0;
393 }
394 }
395 __try_terminate(fum_try1, fum_catch1, fum_match1);
396 }
397}
398
399void foe() {
400 // resume block, call terminate
401 {
402 bool foe_handle1(exception except) {
403 if (3 == except) {
404 printf("foe 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, foe_handle1);
413 {
414 terminate(3);
415 }
416 }
417}
418
419void fy() {
420 // terminate block calls fum, call foe
421 {
422 void fy_try1() {
423 foe();
424 }
425 void fy_catch1(int index, exception except) {
426 switch (index) {
427 case 1:
428 printf("fy caught exception 3\n");
429 fum();
430 break;
431 default:
432 printf("INVALID INDEX in fy: %d (%d)\n", index, except);
433 }
434 }
435 int fy_match1(exception except) {
436 if (3 == except) {
437 return 1;
438 } else {
439 return 0;
440 }
441 }
442 __try_terminate(fy_try1, fy_catch1, fy_match1);
443 }
444}
445
446void fee() {
447 // resume block, call fy
448 {
449 bool fee_handle1(exception except) {
450 if (3 == except) {
451 printf("fee caught exception 3\n");
452 return true;
453 } else {
454 return false;
455 }
456 }
457 struct __try_resume_node node
458 __attribute__((cleanup(__try_resume_node_delete)));
459 __try_resume_node_new(&node, fee_handle1);
460 {
461 fy();
462 }
463 }
464}
465
466
467// main: choose which tests to run
468int main(int argc, char * argv[]) {
469 raii_t a = {"main function"};
470
471 foo(); printf("\n");
472 alpha(); printf("\n");
473 farewell(); printf("\n");
474 fallback(); printf("\n");
475 terminate_swapped(); printf("\n");
476 resume_swapped(); printf("\n");
477 reterminate(); printf("\n");
478 reresume(); printf("\n");
479 fee(); printf("\n");
480 // Uncaught termination test.
481 terminate(7);
482}
Note: See TracBrowser for help on using the repository browser.