source: src/ControlStruct/ExceptTranslate.cc @ 61e2761

aaron-thesisarm-ehcleanup-dtorsdeferred_resndemanglerjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerresolv-newwith_gc
Last change on this file since 61e2761 was 03eedd5, checked in by Andrew Beach <ajbeach@…>, 4 years ago

Just a little bit of cleanup in the time I have left.

  • Property mode set to 100644
File size: 20.6 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// ExceptVisitor.cc --
8//
9// Author           : Andrew Beach
10// Created On       : Wed Jun 14 16:49:00 2017
11// Last Modified By : Andrew Beach
12// Last Modified On : Fri Jul 28 15:34:00 2017
13// Update Count     : 6
14//
15
16#include "ExceptTranslate.h"
17#include "Common/PassVisitor.h"
18#include "SynTree/Statement.h"
19#include "SynTree/Declaration.h"
20#include "SynTree/Expression.h"
21#include "SynTree/Type.h"
22#include "SynTree/Attribute.h"
23#include "SynTree/VarExprReplacer.h"
24
25namespace ControlStruct {
26
27        // void (*function)();
28        static FunctionType try_func_t(noQualifiers, false);
29        // void (*function)(int, exception);
30        static FunctionType catch_func_t(noQualifiers, false);
31        // int (*function)(exception);
32        static FunctionType match_func_t(noQualifiers, false);
33        // bool (*function)(exception);
34        static FunctionType handle_func_t(noQualifiers, false);
35        // void (*function)(__attribute__((unused)) void *);
36        static FunctionType finally_func_t(noQualifiers, false);
37
38        static void init_func_types() {
39                static bool init_complete = false;
40                if (init_complete) {
41                        return;
42                }
43                ObjectDecl index_obj(
44                        "__handler_index",
45                        Type::StorageClasses(),
46                        LinkageSpec::Cforall,
47                        /*bitfieldWidth*/ NULL,
48                        new BasicType( noQualifiers, BasicType::SignedInt ),
49                        /*init*/ NULL
50                        );
51                ObjectDecl exception_obj(
52                        "__exception_inst",
53                        Type::StorageClasses(),
54                        LinkageSpec::Cforall,
55                        /*bitfieldWidth*/ NULL,
56                        new PointerType(
57                                noQualifiers,
58                                new BasicType( noQualifiers, BasicType::SignedInt )
59                                ),
60                        /*init*/ NULL
61                        );
62                ObjectDecl bool_obj(
63                        "__ret_bool",
64                        Type::StorageClasses(),
65                        LinkageSpec::Cforall,
66                        /*bitfieldWidth*/ NULL,
67                        new BasicType(noQualifiers, BasicType::Bool),
68                        /*init*/ NULL
69                        );
70                ObjectDecl voidptr_obj(
71                        "__hook",
72                        Type::StorageClasses(),
73                        LinkageSpec::Cforall,
74                        NULL,
75                        new PointerType(
76                                noQualifiers,
77                                new VoidType(
78                                        noQualifiers
79                                        ),
80                                std::list<Attribute *>{new Attribute("unused")}
81                                ),
82                        NULL
83                        );
84
85                catch_func_t.get_parameters().push_back( index_obj.clone() );
86                catch_func_t.get_parameters().push_back( exception_obj.clone() );
87                match_func_t.get_returnVals().push_back( index_obj.clone() );
88                match_func_t.get_parameters().push_back( exception_obj.clone() );
89                handle_func_t.get_returnVals().push_back( bool_obj.clone() );
90                handle_func_t.get_parameters().push_back( exception_obj.clone() );
91                finally_func_t.get_parameters().push_back( voidptr_obj.clone() );
92
93                init_complete = true;
94        }
95
96        // Buricratic Helpers (Not having to do with the paritular operation.)
97
98        typedef std::list<CatchStmt*> CatchList;
99
100        void split( CatchList& allHandlers, CatchList& terHandlers,
101                                CatchList& resHandlers ) {
102                while ( !allHandlers.empty() ) {
103                        CatchStmt * stmt = allHandlers.front();
104                        allHandlers.pop_front();
105                        if (CatchStmt::Terminate == stmt->get_kind()) {
106                                terHandlers.push_back(stmt);
107                        } else {
108                                resHandlers.push_back(stmt);
109                        }
110                }
111        }
112
113        void appendDeclStmt( CompoundStmt * block, Declaration * item ) {
114                block->push_back(new DeclStmt(noLabels, item));
115        }
116
117        Expression * nameOf( DeclarationWithType * decl ) {
118                return new VariableExpr( decl );
119        }
120
121        // ThrowStmt Mutation Helpers
122
123        Statement * create_given_throw(
124                        const char * throwFunc, ThrowStmt * throwStmt ) {
125                // There is an extra copy here we might be able to remove with
126                // references.
127                // { int NAME = EXPR; throwFunc( &NAME ); }
128                CompoundStmt * result = new CompoundStmt( noLabels );
129                ObjectDecl * local = new ObjectDecl(
130                        "__local_exception_copy",
131                        Type::StorageClasses(),
132                        LinkageSpec::Cforall,
133                        NULL,
134                        new BasicType( noQualifiers, BasicType::SignedInt ),
135                        new SingleInit( throwStmt->get_expr() )
136                        );
137                appendDeclStmt( result, local );
138                UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) );
139                call->get_args().push_back( new AddressExpr( nameOf( local ) ) );
140                result->push_back( new ExprStmt( throwStmt->get_labels(), call ) );
141                throwStmt->set_expr( nullptr );
142                delete throwStmt;
143                return result;
144        }
145
146        Statement * create_terminate_throw( ThrowStmt *throwStmt ) {
147                // { int NAME = EXPR; __throw_terminate( &NAME ); }
148                return create_given_throw( "__cfaehm__throw_terminate", throwStmt );
149        }
150
151        Statement * create_terminate_rethrow( ThrowStmt *throwStmt,
152                        ObjectDecl *handler_except_decl ) {
153                // { `handler_except_decl` = NULL; __rethrow_terminate(); }
154                assert( nullptr == throwStmt->get_expr() );
155                assert( handler_except_decl );
156
157                CompoundStmt * result = new CompoundStmt( throwStmt->get_labels() );
158                result->push_back( new ExprStmt( noLabels, UntypedExpr::createAssign(
159                        nameOf( handler_except_decl ),
160                        new ConstantExpr( Constant::null(
161                                new PointerType(
162                                        noQualifiers,
163                                        handler_except_decl->get_type()->clone()
164                                        )
165                                ) )
166                        ) ) );
167                result->push_back( new ExprStmt(
168                        noLabels,
169                        new UntypedExpr( new NameExpr( "__cfaehm__rethrow_terminate" ) )
170                        ) );
171                delete throwStmt;
172                return result;
173        }
174
175        Statement * create_resume_throw( ThrowStmt *throwStmt ) {
176                // __throw_resume( EXPR );
177                return create_given_throw( "__cfaehm__throw_resume", throwStmt );
178        }
179
180        Statement * create_resume_rethrow( ThrowStmt *throwStmt ) {
181                // return false;
182                Statement * result = new ReturnStmt(
183                        throwStmt->get_labels(),
184                        new ConstantExpr( Constant::from_bool( false ) )
185                        );
186                delete throwStmt;
187                return result;
188        }
189
190        // TryStmt Mutation Helpers
191
192        CompoundStmt * take_try_block( TryStmt *tryStmt ) {
193                CompoundStmt * block = tryStmt->get_block();
194                tryStmt->set_block( nullptr );
195                return block;
196        }
197        FunctionDecl * create_try_wrapper( CompoundStmt *body ) {
198
199                return new FunctionDecl( "try", Type::StorageClasses(),
200                        LinkageSpec::Cforall, try_func_t.clone(), body );
201        }
202
203        FunctionDecl * create_terminate_catch( CatchList &handlers ) {
204                std::list<CaseStmt *> handler_wrappers;
205
206                FunctionType *func_type = catch_func_t.clone();
207                DeclarationWithType * index_obj = func_type->get_parameters().front();
208                DeclarationWithType * except_obj = func_type->get_parameters().back();
209
210                // Index 1..{number of handlers}
211                int index = 0;
212                CatchList::iterator it = handlers.begin();
213                for ( ; it != handlers.end() ; ++it ) {
214                        ++index;
215                        CatchStmt * handler = *it;
216
217                        // INTEGERconstant Version
218                        // case `index`:
219                        // {
220                        //     `handler.decl` {inserted} = { except_obj };
221                        //     `handler.body`
222                        // }
223                        // return;
224                        CompoundStmt * block = new CompoundStmt( noLabels );
225
226                        // Just copy the exception value. (Post Validation)
227                        ObjectDecl * handler_decl =
228                                static_cast<ObjectDecl *>( handler->get_decl() );
229                        ObjectDecl * local_except = handler_decl->clone();
230                        local_except->set_init(
231                                new ListInit({ new SingleInit( nameOf( except_obj ) ) }) );
232#if 0
233                        // Virtual Exception Vision
234                        // case `index`:
235                        // {
236                        //     `handler.decl` = { (virtual `decl.type`)`except` };
237                        //     `handler.body`;
238                        // }
239                        // return;
240
241                        // Save a cast copy of the exception (should always succeed).
242                        local_except->set_init(
243                                new ListInit({ new SingleInit(
244                                        new VirtualCastExpr( nameOf( except_obj ),
245                                                local_except->get_type()
246                                                )
247                                        ) })
248                                );
249#endif
250                        block->push_back( new DeclStmt( noLabels, local_except ) );
251
252                        // Add the cleanup attribute.
253                        local_except->get_attributes().push_back( new Attribute(
254                                "cleanup",
255                                { new NameExpr( "__cfaehm__cleanup_terminate" ) }
256                                ) );
257
258                        // Update variables in the body to point to this local copy.
259                        {
260                                VarExprReplacer::DeclMap mapping;
261                                mapping[ handler_decl ] = local_except;
262                                VarExprReplacer mapper( mapping );
263                                handler->get_body()->accept( mapper );
264                        }
265
266                        block->push_back( handler->get_body() );
267                        handler->set_body( nullptr );
268
269                        std::list<Statement *> caseBody
270                                        { block, new ReturnStmt( noLabels, nullptr ) };
271                        handler_wrappers.push_back( new CaseStmt(
272                                noLabels,
273                                new ConstantExpr( Constant::from_int( index ) ),
274                                caseBody
275                                ) );
276                }
277                // TODO: Some sort of meaningful error on default perhaps?
278
279                std::list<Statement*> stmt_handlers;
280                while ( !handler_wrappers.empty() ) {
281                        stmt_handlers.push_back( handler_wrappers.front() );
282                        handler_wrappers.pop_front();
283                }
284
285                SwitchStmt * handler_lookup = new SwitchStmt(
286                        noLabels,
287                        nameOf( index_obj ),
288                        stmt_handlers
289                        );
290                CompoundStmt * body = new CompoundStmt( noLabels );
291                body->push_back( handler_lookup );
292
293                return new FunctionDecl("catch", Type::StorageClasses(),
294                        LinkageSpec::Cforall, func_type, body);
295        }
296
297        // Create a single check from a moddified handler.
298        // except_obj is referenced, modded_handler will be freed.
299        CompoundStmt *create_single_matcher(
300                        DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
301                CompoundStmt * block = new CompoundStmt( noLabels );
302
303                ObjectDecl * local_except =
304                        dynamic_cast<ObjectDecl *>( modded_handler->get_decl() );
305                assert( local_except );
306                block->push_back( new DeclStmt( noLabels, local_except ) );
307#if 0
308                // Virtual Exception Version
309                // {
310                //     `modded_handler.decl`
311                //     if ( `decl.name = (virtual)`except`
312                //             [&& `modded_handler.cond`] ) {
313                //         `modded_handler.body`
314                //     }
315                // }
316
317                // Check for type match.
318                Expression * cond = UntypedExpr::createAssign( nameOf( local_except ),
319                        new VirtualCastExpr( nameOf( except_obj ),
320                                local_except->get_type()->clone() ) );
321#endif
322
323                // INTEGERconstant Version
324                // {
325                //     `modded_handler.decl` = *`except`
326                //     if ( `decl.name` == `modded_handler.cond` ) {
327                //         `modded_handler.body`
328                //     }
329                // }
330                ConstantExpr * number =
331                        dynamic_cast<ConstantExpr*>( modded_handler->get_cond() );
332                assert( number );
333                modded_handler->set_cond( nullptr );
334
335                Expression * cond;
336                {
337                        std::list<Expression *> args;
338                        args.push_back( number );
339
340                        std::list<Expression *> rhs_args;
341                        rhs_args.push_back( nameOf( except_obj ) );
342                        Expression * rhs = new UntypedExpr(
343                                new NameExpr( "*?" ), rhs_args );
344                        args.push_back( rhs );
345
346                        cond = new UntypedExpr( new NameExpr( "?==?" /*???*/), args );
347                }
348
349                // Add the check on the conditional if it is provided.
350                if ( modded_handler->get_cond() ) {
351                        cond = new LogicalExpr( cond, modded_handler->get_cond() );
352                }
353                // Construct the match condition.
354                block->push_back( new IfStmt( noLabels,
355                        cond, modded_handler->get_body(), nullptr ) );
356
357                modded_handler->set_decl( nullptr );
358                modded_handler->set_cond( nullptr );
359                modded_handler->set_body( nullptr );
360                delete modded_handler;
361                return block;
362        }
363
364        FunctionDecl * create_terminate_match( CatchList &handlers ) {
365                // int match(exception * except) {
366                //     HANDLER WRAPPERS { return `index`; }
367                // }
368
369                CompoundStmt * body = new CompoundStmt( noLabels );
370
371                FunctionType * func_type = match_func_t.clone();
372                DeclarationWithType * except_obj = func_type->get_parameters().back();
373
374                // Index 1..{number of handlers}
375                int index = 0;
376                CatchList::iterator it;
377                for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
378                        ++index;
379                        CatchStmt * handler = *it;
380
381                        // Body should have been taken by create_terminate_catch.
382                        assert( nullptr == handler->get_body() );
383
384                        // Create new body.
385                        handler->set_body( new ReturnStmt( noLabels,
386                                new ConstantExpr( Constant::from_int( index ) ) ) );
387
388                        // Create the handler.
389                        body->push_back( create_single_matcher( except_obj, handler ) );
390                        *it = nullptr;
391                }
392
393                body->push_back( new ReturnStmt( noLabels, new ConstantExpr(
394                        Constant::from_int( 0 ) ) ) );
395
396                return new FunctionDecl("match", Type::StorageClasses(),
397                        LinkageSpec::Cforall, func_type, body);
398        }
399
400        CompoundStmt * create_terminate_caller(
401                        FunctionDecl * try_wrapper,
402                        FunctionDecl * terminate_catch,
403                        FunctionDecl * terminate_match) {
404                // { __cfaehm__try_terminate(`try`, `catch`, `match`); }
405
406                UntypedExpr * caller = new UntypedExpr( new NameExpr(
407                        "__cfaehm__try_terminate" ) );
408                std::list<Expression *>& args = caller->get_args();
409                args.push_back( nameOf( try_wrapper ) );
410                args.push_back( nameOf( terminate_catch ) );
411                args.push_back( nameOf( terminate_match ) );
412
413                CompoundStmt * callStmt = new CompoundStmt( noLabels );
414                callStmt->push_back( new ExprStmt( noLabels, caller ) );
415                return callStmt;
416        }
417
418        FunctionDecl * create_resume_handler( CatchList &handlers ) {
419                // bool handle(exception * except) {
420                //     HANDLER WRAPPERS { `hander->body`; return true; }
421                // }
422                CompoundStmt * body = new CompoundStmt( noLabels );
423
424                FunctionType * func_type = match_func_t.clone();
425                DeclarationWithType * except_obj = func_type->get_parameters().back();
426
427                CatchList::iterator it;
428                for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
429                        CatchStmt * handler = *it;
430
431                        // Modifiy body.
432                        CompoundStmt * handling_code =
433                                dynamic_cast<CompoundStmt*>( handler->get_body() );
434                        if ( ! handling_code ) {
435                                handling_code = new CompoundStmt( noLabels );
436                                handling_code->push_back( handler->get_body() );
437                        }
438                        handling_code->push_back( new ReturnStmt( noLabels,
439                                new ConstantExpr( Constant::from_bool( true ) ) ) );
440                        handler->set_body( handling_code );
441
442                        // Create the handler.
443                        body->push_back( create_single_matcher( except_obj, handler ) );
444                        *it = nullptr;
445                }
446
447                body->push_back( new ReturnStmt( noLabels, new ConstantExpr(
448                        Constant::from_bool( false ) ) ) );
449
450                return new FunctionDecl("handle", Type::StorageClasses(),
451                        LinkageSpec::Cforall, func_type, body);
452        }
453
454        CompoundStmt * create_resume_wrapper(
455                        StructDecl * node_decl,
456                        Statement * wraps,
457                        FunctionDecl * resume_handler ) {
458                CompoundStmt * body = new CompoundStmt( noLabels );
459
460                // struct __try_resume_node __resume_node
461                //      __attribute__((cleanup( __cfaehm__try_resume_cleanup )));
462                // ** unwinding of the stack here could cause problems **
463                // ** however I don't think that can happen currently **
464                // __cfaehm__try_resume_setup( &__resume_node, resume_handler );
465
466                std::list< Attribute * > attributes;
467                {
468                        std::list< Expression * > attr_params;
469                        attr_params.push_back( new NameExpr(
470                                "__cfaehm__try_resume_cleanup" ) );
471                        attributes.push_back( new Attribute( "cleanup", attr_params ) );
472                }
473
474                ObjectDecl * obj = new ObjectDecl(
475                        "__resume_node",
476                        Type::StorageClasses(),
477                        LinkageSpec::Cforall,
478                        nullptr,
479                        new StructInstType(
480                                Type::Qualifiers(),
481                                node_decl
482                                ),
483                        nullptr,
484                        attributes
485                        );
486                appendDeclStmt( body, obj );
487
488                UntypedExpr *setup = new UntypedExpr( new NameExpr(
489                        "__cfaehm__try_resume_setup" ) );
490                setup->get_args().push_back( new AddressExpr( nameOf( obj ) ) );
491                setup->get_args().push_back( nameOf( resume_handler ) );
492
493                body->push_back( new ExprStmt( noLabels, setup ) );
494
495                body->push_back( wraps );
496                return body;
497        }
498
499        FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ) {
500                // void finally() { <finally code> }
501                FinallyStmt * finally = tryStmt->get_finally();
502                CompoundStmt * body = finally->get_block();
503                finally->set_block( nullptr );
504                delete finally;
505                tryStmt->set_finally( nullptr );
506
507                return new FunctionDecl("finally", Type::StorageClasses(),
508                        LinkageSpec::Cforall, finally_func_t.clone(), body);
509        }
510
511        ObjectDecl * create_finally_hook(
512                        StructDecl * hook_decl, FunctionDecl * finally_wrapper ) {
513                // struct __cfaehm__cleanup_hook __finally_hook
514                //      __attribute__((cleanup( finally_wrapper )));
515
516                // Make Cleanup Attribute.
517                std::list< Attribute * > attributes;
518                {
519                        std::list< Expression * > attr_params;
520                        attr_params.push_back( nameOf( finally_wrapper ) );
521                        attributes.push_back( new Attribute( "cleanup", attr_params ) );
522                }
523
524                return new ObjectDecl(
525                        "__finally_hook",
526                        Type::StorageClasses(),
527                        LinkageSpec::Cforall,
528                        nullptr,
529                        new StructInstType(
530                                noQualifiers,
531                                hook_decl
532                                ),
533                        nullptr,
534                        attributes
535                        );
536        }
537
538
539        class ExceptionMutatorCore : public WithGuards {
540                enum Context { NoHandler, TerHandler, ResHandler };
541
542                // Also need to handle goto, break & continue.
543                // They need to be cut off in a ResHandler, until we enter another
544                // loop, switch or the goto stays within the function.
545
546                Context cur_context;
547
548                // The current (innermost) termination handler exception declaration.
549                ObjectDecl * handler_except_decl;
550
551                // We might not need this, but a unique base for each try block's
552                // generated functions might be nice.
553                //std::string curFunctionName;
554                //unsigned int try_count = 0;
555
556                StructDecl *node_decl;
557                StructDecl *hook_decl;
558
559        public:
560                ExceptionMutatorCore() :
561                        cur_context(NoHandler),
562                        handler_except_decl( nullptr ),
563                        node_decl( nullptr ), hook_decl( nullptr )
564                {}
565
566                void premutate( CatchStmt *catchStmt );
567                void premutate( StructDecl *structDecl );
568                Statement * postmutate( ThrowStmt *throwStmt );
569                Statement * postmutate( TryStmt *tryStmt );
570        };
571
572        void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
573                // Currently, we make up the declaration, as there isn't one for
574                // integers.
575                ObjectDecl * tmp = new ObjectDecl(
576                        "_hidden_local",
577                        Type::StorageClasses(),
578                        LinkageSpec::Cforall,
579                        nullptr,
580                        new PointerType(
581                                noQualifiers,
582                                new BasicType( noQualifiers, BasicType::SignedInt )
583                                ),
584                        nullptr
585                        );
586                catchStmt->set_decl( tmp );
587
588                // Validate the Statement's form.
589                ObjectDecl * decl =
590                        dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
591                if ( decl && true /* check decl->get_type() */ ) {
592                        // Pass.
593                } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
594                        throw SemanticError("catch must have exception type");
595                } else {
596                        throw SemanticError("catchResume must have exception type");
597                }
598
599                // Track the handler context.
600                GuardValue( cur_context );
601                if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
602                        cur_context = TerHandler;
603
604                        GuardValue( handler_except_decl );
605                        handler_except_decl = decl;
606                } else {
607                        cur_context = ResHandler;
608                }
609        }
610
611        void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
612                if ( !structDecl->has_body() ) {
613                        // Skip children?
614                        return;
615                } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) {
616                        assert( nullptr == node_decl );
617                        node_decl = structDecl;
618                } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) {
619                        assert( nullptr == hook_decl );
620                        hook_decl = structDecl;
621                }
622                // Later we might get the exception type as well.
623        }
624
625        Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) {
626                // Ignoring throwStmt->get_target() for now.
627                if ( ThrowStmt::Terminate == throwStmt->get_kind() ) {
628                        if ( throwStmt->get_expr() ) {
629                                return create_terminate_throw( throwStmt );
630                        } else if ( TerHandler == cur_context ) {
631                                return create_terminate_rethrow(
632                                        throwStmt, handler_except_decl );
633                        } else {
634                                assertf(false, "Invalid throw in %s at %i\n",
635                                        throwStmt->location.filename.c_str(),
636                                        throwStmt->location.linenumber);
637                                return nullptr;
638                        }
639                } else {
640                        if ( throwStmt->get_expr() ) {
641                                return create_resume_throw( throwStmt );
642                        } else if ( ResHandler == cur_context ) {
643                                return create_resume_rethrow( throwStmt );
644                        } else {
645                                assertf(false, "Invalid throwResume in %s at %i\n",
646                                        throwStmt->location.filename.c_str(),
647                                        throwStmt->location.linenumber);
648                                return nullptr;
649                        }
650                }
651        }
652
653        Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) {
654                assert( node_decl );
655                assert( hook_decl );
656
657                // Generate a prefix for the function names?
658
659                CompoundStmt * block = new CompoundStmt( noLabels );
660                CompoundStmt * inner = take_try_block( tryStmt );
661
662                if ( tryStmt->get_finally() ) {
663                        // Define the helper function.
664                        FunctionDecl * finally_block =
665                                create_finally_wrapper( tryStmt );
666                        appendDeclStmt( block, finally_block );
667                        // Create and add the finally cleanup hook.
668                        appendDeclStmt( block,
669                                create_finally_hook( hook_decl, finally_block ) );
670                }
671
672                CatchList termination_handlers;
673                CatchList resumption_handlers;
674                split( tryStmt->get_catchers(),
675                           termination_handlers, resumption_handlers );
676
677                if ( resumption_handlers.size() ) {
678                        // Define the helper function.
679                        FunctionDecl * resume_handler =
680                                create_resume_handler( resumption_handlers );
681                        appendDeclStmt( block, resume_handler );
682                        // Prepare hooks
683                        inner = create_resume_wrapper( node_decl, inner, resume_handler );
684                }
685
686                if ( termination_handlers.size() ) {
687                        // Define the three helper functions.
688                        FunctionDecl * try_wrapper = create_try_wrapper( inner );
689                        appendDeclStmt( block, try_wrapper );
690                        FunctionDecl * terminate_catch =
691                                create_terminate_catch( termination_handlers );
692                        appendDeclStmt( block, terminate_catch );
693                        FunctionDecl * terminate_match =
694                                create_terminate_match( termination_handlers );
695                        appendDeclStmt( block, terminate_match );
696                        // Build the call to the try wrapper.
697                        inner = create_terminate_caller(
698                                try_wrapper, terminate_catch, terminate_match );
699                }
700
701                // Embed the try block.
702                block->push_back( inner );
703
704                return block;
705        }
706
707        void translateEHM( std::list< Declaration *> & translationUnit ) {
708                init_func_types();
709
710                PassVisitor<ExceptionMutatorCore> translator;
711                mutateAll( translationUnit, translator );
712        }
713}
Note: See TracBrowser for help on using the repository browser.