Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/ExceptTranslateNew.cpp

    r5f3ba11 r0fba0d4  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Nov  8 11:53:00 2021
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Nov  8 16:50:00 2021
    13 // Update Count     : 0
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Mon Jan 31 18:49:58 2022
     13// Update Count     : 1
    1414//
    1515
     
    2020#include "AST/Stmt.hpp"
    2121#include "AST/TranslationUnit.hpp"
    22 #include "AST/DeclReplacer.hpp"
    2322
    2423namespace ControlStruct {
    25 
    26 namespace {
    27 
    28         typedef std::list<ast::CatchStmt*> CatchList;
    29 
    30         void split( CatchList& allHandlers, CatchList& terHandlers,
    31                                 CatchList& resHandlers ) {
    32                 while ( !allHandlers.empty() ) {
    33                         ast::CatchStmt * stmt = allHandlers.front();
    34                         allHandlers.pop_front();
    35                         if (stmt->kind == ast::ExceptionKind::Terminate) {
    36                                 terHandlers.push_back(stmt);
    37                         } else {
    38                                 resHandlers.push_back(stmt);
    39                         }
    40                 }
    41         }
    42 
    43         void appendDeclStmt( ast::CompoundStmt * block, ast::DeclWithType * item ) {
    44                 block->push_back(new ast::DeclStmt(block->location, item));
    45         }
    4624
    4725class TranslateThrowsCore : public ast::WithGuards {
     
    148126}
    149127
    150 
    151 class TryMutatorCore {
    152         // The built in types used in translation.
    153         const ast::StructDecl * except_decl;
    154         const ast::StructDecl * node_decl;
    155         const ast::StructDecl * hook_decl;
    156 
    157         // The many helper functions for code/syntree generation.
    158         ast::CompoundStmt * take_try_block( ast::TryStmt * tryStmt );
    159         ast::FunctionDecl * create_try_wrapper( const ast::CompoundStmt * body );
    160         ast::FunctionDecl * create_terminate_catch( CatchList &handlers );
    161         ast::CompoundStmt * create_single_matcher(
    162                 const ast::DeclWithType * except_obj, ast::CatchStmt * modded_handler );
    163         ast::FunctionDecl * create_terminate_match( CatchList &handlers );
    164         ast::CompoundStmt * create_terminate_caller( CodeLocation loc, ast::FunctionDecl * try_wrapper,
    165                 ast::FunctionDecl * terminate_catch, ast::FunctionDecl * terminate_match );
    166         ast::FunctionDecl * create_resume_handler( CatchList &handlers );
    167         ast::CompoundStmt * create_resume_wrapper(
    168                 const ast::Stmt * wraps, const ast::FunctionDecl * resume_handler );
    169         ast::FunctionDecl * create_finally_wrapper( ast::TryStmt * tryStmt );
    170         ast::ObjectDecl * create_finally_hook( ast::FunctionDecl * finally_wrapper );
    171         ast::Stmt * create_resume_rethrow( const ast::ThrowStmt * throwStmt );
    172 
    173         // Types used in translation, make sure to use clone.
    174         // void (*function)();
    175         ast::FunctionDecl * try_func_t;
    176         // void (*function)(int, exception);
    177         ast::FunctionDecl * catch_func_t;
    178         // int (*function)(exception);
    179         ast::FunctionDecl * match_func_t;
    180         // bool (*function)(exception);
    181         ast::FunctionDecl * handle_func_t;
    182         // void (*function)(__attribute__((unused)) void *);
    183         ast::FunctionDecl * finally_func_t;
    184 
    185         ast::StructInstType * create_except_type() {
    186                 assert( except_decl );
    187                 return new ast::StructInstType( except_decl );
    188         }
    189         void init_func_types();
    190 
    191 public:
    192         TryMutatorCore() :
    193                 except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr )
    194         {}
    195 
    196         void previsit( const ast::StructDecl *structDecl );
    197         ast::Stmt * postvisit( const ast::TryStmt *tryStmt );
    198         ast::Stmt * postvisit( const ast::ThrowStmt *throwStmt );
    199 };
    200 
    201 void TryMutatorCore::init_func_types() {
    202         assert( except_decl );
    203 
    204         ast::ObjectDecl index_obj(
    205                 {},
    206                 "__handler_index",
    207                 new ast::BasicType(ast::BasicType::SignedInt)
    208                 );
    209         ast::ObjectDecl exception_obj(
    210                 {},
    211                 "__exception_inst",
    212                 new ast::PointerType(
    213                         new ast::StructInstType( except_decl )
    214                         ),
    215                 NULL
    216                 );
    217         ast::ObjectDecl bool_obj(
    218                 {},
    219                 "__ret_bool",
    220                 new ast::BasicType( ast::BasicType::Bool ),
    221                 nullptr, //init
    222                 ast::Storage::Classes{},
    223                 ast::Linkage::Cforall,
    224                 nullptr, //width
    225                 std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
    226                 );
    227         ast::ObjectDecl voidptr_obj(
    228                 {},
    229                 "__hook",
    230                 new ast::PointerType(
    231                         new ast::VoidType()
    232                 ),
    233                 nullptr, //init
    234                 ast::Storage::Classes{},
    235                 ast::Linkage::Cforall,
    236                 nullptr, //width
    237                 std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
    238                 );
    239 
    240         ast::ObjectDecl unused_index_obj(
    241                 {},
    242                 "__handler_index",
    243                 new ast::BasicType(ast::BasicType::SignedInt),
    244                 nullptr,
    245                 ast::Storage::Classes{},
    246                 ast::Linkage::Cforall,
    247                 nullptr, //width
    248                 std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
    249         );
    250         //unused_index_obj->attributes.push_back( new Attribute( "unused" ) );
    251 
    252         try_func_t = new ast::FunctionDecl(
    253                 {},
    254                 "try",
    255                 {}, //forall
    256                 {}, //no param
    257                 {}, //no return
    258                 nullptr,
    259                 ast::Storage::Classes{},
    260                 ast::Linkage::Cforall
    261         );
    262 
    263         catch_func_t = new ast::FunctionDecl(
    264                 {},
    265                 "catch",
    266                 {}, //forall
    267                 {ast::deepCopy(&index_obj), ast::deepCopy(&exception_obj)},//param
    268                 {}, //return void
    269                 nullptr,
    270                 ast::Storage::Classes{},
    271                 ast::Linkage::Cforall
    272         );
    273 
    274         match_func_t = new ast::FunctionDecl(
    275                 {},
    276                 "match",
    277                 {}, //forall
    278                 {ast::deepCopy(&exception_obj)},
    279                 {ast::deepCopy(&unused_index_obj)},
    280                 nullptr,
    281                 ast::Storage::Classes{},
    282                 ast::Linkage::Cforall
    283         );
    284 
    285         handle_func_t = new ast::FunctionDecl(
    286                 {},
    287                 "handle",
    288                 {}, //forall
    289                 {ast::deepCopy(&exception_obj)},
    290                 {ast::deepCopy(&bool_obj)},
    291                 nullptr,
    292                 ast::Storage::Classes{},
    293                 ast::Linkage::Cforall
    294         );
    295 
    296         finally_func_t = new ast::FunctionDecl(
    297                 {},
    298                 "finally",
    299                 {}, //forall
    300                 {ast::deepCopy(&voidptr_obj)},
    301                 {}, //return void
    302                 nullptr,
    303                 ast::Storage::Classes{},
    304                 ast::Linkage::Cforall
    305         );
    306 
    307         //catch_func_t.get_parameters().push_back( index_obj.clone() );
    308         //catch_func_t.get_parameters().push_back( exception_obj.clone() );
    309         //match_func_t.get_returnVals().push_back( unused_index_obj );
    310         //match_func_t.get_parameters().push_back( exception_obj.clone() );
    311         //handle_func_t.get_returnVals().push_back( bool_obj.clone() );
    312         //handle_func_t.get_parameters().push_back( exception_obj.clone() );
    313         //finally_func_t.get_parameters().push_back( voidptr_obj.clone() );
    314 }
    315 
    316 // TryStmt Mutation Helpers
    317 
    318 /*
    319 ast::CompoundStmt * TryMutatorCore::take_try_block( ast::TryStmt *tryStmt ) {
    320         ast::CompoundStmt * block = tryStmt->body;
    321         tryStmt->body = nullptr;
    322         return block;
    323 }
    324 */
    325 
    326 ast::FunctionDecl * TryMutatorCore::create_try_wrapper(
    327                 const ast::CompoundStmt *body ) {
    328 
    329         ast::FunctionDecl * ret = ast::deepCopy(try_func_t);
    330         ret->stmts = body;
    331         return ret;
    332 }
    333 
    334 ast::FunctionDecl * TryMutatorCore::create_terminate_catch(
    335                 CatchList &handlers ) {
    336         std::vector<ast::ptr<ast::Stmt>> handler_wrappers;
    337 
    338         assert (!handlers.empty());
    339         const CodeLocation loc = handlers.front()->location;
    340 
    341         ast::FunctionDecl * func_t = ast::deepCopy(catch_func_t);
    342         const ast::DeclWithType * index_obj = func_t->params.front();
    343         const ast::DeclWithType * except_obj = func_t->params.back();
    344 
    345         // Index 1..{number of handlers}
    346         int index = 0;
    347         CatchList::iterator it = handlers.begin();
    348         for ( ; it != handlers.end() ; ++it ) {
    349                 ++index;
    350                 ast::CatchStmt * handler = *it;
    351                 const CodeLocation loc = handler->location;
    352 
    353                 // case `index`:
    354                 // {
    355                 //     `handler.decl` = { (virtual `decl.type`)`except` };
    356                 //     `handler.body`;
    357                 // }
    358                 // return;
    359                 ast::CompoundStmt * block = new ast::CompoundStmt(loc);
    360 
    361                 // Just copy the exception value. (Post Validation)
    362                 const ast::ObjectDecl * handler_decl =
    363                         handler->decl.strict_as<ast::ObjectDecl>();
    364                 ast::ObjectDecl * local_except = ast::deepCopy(handler_decl);
    365                 ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc,
    366                         new ast::VariableExpr( loc, except_obj ),
    367                         local_except->get_type()
    368                         );
    369                 vcex->location = handler->location;
    370                 local_except->init = new ast::ListInit(loc, { new ast::SingleInit( loc, vcex ) });
    371                 block->push_back( new ast::DeclStmt( loc, local_except ) );
    372 
    373                 // Add the cleanup attribute.
    374                 local_except->attributes.push_back( new ast::Attribute(
    375                         "cleanup",
    376                         { new ast::NameExpr( loc, "__cfaehm_cleanup_terminate" ) }
    377                         ) );
    378 
    379                 ast::DeclReplacer::DeclMap mapping;
    380                 mapping[handler_decl] = local_except;
    381                 const ast::Stmt * mutBody = strict_dynamic_cast<const ast::Stmt *>(
    382                         ast::DeclReplacer::replace(handler->body, mapping));
    383 
    384 
    385                 block->push_back( mutBody );
    386                 // handler->body = nullptr;
    387 
    388                 handler_wrappers.push_back( new ast::CaseStmt(loc,
    389                         ast::ConstantExpr::from_int(loc, index) ,
    390                         { block, new ast::ReturnStmt( loc, nullptr ) }
    391                         ));
    392         }
    393         // TODO: Some sort of meaningful error on default perhaps?
    394 
    395         /*
    396         std::list<Statement*> stmt_handlers;
    397         while ( !handler_wrappers.empty() ) {
    398                 stmt_handlers.push_back( handler_wrappers.front() );
    399                 handler_wrappers.pop_front();
    400         }
    401         */
    402 
    403         ast::SwitchStmt * handler_lookup = new ast::SwitchStmt(loc,
    404                 new ast::VariableExpr( loc, index_obj ),
    405                 std::move(handler_wrappers)
    406                 );
    407         ast::CompoundStmt * body = new ast::CompoundStmt(loc,
    408                 {handler_lookup});
    409 
    410         func_t->stmts = body;
    411         return func_t;
    412 }
    413 
    414 // Create a single check from a moddified handler.
    415 // except_obj is referenced, modded_handler will be freed.
    416 ast::CompoundStmt * TryMutatorCore::create_single_matcher(
    417                 const ast::DeclWithType * except_obj, ast::CatchStmt * modded_handler ) {
    418         // {
    419         //     `modded_handler.decl`
    420         //     if ( `decl.name = (virtual `decl.type`)`except`
    421         //             [&& `modded_handler.cond`] ) {
    422         //         `modded_handler.body`
    423         //     }
    424         // }
    425 
    426         const CodeLocation loc = modded_handler->location;
    427         ast::CompoundStmt * block = new ast::CompoundStmt(loc);
    428 
    429         // Local Declaration
    430         const ast::ObjectDecl * local_except =
    431                 modded_handler->decl.strict_as<ast::ObjectDecl>();
    432         block->push_back( new ast::DeclStmt( loc,  local_except ) );
    433 
    434         // Check for type match.
    435         ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc,
    436                 new ast::VariableExpr(loc, except_obj ),
    437                 local_except->get_type()
    438                 );
    439         ast::Expr * cond = ast::UntypedExpr::createAssign(loc,
    440                 new ast::VariableExpr(loc, local_except ), vcex );
    441 
    442         // Add the check on the conditional if it is provided.
    443         if ( modded_handler->cond ) {
    444                 cond = new ast::LogicalExpr( loc, cond, modded_handler->cond, ast::LogicalFlag::AndExpr );
    445         }
    446         // Construct the match condition.
    447         block->push_back( new ast::IfStmt(loc,
    448                 cond, modded_handler->body, nullptr ) );
    449 
    450         // xxx - how does this work in new ast
    451         //modded_handler->set_decl( nullptr );
    452         //modded_handler->set_cond( nullptr );
    453         //modded_handler->set_body( nullptr );
    454         //delete modded_handler;
    455         return block;
    456 }
    457 
    458 ast::FunctionDecl * TryMutatorCore::create_terminate_match(
    459                 CatchList &handlers ) {
    460         // int match(exception * except) {
    461         //     HANDLER WRAPPERS { return `index`; }
    462         // }
    463 
    464         assert (!handlers.empty());
    465         const CodeLocation loc = handlers.front()->location;
    466 
    467         ast::CompoundStmt * body = new ast::CompoundStmt(loc);
    468 
    469         ast::FunctionDecl * func_t = ast::deepCopy(match_func_t);
    470         const ast::DeclWithType * except_obj = func_t->params.back();
    471 
    472         // Index 1..{number of handlers}
    473         int index = 0;
    474         CatchList::iterator it;
    475         for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
    476                 ++index;
    477                 ast::CatchStmt * handler = *it;
    478 
    479                 // Body should have been taken by create_terminate_catch.
    480                 // xxx - just ignore it?
    481                 // assert( nullptr == handler->get_body() );
    482 
    483                 // Create new body.
    484                 handler->body = new ast::ReturnStmt( handler->location,
    485                         ast::ConstantExpr::from_int( handler->location, index ) );
    486 
    487                 // Create the handler.
    488                 body->push_back( create_single_matcher( except_obj, handler ) );
    489                 *it = nullptr;
    490         }
    491 
    492         body->push_back( new ast::ReturnStmt(loc,
    493                 ast::ConstantExpr::from_int( loc, 0 ) ));
    494 
    495         func_t->stmts = body;
    496 
    497         return func_t;
    498 }
    499 
    500 ast::CompoundStmt * TryMutatorCore::create_terminate_caller(
    501                 CodeLocation loc,
    502                 ast::FunctionDecl * try_wrapper,
    503                 ast::FunctionDecl * terminate_catch,
    504                 ast::FunctionDecl * terminate_match ) {
    505         // { __cfaehm_try_terminate(`try`, `catch`, `match`); }
    506 
    507         ast::UntypedExpr * caller = new ast::UntypedExpr(loc, new ast::NameExpr(loc,
    508                 "__cfaehm_try_terminate" ) );
    509         caller->args.push_back( new ast::VariableExpr(loc, try_wrapper ) );
    510         caller->args.push_back( new ast::VariableExpr(loc, terminate_catch ) );
    511         caller->args.push_back( new ast::VariableExpr(loc, terminate_match ) );
    512 
    513         ast::CompoundStmt * callStmt = new ast::CompoundStmt(loc);
    514         callStmt->push_back( new ast::ExprStmt( loc, caller ) );
    515         return callStmt;
    516 }
    517 
    518 ast::FunctionDecl * TryMutatorCore::create_resume_handler(
    519                 CatchList &handlers ) {
    520         // bool handle(exception * except) {
    521         //     HANDLER WRAPPERS { `hander->body`; return true; }
    522         // }
    523         assert (!handlers.empty());
    524         const CodeLocation loc = handlers.front()->location;
    525         ast::CompoundStmt * body = new ast::CompoundStmt(loc);
    526 
    527         ast::FunctionDecl * func_t = ast::deepCopy(handle_func_t);
    528         const ast::DeclWithType * except_obj = func_t->params.back();
    529 
    530         CatchList::iterator it;
    531         for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
    532                 ast::CatchStmt * handler = *it;
    533                 const CodeLocation loc = handler->location;
    534                 // Modifiy body.
    535                 ast::CompoundStmt * handling_code;
    536                 if (handler->body.as<ast::CompoundStmt>()) {
    537                         handling_code =
    538                         strict_dynamic_cast<ast::CompoundStmt*>( handler->body.get_and_mutate() );
    539                 } else {
    540                         handling_code = new ast::CompoundStmt(loc);
    541                         handling_code->push_back( handler->body );
    542                 }
    543                 handling_code->push_back( new ast::ReturnStmt(loc,
    544                         ast::ConstantExpr::from_bool(loc, true ) ) );
    545                 handler->body = handling_code;
    546 
    547                 // Create the handler.
    548                 body->push_back( create_single_matcher( except_obj, handler ) );
    549                 *it = nullptr;
    550         }
    551 
    552         body->push_back( new ast::ReturnStmt(loc,
    553                 ast::ConstantExpr::from_bool(loc, false ) ) );
    554         func_t->stmts = body;
    555 
    556         return func_t;
    557 }
    558 
    559 ast::CompoundStmt * TryMutatorCore::create_resume_wrapper(
    560                 const ast::Stmt * wraps,
    561                 const ast::FunctionDecl * resume_handler ) {
    562         const CodeLocation loc = wraps->location;
    563         ast::CompoundStmt * body = new ast::CompoundStmt(loc);
    564 
    565         // struct __try_resume_node __resume_node
    566         //      __attribute__((cleanup( __cfaehm_try_resume_cleanup )));
    567         // ** unwinding of the stack here could cause problems **
    568         // ** however I don't think that can happen currently **
    569         // __cfaehm_try_resume_setup( &__resume_node, resume_handler );
    570 
    571         ast::ObjectDecl * obj = new ast::ObjectDecl(
    572                 loc,
    573                 "__resume_node",
    574                 new ast::StructInstType(
    575                         node_decl
    576                         ),
    577                 nullptr,
    578                 ast::Storage::Classes{},
    579                 ast::Linkage::Cforall,
    580                 nullptr,
    581                 {new ast::Attribute("cleanup", {new ast::NameExpr(loc, "__cfaehm_try_resume_cleanup")})}
    582                 );
    583         appendDeclStmt( body, obj );
    584 
    585         ast::UntypedExpr *setup = new ast::UntypedExpr(loc, new ast::NameExpr(loc,
    586                 "__cfaehm_try_resume_setup" ) );
    587         setup->args.push_back( new ast::AddressExpr( loc, new ast::VariableExpr(loc, obj ) ) );
    588         setup->args.push_back( new ast::VariableExpr( loc, resume_handler ) );
    589 
    590         body->push_back( new ast::ExprStmt(loc, setup ) );
    591 
    592         body->push_back( wraps );
    593         return body;
    594 }
    595 
    596 ast::FunctionDecl * TryMutatorCore::create_finally_wrapper(
    597                 ast::TryStmt * tryStmt ) {
    598         // void finally() { `finally->block` }
    599         const ast::FinallyStmt * finally = tryStmt->finally;
    600         const ast::CompoundStmt * body = finally->body;
    601 
    602         ast::FunctionDecl * func_t = ast::deepCopy(finally_func_t);
    603         func_t->stmts = body;
    604 
    605         // finally->set_block( nullptr );
    606         // delete finally;
    607         tryStmt->finally = nullptr;
    608 
    609 
    610         return func_t;
    611 }
    612 
    613 ast::ObjectDecl * TryMutatorCore::create_finally_hook(
    614                 ast::FunctionDecl * finally_wrapper ) {
    615         // struct __cfaehm_cleanup_hook __finally_hook
    616         //      __attribute__((cleanup( `finally_wrapper` )));
    617 
    618         const CodeLocation loc = finally_wrapper->location;
    619         // Make Cleanup Attribute.
    620         /*
    621         std::list< ast::Attribute * > attributes;
    622         {
    623                 std::list<  > attr_params;
    624                 attr_params.push_back( nameOf( finally_wrapper ) );
    625                 attributes.push_back( new Attribute( "cleanup", attr_params ) );
    626         }
    627         */
    628 
    629         return new ast::ObjectDecl(
    630                 loc,
    631                 "__finally_hook",
    632                 new ast::StructInstType(
    633                         hook_decl
    634                         ),
    635                 nullptr,
    636                 ast::Storage::Classes{},
    637                 ast::Linkage::Cforall,
    638                 nullptr,
    639                 {new ast::Attribute("cleanup", {new ast::VariableExpr{loc, finally_wrapper}})}
    640                 );
    641 }
    642 
    643 ast::Stmt * TryMutatorCore::create_resume_rethrow( const ast::ThrowStmt *throwStmt ) {
    644         // return false;
    645         const CodeLocation loc = throwStmt->location;
    646         ast::Stmt * result = new ast::ReturnStmt(loc,
    647                 ast::ConstantExpr::from_bool( loc, false )
    648                 );
    649         result->labels = throwStmt->labels;
    650         // delete throwStmt; done by postvisit
    651         return result;
    652 }
    653 
    654 // Visiting/Mutating Functions
    655 void TryMutatorCore::previsit( const ast::StructDecl *structDecl ) {
    656         if ( !structDecl->body ) {
    657                 // Skip children?
    658                 return;
    659         } else if ( structDecl->name == "__cfaehm_base_exception_t" ) {
    660                 assert( nullptr == except_decl );
    661                 except_decl = structDecl;
    662                 init_func_types();
    663         } else if ( structDecl->name == "__cfaehm_try_resume_node" ) {
    664                 assert( nullptr == node_decl );
    665                 node_decl = structDecl;
    666         } else if ( structDecl->name == "__cfaehm_cleanup_hook" ) {
    667                 assert( nullptr == hook_decl );
    668                 hook_decl = structDecl;
    669         }
    670 }
    671 
    672 ast::Stmt * TryMutatorCore::postvisit( const ast::TryStmt *tryStmt ) {
    673         assert( except_decl );
    674         assert( node_decl );
    675         assert( hook_decl );
    676 
    677         const CodeLocation loc = tryStmt->location;
    678         ast::TryStmt * mutStmt = mutate(tryStmt);
    679         // Generate a prefix for the function names?
    680 
    681         ast::CompoundStmt * block = new ast::CompoundStmt( loc );
    682         // ast::CompoundStmt * inner = take_try_block( mutStmt );
    683         // this is never mutated so let node deletion do its job?
    684         const ast::CompoundStmt * inner = mutStmt->body;
    685 
    686         if ( mutStmt->finally ) {
    687                 // Define the helper function.
    688                 ast::FunctionDecl * finally_block =
    689                         create_finally_wrapper( mutStmt );
    690                 appendDeclStmt( block, finally_block );
    691                 // Create and add the finally cleanup hook.
    692                 appendDeclStmt( block, create_finally_hook( finally_block ) );
    693         }
    694 
    695         CatchList termination_handlers;
    696         CatchList resumption_handlers;
    697 
    698         for (auto & handler: mutStmt->handlers) {
    699                 // xxx - should always be unique? mutate as safe const-cast
    700                 assert(handler->unique());
    701                 if (handler->kind == ast::ExceptionKind::Resume) {
    702                         resumption_handlers.push_back(handler.get_and_mutate());
    703                 }
    704                 else {
    705                         termination_handlers.push_back(handler.get_and_mutate());
    706                 }
    707         }
    708         // split( mutStmt->handlers,
    709         //              termination_handlers, resumption_handlers );
    710 
    711         if ( resumption_handlers.size() ) {
    712                 // Define the helper function.
    713                 ast::FunctionDecl * resume_handler =
    714                         create_resume_handler( resumption_handlers );
    715                 appendDeclStmt( block, resume_handler );
    716                 // Prepare hooks
    717                 inner = create_resume_wrapper( inner, resume_handler );
    718         }
    719 
    720         if ( termination_handlers.size() ) {
    721                 // Define the three helper functions.
    722                 ast::FunctionDecl * try_wrapper = create_try_wrapper( inner );
    723                 appendDeclStmt( block, try_wrapper );
    724                 ast::FunctionDecl * terminate_catch =
    725                         create_terminate_catch( termination_handlers );
    726                 appendDeclStmt( block, terminate_catch );
    727                 ast::FunctionDecl * terminate_match =
    728                         create_terminate_match( termination_handlers );
    729                 appendDeclStmt( block, terminate_match );
    730                 // Build the call to the try wrapper.
    731                 inner = create_terminate_caller(inner->location,
    732                         try_wrapper, terminate_catch, terminate_match );
    733         }
    734 
    735         // Embed the try block.
    736         block->push_back( inner );
    737 
    738         return block;
    739 }
    740 
    741 ast::Stmt * TryMutatorCore::postvisit( const ast::ThrowStmt *throwStmt ) {
    742         // Only valid `throwResume;` statements should remain. (2/3 checks)
    743         assert( ast::ExceptionKind::Resume == throwStmt->kind && ! throwStmt->expr );
    744         return create_resume_rethrow( throwStmt );
    745 }
    746 
    747 } // namespace
    748 
    749128void translateThrows( ast::TranslationUnit & transUnit ) {
    750129        ast::Pass<TranslateThrowsCore>::run( transUnit );
    751 }
    752 
    753 void translateTries( ast::TranslationUnit & transUnit ) {
    754         ast::Pass<TryMutatorCore>::run(transUnit);
    755130}
    756131
Note: See TracChangeset for help on using the changeset viewer.