source: src/ControlStruct/ExceptTranslate.cc @ e9145a3

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

Updated exception tests to exception structures. Should be re-orginized still.

  • Property mode set to 100644
File size: 22.1 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 15:48:00 2017
13// Update Count     : 8
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        // TODO: Stoping the function from generating the 'return variable'
390        // entirely would be cleaner. But this does get ride of warnings.
391        CompoundStmt * set_and_ret(DeclarationWithType * var, Expression * val) {
392                CompoundStmt * block = new CompoundStmt( noLabels );
393                block->push_back( new ExprStmt( noLabels,
394                        UntypedExpr::createAssign( new VariableExpr( var ), val )
395                        ) );
396                block->push_back( new ReturnStmt( noLabels,
397                        new VariableExpr( var )
398                        ) );
399                return block;
400        }
401
402        FunctionDecl * ExceptionMutatorCore::create_terminate_match(
403                        CatchList &handlers ) {
404                // int match(exception * except) {
405                //     HANDLER WRAPPERS { return `index`; }
406                // }
407
408                CompoundStmt * body = new CompoundStmt( noLabels );
409
410                FunctionType * func_type = match_func_t.clone();
411                DeclarationWithType * except_obj = func_type->get_parameters().back();
412                DeclarationWithType * index_obj = func_type->get_returnVals().front();
413
414                // Index 1..{number of handlers}
415                int index = 0;
416                CatchList::iterator it;
417                for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
418                        ++index;
419                        CatchStmt * handler = *it;
420
421                        // Body should have been taken by create_terminate_catch.
422                        assert( nullptr == handler->get_body() );
423
424                        // Create new body.
425                        handler->set_body( set_and_ret( index_obj,
426                                new ConstantExpr( Constant::from_int( index ) ) ) );
427
428                        // Create the handler.
429                        body->push_back( create_single_matcher( except_obj, handler ) );
430                        *it = nullptr;
431                }
432
433                body->push_back( set_and_ret( index_obj,
434                        new ConstantExpr( Constant::from_int( 0 ) ) ) );
435
436                return new FunctionDecl("match", Type::StorageClasses(),
437                        LinkageSpec::Cforall, func_type, body);
438        }
439
440        CompoundStmt * ExceptionMutatorCore::create_terminate_caller(
441                        FunctionDecl * try_wrapper,
442                        FunctionDecl * terminate_catch,
443                        FunctionDecl * terminate_match ) {
444                // { __cfaehm__try_terminate(`try`, `catch`, `match`); }
445
446                UntypedExpr * caller = new UntypedExpr( new NameExpr(
447                        "__cfaehm__try_terminate" ) );
448                std::list<Expression *>& args = caller->get_args();
449                args.push_back( nameOf( try_wrapper ) );
450                args.push_back( nameOf( terminate_catch ) );
451                args.push_back( nameOf( terminate_match ) );
452
453                CompoundStmt * callStmt = new CompoundStmt( noLabels );
454                callStmt->push_back( new ExprStmt( noLabels, caller ) );
455                return callStmt;
456        }
457
458        FunctionDecl * ExceptionMutatorCore::create_resume_handler(
459                        CatchList &handlers ) {
460                // bool handle(exception * except) {
461                //     HANDLER WRAPPERS { `hander->body`; return true; }
462                // }
463                CompoundStmt * body = new CompoundStmt( noLabels );
464
465                FunctionType * func_type = handle_func_t.clone();
466                DeclarationWithType * except_obj = func_type->get_parameters().back();
467                DeclarationWithType * bool_obj = func_type->get_returnVals().front();
468
469                CatchList::iterator it;
470                for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
471                        CatchStmt * handler = *it;
472
473                        // Modifiy body.
474                        CompoundStmt * handling_code =
475                                dynamic_cast<CompoundStmt*>( handler->get_body() );
476                        if ( ! handling_code ) {
477                                handling_code = new CompoundStmt( noLabels );
478                                handling_code->push_back( handler->get_body() );
479                        }
480                        handling_code->push_back( set_and_ret( bool_obj,
481                                new ConstantExpr( Constant::from_bool( true ) ) ) );
482                        handler->set_body( handling_code );
483
484                        // Create the handler.
485                        body->push_back( create_single_matcher( except_obj, handler ) );
486                        *it = nullptr;
487                }
488
489                body->push_back( set_and_ret( bool_obj,
490                        new ConstantExpr( Constant::from_bool( false ) ) ) );
491
492                return new FunctionDecl("handle", Type::StorageClasses(),
493                        LinkageSpec::Cforall, func_type, body);
494        }
495
496        CompoundStmt * ExceptionMutatorCore::create_resume_wrapper(
497                        Statement * wraps,
498                        FunctionDecl * resume_handler ) {
499                CompoundStmt * body = new CompoundStmt( noLabels );
500
501                // struct __try_resume_node __resume_node
502                //      __attribute__((cleanup( __cfaehm__try_resume_cleanup )));
503                // ** unwinding of the stack here could cause problems **
504                // ** however I don't think that can happen currently **
505                // __cfaehm__try_resume_setup( &__resume_node, resume_handler );
506
507                std::list< Attribute * > attributes;
508                {
509                        std::list< Expression * > attr_params;
510                        attr_params.push_back( new NameExpr(
511                                "__cfaehm__try_resume_cleanup" ) );
512                        attributes.push_back( new Attribute( "cleanup", attr_params ) );
513                }
514
515                ObjectDecl * obj = new ObjectDecl(
516                        "__resume_node",
517                        Type::StorageClasses(),
518                        LinkageSpec::Cforall,
519                        nullptr,
520                        new StructInstType(
521                                Type::Qualifiers(),
522                                node_decl
523                                ),
524                        nullptr,
525                        attributes
526                        );
527                appendDeclStmt( body, obj );
528
529                UntypedExpr *setup = new UntypedExpr( new NameExpr(
530                        "__cfaehm__try_resume_setup" ) );
531                setup->get_args().push_back( new AddressExpr( nameOf( obj ) ) );
532                setup->get_args().push_back( nameOf( resume_handler ) );
533
534                body->push_back( new ExprStmt( noLabels, setup ) );
535
536                body->push_back( wraps );
537                return body;
538        }
539
540        FunctionDecl * ExceptionMutatorCore::create_finally_wrapper(
541                        TryStmt * tryStmt ) {
542                // void finally() { <finally code> }
543                FinallyStmt * finally = tryStmt->get_finally();
544                CompoundStmt * body = finally->get_block();
545                finally->set_block( nullptr );
546                delete finally;
547                tryStmt->set_finally( nullptr );
548
549                return new FunctionDecl("finally", Type::StorageClasses(),
550                        LinkageSpec::Cforall, finally_func_t.clone(), body);
551        }
552
553        ObjectDecl * ExceptionMutatorCore::create_finally_hook(
554                        FunctionDecl * finally_wrapper ) {
555                // struct __cfaehm__cleanup_hook __finally_hook
556                //      __attribute__((cleanup( finally_wrapper )));
557
558                // Make Cleanup Attribute.
559                std::list< Attribute * > attributes;
560                {
561                        std::list< Expression * > attr_params;
562                        attr_params.push_back( nameOf( finally_wrapper ) );
563                        attributes.push_back( new Attribute( "cleanup", attr_params ) );
564                }
565
566                return new ObjectDecl(
567                        "__finally_hook",
568                        Type::StorageClasses(),
569                        LinkageSpec::Cforall,
570                        nullptr,
571                        new StructInstType(
572                                noQualifiers,
573                                hook_decl
574                                ),
575                        nullptr,
576                        attributes
577                        );
578        }
579
580        // Visiting/Mutating Functions
581        void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
582                // Validate the Statement's form.
583                ObjectDecl * decl =
584                        dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
585                if ( decl && true /* check decl->get_type() */ ) {
586                        // Pass.
587                } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
588                        throw SemanticError("catch must have exception type");
589                } else {
590                        throw SemanticError("catchResume must have exception type");
591                }
592
593                // Track the handler context.
594                GuardValue( cur_context );
595                if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
596                        cur_context = TerHandler;
597
598                        GuardValue( handler_except_decl );
599                        handler_except_decl = decl;
600                } else {
601                        cur_context = ResHandler;
602                }
603        }
604
605        void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
606                if ( !structDecl->has_body() ) {
607                        // Skip children?
608                        return;
609                } else if ( structDecl->get_name() == "__cfaehm__base_exception_t" ) {
610                        assert( nullptr == except_decl );
611                        except_decl = structDecl;
612                        init_func_types();
613                } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) {
614                        assert( nullptr == node_decl );
615                        node_decl = structDecl;
616                } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) {
617                        assert( nullptr == hook_decl );
618                        hook_decl = structDecl;
619                }
620                // Later we might get the exception type as well.
621        }
622
623        Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) {
624                assert( except_decl );
625
626                // Ignoring throwStmt->get_target() for now.
627                if ( ThrowStmt::Terminate == throwStmt->get_kind() ) {
628                        if ( throwStmt->get_expr() ) {
629                                return create_terminate_throw( throwStmt );
630                        } else if ( TerHandler == cur_context ) {
631                                return create_terminate_rethrow( throwStmt );
632                        } else {
633                                assertf(false, "Invalid throw in %s at %i\n",
634                                        throwStmt->location.filename.c_str(),
635                                        throwStmt->location.linenumber);
636                                return nullptr;
637                        }
638                } else {
639                        if ( throwStmt->get_expr() ) {
640                                return create_resume_throw( throwStmt );
641                        } else if ( ResHandler == cur_context ) {
642                                return create_resume_rethrow( throwStmt );
643                        } else {
644                                assertf(false, "Invalid throwResume in %s at %i\n",
645                                        throwStmt->location.filename.c_str(),
646                                        throwStmt->location.linenumber);
647                                return nullptr;
648                        }
649                }
650        }
651
652        Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) {
653                assert( except_decl );
654                assert( node_decl );
655                assert( hook_decl );
656
657                // Generate a prefix for the function names?
658
659                CompoundStmt * block = new CompoundStmt( noLabels );
660                CompoundStmt * inner = take_try_block( tryStmt );
661
662                if ( tryStmt->get_finally() ) {
663                        // Define the helper function.
664                        FunctionDecl * finally_block =
665                                create_finally_wrapper( tryStmt );
666                        appendDeclStmt( block, finally_block );
667                        // Create and add the finally cleanup hook.
668                        appendDeclStmt( block, create_finally_hook( finally_block ) );
669                }
670
671                CatchList termination_handlers;
672                CatchList resumption_handlers;
673                split( tryStmt->get_catchers(),
674                           termination_handlers, resumption_handlers );
675
676                if ( resumption_handlers.size() ) {
677                        // Define the helper function.
678                        FunctionDecl * resume_handler =
679                                create_resume_handler( resumption_handlers );
680                        appendDeclStmt( block, resume_handler );
681                        // Prepare hooks
682                        inner = create_resume_wrapper( inner, resume_handler );
683                }
684
685                if ( termination_handlers.size() ) {
686                        // Define the three helper functions.
687                        FunctionDecl * try_wrapper = create_try_wrapper( inner );
688                        appendDeclStmt( block, try_wrapper );
689                        FunctionDecl * terminate_catch =
690                                create_terminate_catch( termination_handlers );
691                        appendDeclStmt( block, terminate_catch );
692                        FunctionDecl * terminate_match =
693                                create_terminate_match( termination_handlers );
694                        appendDeclStmt( block, terminate_match );
695                        // Build the call to the try wrapper.
696                        inner = create_terminate_caller(
697                                try_wrapper, terminate_catch, terminate_match );
698                }
699
700                // Embed the try block.
701                block->push_back( inner );
702
703                return block;
704        }
705
706        void translateEHM( std::list< Declaration *> & translationUnit ) {
707                PassVisitor<ExceptionMutatorCore> translator;
708                mutateAll( translationUnit, translator );
709        }
710}
Note: See TracBrowser for help on using the repository browser.