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

aaron-thesisarm-ehcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since 35ba584c was 35ba584c, checked in by Andrew Beach <ajbeach@…>, 5 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.