- File:
-
- 1 edited
-
src/ControlStruct/ExceptTranslate.cc (modified) (19 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/ExceptTranslate.cc
rcbce272 rac10576 10 10 // Created On : Wed Jun 14 16:49:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tus Aug 8 16:54:00 201713 // Update Count : 712 // Last Modified On : Tus Jul 18 10:09:00 2017 13 // Update Count : 4 14 14 // 15 15 … … 21 21 #include "SynTree/Type.h" 22 22 #include "SynTree/Attribute.h" 23 #include "SynTree/VarExprReplacer.h"24 23 25 24 namespace ControlStruct { 25 26 // This (large) section could probably be moved out of the class 27 // and be static helpers instead. 28 29 // Type(Qualifiers &, false, std::list<Attribute *> &) 30 31 // void (*function)(); 32 static FunctionType try_func_t(Type::Qualifiers(), false); 33 // void (*function)(int, exception); 34 static FunctionType catch_func_t(Type::Qualifiers(), false); 35 // int (*function)(exception); 36 static FunctionType match_func_t(Type::Qualifiers(), false); 37 // bool (*function)(exception); 38 static FunctionType handle_func_t(Type::Qualifiers(), false); 39 // void (*function)(__attribute__((unused)) void *); 40 static FunctionType finally_func_t(Type::Qualifiers(), false); 41 42 static void init_func_types() { 43 static bool init_complete = false; 44 if (init_complete) { 45 return; 46 } 47 ObjectDecl index_obj( 48 "__handler_index", 49 Type::StorageClasses(), 50 LinkageSpec::Cforall, 51 /*bitfieldWidth*/ NULL, 52 new BasicType( noQualifiers, BasicType::SignedInt ), 53 /*init*/ NULL 54 ); 55 ObjectDecl exception_obj( 56 "__exception_inst", 57 Type::StorageClasses(), 58 LinkageSpec::Cforall, 59 /*bitfieldWidth*/ NULL, 60 new PointerType( 61 noQualifiers, 62 new BasicType( noQualifiers, BasicType::SignedInt ) 63 ), 64 /*init*/ NULL 65 ); 66 ObjectDecl bool_obj( 67 "__ret_bool", 68 Type::StorageClasses(), 69 LinkageSpec::Cforall, 70 /*bitfieldWidth*/ NULL, 71 new BasicType(noQualifiers, BasicType::Bool), 72 /*init*/ NULL 73 ); 74 ObjectDecl voidptr_obj( 75 "__hook", 76 Type::StorageClasses(), 77 LinkageSpec::Cforall, 78 NULL, 79 new PointerType( 80 noQualifiers, 81 new VoidType( 82 noQualifiers 83 ), 84 std::list<Attribute *>{new Attribute("unused")} 85 ), 86 NULL 87 ); 88 89 catch_func_t.get_parameters().push_back( index_obj.clone() ); 90 catch_func_t.get_parameters().push_back( exception_obj.clone() ); 91 match_func_t.get_returnVals().push_back( index_obj.clone() ); 92 match_func_t.get_parameters().push_back( exception_obj.clone() ); 93 handle_func_t.get_returnVals().push_back( bool_obj.clone() ); 94 handle_func_t.get_parameters().push_back( exception_obj.clone() ); 95 finally_func_t.get_parameters().push_back( voidptr_obj.clone() ); 96 97 init_complete = true; 98 } 26 99 27 100 // Buricratic Helpers (Not having to do with the paritular operation.) … … 42 115 } 43 116 117 template<typename T> 118 void free_all( std::list<T *> &list ) { 119 typename std::list<T *>::iterator it; 120 for ( it = list.begin() ; it != list.end() ; ++it ) { 121 delete *it; 122 } 123 list.clear(); 124 } 125 44 126 void appendDeclStmt( CompoundStmt * block, Declaration * item ) { 45 127 block->push_back(new DeclStmt(noLabels, item)); … … 50 132 } 51 133 52 class ExceptionMutatorCore : public WithGuards { 53 enum Context { NoHandler, TerHandler, ResHandler }; 54 55 // Also need to handle goto, break & continue. 56 // They need to be cut off in a ResHandler, until we enter another 57 // loop, switch or the goto stays within the function. 58 59 Context cur_context; 60 61 // The current (innermost) termination handler exception declaration. 62 ObjectDecl * handler_except_decl; 63 64 // The built in types used in translation. 65 StructDecl * except_decl; 66 StructDecl * node_decl; 67 StructDecl * hook_decl; 68 69 // The many helper functions for code/syntree generation. 70 Statement * create_given_throw( 71 const char * throwFunc, ThrowStmt * throwStmt ); 72 Statement * create_terminate_throw( ThrowStmt * throwStmt ); 73 Statement * create_terminate_rethrow( ThrowStmt * throwStmt ); 74 Statement * create_resume_throw( ThrowStmt * throwStmt ); 75 Statement * create_resume_rethrow( ThrowStmt * throwStmt ); 76 CompoundStmt * take_try_block( TryStmt * tryStmt ); 77 FunctionDecl * create_try_wrapper( CompoundStmt * body ); 78 FunctionDecl * create_terminate_catch( CatchList &handlers ); 79 CompoundStmt * create_single_matcher( 80 DeclarationWithType * except_obj, CatchStmt * modded_handler ); 81 FunctionDecl * create_terminate_match( CatchList &handlers ); 82 CompoundStmt * create_terminate_caller( FunctionDecl * try_wrapper, 83 FunctionDecl * terminate_catch, FunctionDecl * terminate_match ); 84 FunctionDecl * create_resume_handler( CatchList &handlers ); 85 CompoundStmt * create_resume_wrapper( 86 Statement * wraps, FunctionDecl * resume_handler ); 87 FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ); 88 ObjectDecl * create_finally_hook( FunctionDecl * finally_wrapper ); 89 90 // Types used in translation, make sure to use clone. 91 // void (*function)(); 92 FunctionType try_func_t; 93 // void (*function)(int, exception); 94 FunctionType catch_func_t; 95 // int (*function)(exception); 96 FunctionType match_func_t; 97 // bool (*function)(exception); 98 FunctionType handle_func_t; 99 // void (*function)(__attribute__((unused)) void *); 100 FunctionType finally_func_t; 101 102 StructInstType * create_except_type() { 103 assert( except_decl ); 104 return new StructInstType( noQualifiers, except_decl ); 105 } 106 void init_func_types(); 107 108 public: 109 ExceptionMutatorCore() : 110 cur_context( NoHandler ), 111 handler_except_decl( nullptr ), 112 except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr ), 113 try_func_t( noQualifiers, false ), 114 catch_func_t( noQualifiers, false ), 115 match_func_t( noQualifiers, false ), 116 handle_func_t( noQualifiers, false ), 117 finally_func_t( noQualifiers, false ) 118 {} 119 120 void premutate( CatchStmt *catchStmt ); 121 void premutate( StructDecl *structDecl ); 122 Statement * postmutate( ThrowStmt *throwStmt ); 123 Statement * postmutate( TryStmt *tryStmt ); 124 }; 125 126 void ExceptionMutatorCore::init_func_types() { 127 assert( except_decl ); 128 129 ObjectDecl index_obj( 130 "__handler_index", 131 Type::StorageClasses(), 132 LinkageSpec::Cforall, 133 /*bitfieldWidth*/ NULL, 134 // ThrowStmt Mutation Helpers 135 136 Statement * create_given_throw( 137 const char * throwFunc, ThrowStmt * throwStmt ) { 138 // { int NAME = EXPR; throwFunc( &NAME ); } 139 CompoundStmt * result = new CompoundStmt( noLabels ); 140 ObjectDecl * local = new ObjectDecl( 141 "__local_exception_copy", 142 Type::StorageClasses(), 143 LinkageSpec::Cforall, 144 NULL, 134 145 new BasicType( noQualifiers, BasicType::SignedInt ), 135 /*init*/ NULL 136 ); 137 ObjectDecl exception_obj( 138 "__exception_inst", 139 Type::StorageClasses(), 140 LinkageSpec::Cforall, 141 /*bitfieldWidth*/ NULL, 142 new PointerType( 143 noQualifiers, 144 new StructInstType( noQualifiers, except_decl ) 145 ), 146 /*init*/ NULL 147 ); 148 ObjectDecl bool_obj( 149 "__ret_bool", 150 Type::StorageClasses(), 151 LinkageSpec::Cforall, 152 /*bitfieldWidth*/ NULL, 153 new BasicType( noQualifiers, BasicType::Bool ), 154 /*init*/ NULL 155 ); 156 ObjectDecl voidptr_obj( 157 "__hook", 158 Type::StorageClasses(), 159 LinkageSpec::Cforall, 160 NULL, 161 new PointerType( 162 noQualifiers, 163 new VoidType( 164 noQualifiers 165 ), 166 std::list<Attribute *>{ new Attribute( "unused" ) } 167 ), 168 NULL 169 ); 170 171 catch_func_t.get_parameters().push_back( index_obj.clone() ); 172 catch_func_t.get_parameters().push_back( exception_obj.clone() ); 173 match_func_t.get_returnVals().push_back( index_obj.clone() ); 174 match_func_t.get_parameters().push_back( exception_obj.clone() ); 175 handle_func_t.get_returnVals().push_back( bool_obj.clone() ); 176 handle_func_t.get_parameters().push_back( exception_obj.clone() ); 177 finally_func_t.get_parameters().push_back( voidptr_obj.clone() ); 178 } 179 180 // ThrowStmt Mutation Helpers 181 182 Statement * ExceptionMutatorCore::create_given_throw( 183 const char * throwFunc, ThrowStmt * throwStmt ) { 184 // `throwFunc`( `throwStmt->get_name` ); 146 new SingleInit( throwStmt->get_expr() ) 147 ); 148 appendDeclStmt( result, local ); 185 149 UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) ); 186 call->get_args().push_back( throwStmt->get_expr() ); 150 call->get_args().push_back( new AddressExpr( nameOf( local ) ) ); 151 result->push_back( new ExprStmt( throwStmt->get_labels(), call ) ); 187 152 throwStmt->set_expr( nullptr ); 188 153 delete throwStmt; 189 return new ExprStmt( noLabels, call ); 190 } 191 192 Statement * ExceptionMutatorCore::create_terminate_throw( 193 ThrowStmt *throwStmt ) { 194 // __throw_terminate( `throwStmt->get_name()` ); } 154 return result; 155 } 156 157 Statement * create_terminate_throw( ThrowStmt *throwStmt ) { 158 // { int NAME = EXPR; __throw_terminate( &NAME ); } 195 159 return create_given_throw( "__cfaehm__throw_terminate", throwStmt ); 196 160 } 197 198 Statement * ExceptionMutatorCore::create_terminate_rethrow( 199 ThrowStmt *throwStmt ) { 200 // { `handler_except_decl` = NULL; __rethrow_terminate(); } 161 Statement * create_terminate_rethrow( ThrowStmt *throwStmt ) { 162 // __rethrow_terminate(); 201 163 assert( nullptr == throwStmt->get_expr() ); 202 assert( handler_except_decl ); 203 204 CompoundStmt * result = new CompoundStmt( throwStmt->get_labels() ); 205 result->push_back( new ExprStmt( noLabels, UntypedExpr::createAssign( 206 nameOf( handler_except_decl ), 207 new ConstantExpr( Constant::null( 208 new PointerType( 209 noQualifiers, 210 handler_except_decl->get_type()->clone() 211 ) 212 ) ) 213 ) ) ); 214 result->push_back( new ExprStmt( 215 noLabels, 164 Statement * result = new ExprStmt( 165 throwStmt->get_labels(), 216 166 new UntypedExpr( new NameExpr( "__cfaehm__rethrow_terminate" ) ) 217 ) );167 ); 218 168 delete throwStmt; 219 169 return result; 220 170 } 221 222 Statement * ExceptionMutatorCore::create_resume_throw( 223 ThrowStmt *throwStmt ) { 224 // __throw_resume( `throwStmt->get_name` ); 171 Statement * create_resume_throw( ThrowStmt *throwStmt ) { 172 // __throw_resume( EXPR ); 225 173 return create_given_throw( "__cfaehm__throw_resume", throwStmt ); 226 174 } 227 228 Statement * ExceptionMutatorCore::create_resume_rethrow( 229 ThrowStmt *throwStmt ) { 175 Statement * create_resume_rethrow( ThrowStmt *throwStmt ) { 230 176 // return false; 231 177 Statement * result = new ReturnStmt( … … 239 185 // TryStmt Mutation Helpers 240 186 241 CompoundStmt * ExceptionMutatorCore::take_try_block( TryStmt *tryStmt ) {187 CompoundStmt * take_try_block( TryStmt *tryStmt ) { 242 188 CompoundStmt * block = tryStmt->get_block(); 243 189 tryStmt->set_block( nullptr ); 244 190 return block; 245 191 } 246 247 FunctionDecl * ExceptionMutatorCore::create_try_wrapper( 248 CompoundStmt *body ) { 192 FunctionDecl * create_try_wrapper( CompoundStmt *body ) { 249 193 250 194 return new FunctionDecl( "try", Type::StorageClasses(), … … 252 196 } 253 197 254 FunctionDecl * ExceptionMutatorCore::create_terminate_catch( 255 CatchList &handlers ) { 198 FunctionDecl * create_terminate_catch( CatchList &handlers ) { 256 199 std::list<CaseStmt *> handler_wrappers; 257 200 258 201 FunctionType *func_type = catch_func_t.clone(); 259 202 DeclarationWithType * index_obj = func_type->get_parameters().front(); 260 DeclarationWithType * except_obj = func_type->get_parameters().back();203 // DeclarationWithType * except_obj = func_type->get_parameters().back(); 261 204 262 205 // Index 1..{number of handlers} … … 267 210 CatchStmt * handler = *it; 268 211 212 // INTEGERconstant Version 269 213 // case `index`: 270 214 // { 271 // `handler.decl` = { (virtual `decl.type`)`except` }; 272 // `handler.body`; 215 // `handler.body` 273 216 // } 274 217 // return; 275 CompoundStmt * block = new CompoundStmt( noLabels ); 276 277 // Just copy the exception value. (Post Validation) 278 ObjectDecl * handler_decl = 279 static_cast<ObjectDecl *>( handler->get_decl() ); 280 ObjectDecl * local_except = handler_decl->clone(); 281 local_except->set_init( 282 new ListInit({ new SingleInit( 283 new VirtualCastExpr( nameOf( except_obj ), 284 local_except->get_type() 285 ) 286 ) }) 287 ); 288 block->push_back( new DeclStmt( noLabels, local_except ) ); 289 290 // Add the cleanup attribute. 291 local_except->get_attributes().push_back( new Attribute( 292 "cleanup", 293 { new NameExpr( "__cfaehm__cleanup_terminate" ) } 294 ) ); 295 296 // Update variables in the body to point to this local copy. 297 { 298 VarExprReplacer::DeclMap mapping; 299 mapping[ handler_decl ] = local_except; 300 VarExprReplacer mapper( mapping ); 301 handler->get_body()->accept( mapper ); 302 } 303 304 block->push_back( handler->get_body() ); 218 std::list<Statement *> caseBody; 219 caseBody.push_back( handler->get_body() ); 305 220 handler->set_body( nullptr ); 306 307 std::list<Statement *> caseBody 308 { block, new ReturnStmt( noLabels, nullptr ) }; 221 caseBody.push_back( new ReturnStmt( noLabels, nullptr ) ); 222 309 223 handler_wrappers.push_back( new CaseStmt( 310 224 noLabels, … … 335 249 // Create a single check from a moddified handler. 336 250 // except_obj is referenced, modded_handler will be freed. 337 CompoundStmt * ExceptionMutatorCore::create_single_matcher(251 CompoundStmt *create_single_matcher( 338 252 DeclarationWithType * except_obj, CatchStmt * modded_handler ) { 339 // {340 // `modded_handler.decl`341 // if ( `decl.name = (virtual `decl.type`)`except`342 // [&& `modded_handler.cond`] ) {343 // `modded_handler.body`344 // }345 // }346 347 253 CompoundStmt * block = new CompoundStmt( noLabels ); 348 254 349 // Local Declaration 350 ObjectDecl * local_except = 351 dynamic_cast<ObjectDecl *>( modded_handler->get_decl() ); 352 assert( local_except ); 353 block->push_back( new DeclStmt( noLabels, local_except ) ); 354 355 // Check for type match. 356 Expression * cond = UntypedExpr::createAssign( nameOf( local_except ), 357 new VirtualCastExpr( nameOf( except_obj ), 358 local_except->get_type()->clone() ) ); 359 360 // Add the check on the conditional if it is provided. 255 // INTEGERconstant Version 256 assert( nullptr == modded_handler->get_decl() ); 257 ConstantExpr * number = 258 dynamic_cast<ConstantExpr*>( modded_handler->get_cond() ); 259 assert( number ); 260 modded_handler->set_cond( nullptr ); 261 262 Expression * cond; 263 { 264 std::list<Expression *> args; 265 args.push_back( number ); 266 267 std::list<Expression *> rhs_args; 268 rhs_args.push_back( nameOf( except_obj ) ); 269 Expression * rhs = new UntypedExpr( 270 new NameExpr( "*?" ), rhs_args ); 271 args.push_back( rhs ); 272 273 cond = new UntypedExpr( new NameExpr( "?==?" /*???*/), args ); 274 } 275 361 276 if ( modded_handler->get_cond() ) { 362 277 cond = new LogicalExpr( cond, modded_handler->get_cond() ); 363 278 } 364 // Construct the match condition.365 279 block->push_back( new IfStmt( noLabels, 366 280 cond, modded_handler->get_body(), nullptr ) ); … … 373 287 } 374 288 375 FunctionDecl * ExceptionMutatorCore::create_terminate_match( 376 CatchList &handlers ) { 377 // int match(exception * except) { 378 // HANDLER WRAPPERS { return `index`; } 379 // } 380 289 FunctionDecl * create_terminate_match( CatchList &handlers ) { 381 290 CompoundStmt * body = new CompoundStmt( noLabels ); 382 291 … … 410 319 } 411 320 412 CompoundStmt * ExceptionMutatorCore::create_terminate_caller(321 CompoundStmt * create_terminate_caller( 413 322 FunctionDecl * try_wrapper, 414 323 FunctionDecl * terminate_catch, 415 FunctionDecl * terminate_match ) { 416 // { __cfaehm__try_terminate(`try`, `catch`, `match`); } 324 FunctionDecl * terminate_match) { 417 325 418 326 UntypedExpr * caller = new UntypedExpr( new NameExpr( … … 428 336 } 429 337 430 FunctionDecl * ExceptionMutatorCore::create_resume_handler( 431 CatchList &handlers ) { 432 // bool handle(exception * except) { 433 // HANDLER WRAPPERS { `hander->body`; return true; } 434 // } 338 FunctionDecl * create_resume_handler( CatchList &handlers ) { 435 339 CompoundStmt * body = new CompoundStmt( noLabels ); 436 340 … … 465 369 } 466 370 467 CompoundStmt * ExceptionMutatorCore::create_resume_wrapper( 371 CompoundStmt * create_resume_wrapper( 372 StructDecl * node_decl, 468 373 Statement * wraps, 469 374 FunctionDecl * resume_handler ) { … … 509 414 } 510 415 511 FunctionDecl * ExceptionMutatorCore::create_finally_wrapper( 512 TryStmt * tryStmt ) { 513 // void finally() { <finally code> } 416 FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ) { 514 417 FinallyStmt * finally = tryStmt->get_finally(); 515 418 CompoundStmt * body = finally->get_block(); … … 522 425 } 523 426 524 ObjectDecl * ExceptionMutatorCore::create_finally_hook(525 FunctionDecl * finally_wrapper ) {427 ObjectDecl * create_finally_hook( 428 StructDecl * hook_decl, FunctionDecl * finally_wrapper ) { 526 429 // struct __cfaehm__cleanup_hook __finally_hook 527 430 // __attribute__((cleanup( finally_wrapper ))); … … 549 452 } 550 453 551 // Visiting/Mutating Functions 552 void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) { 553 // Validate the Statement's form. 554 ObjectDecl * decl = 555 dynamic_cast<ObjectDecl *>( catchStmt->get_decl() ); 556 if ( decl && true /* check decl->get_type() */ ) { 557 // Pass. 558 } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) { 559 throw SemanticError("catch must have exception type"); 560 } else { 561 throw SemanticError("catchResume must have exception type"); 562 } 563 564 // Track the handler context. 565 GuardValue( cur_context ); 566 if ( CatchStmt::Terminate == catchStmt->get_kind() ) { 567 cur_context = TerHandler; 568 569 GuardValue( handler_except_decl ); 570 handler_except_decl = decl; 571 } else { 572 cur_context = ResHandler; 573 } 574 } 575 576 void ExceptionMutatorCore::premutate( StructDecl *structDecl ) { 577 if ( !structDecl->has_body() ) { 578 // Skip children? 579 return; 580 } else if ( structDecl->get_name() == "__cfaehm__base_exception_t" ) { 581 assert( nullptr == except_decl ); 582 except_decl = structDecl; 583 init_func_types(); 584 } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) { 585 assert( nullptr == node_decl ); 586 node_decl = structDecl; 587 } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) { 588 assert( nullptr == hook_decl ); 589 hook_decl = structDecl; 590 } 591 // Later we might get the exception type as well. 592 } 454 455 class ExceptionMutatorCore : public WithGuards { 456 enum Context { NoHandler, TerHandler, ResHandler }; 457 458 // Also need to handle goto, break & continue. 459 // They need to be cut off in a ResHandler, until we enter another 460 // loop, switch or the goto stays within the function. 461 462 Context cur_context; 463 464 // We might not need this, but a unique base for each try block's 465 // generated functions might be nice. 466 //std::string curFunctionName; 467 //unsigned int try_count = 0; 468 469 StructDecl *node_decl; 470 StructDecl *hook_decl; 471 472 public: 473 ExceptionMutatorCore() : 474 cur_context(NoHandler), 475 node_decl(nullptr), hook_decl(nullptr) 476 {} 477 478 void premutate( CatchStmt *catchStmt ); 479 void premutate( StructDecl *structDecl ); 480 Statement * postmutate( ThrowStmt *throwStmt ); 481 Statement * postmutate( TryStmt *tryStmt ); 482 }; 593 483 594 484 Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) { 595 assert( except_decl );596 597 485 // Ignoring throwStmt->get_target() for now. 598 486 if ( ThrowStmt::Terminate == throwStmt->get_kind() ) { … … 622 510 623 511 Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) { 624 assert( except_decl );625 512 assert( node_decl ); 626 513 assert( hook_decl ); … … 637 524 appendDeclStmt( block, finally_block ); 638 525 // Create and add the finally cleanup hook. 639 appendDeclStmt( block, create_finally_hook( finally_block ) ); 526 appendDeclStmt( block, 527 create_finally_hook( hook_decl, finally_block ) ); 640 528 } 641 529 … … 651 539 appendDeclStmt( block, resume_handler ); 652 540 // Prepare hooks 653 inner = create_resume_wrapper( inner, resume_handler );541 inner = create_resume_wrapper( node_decl, inner, resume_handler ); 654 542 } 655 543 … … 672 560 block->push_back( inner ); 673 561 562 //free_all( termination_handlers ); 563 //free_all( resumption_handlers ); 564 674 565 return block; 675 566 } 676 567 568 void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) { 569 GuardValue( cur_context ); 570 if ( CatchStmt::Terminate == catchStmt->get_kind() ) { 571 cur_context = TerHandler; 572 } else { 573 cur_context = ResHandler; 574 } 575 } 576 577 void ExceptionMutatorCore::premutate( StructDecl *structDecl ) { 578 if ( !structDecl->has_body() ) { 579 // Skip children? 580 return; 581 } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) { 582 assert( nullptr == node_decl ); 583 node_decl = structDecl; 584 } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) { 585 assert( nullptr == hook_decl ); 586 hook_decl = structDecl; 587 } 588 // Later we might get the exception type as well. 589 } 590 677 591 void translateEHM( std::list< Declaration *> & translationUnit ) { 592 init_func_types(); 593 678 594 PassVisitor<ExceptionMutatorCore> translator; 679 595 mutateAll( translationUnit, translator );
Note:
See TracChangeset
for help on using the changeset viewer.