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