source: src/ControlStruct/ExceptTranslate.cc @ d180746

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since d180746 was d180746, checked in by Thierry Delisle <tdelisle@…>, 7 years ago

Big header cleaning pass - commit 2

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