source: src/ControlStruct/ExceptTranslate.cc @ b834e98

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 b834e98 was 5da9d6a, checked in by Rob Schluntz <rschlunt@…>, 7 years ago

Merge branch 'master' of plg.uwaterloo.ca:/u/cforall/software/cfa/cfa-cc

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