source: src/ControlStruct/ExceptTranslate.cc @ ff79d5e

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since ff79d5e was b2de2e0, checked in by Andrew Beach <ajbeach@…>, 4 years ago

Improved the check of the catch[Resume] exception declaration.

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