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