source: src/ControlStruct/ExceptTranslate.cc@ ea5023c

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since ea5023c was 86d5ba7c, checked in by Andrew Beach <ajbeach@…>, 8 years ago

Added the memory management calls to the exception control flow.

  • Property mode set to 100644
File size: 20.4 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// ExceptVisitor.cc --
8//
9// Author : Andrew Beach
10// Created On : Wed Jun 14 16:49:00 2017
11// Last Modified By : Andrew Beach
12// Last Modified On : Fri Jul 28 14:03:00 2017
13// Update Count : 5
14//
15
16#include "ExceptTranslate.h"
17#include "Common/PassVisitor.h"
18#include "SynTree/Statement.h"
19#include "SynTree/Declaration.h"
20#include "SynTree/Expression.h"
21#include "SynTree/Type.h"
22#include "SynTree/Attribute.h"
23#include "SynTree/VarExprReplacer.h"
24
25namespace ControlStruct {
26
27 // void (*function)();
28 static FunctionType try_func_t(noQualifiers, false);
29 // void (*function)(int, exception);
30 static FunctionType catch_func_t(noQualifiers, false);
31 // int (*function)(exception);
32 static FunctionType match_func_t(noQualifiers, false);
33 // bool (*function)(exception);
34 static FunctionType handle_func_t(noQualifiers, false);
35 // void (*function)(__attribute__((unused)) void *);
36 static FunctionType finally_func_t(noQualifiers, false);
37
38 static void init_func_types() {
39 static bool init_complete = false;
40 if (init_complete) {
41 return;
42 }
43 ObjectDecl index_obj(
44 "__handler_index",
45 Type::StorageClasses(),
46 LinkageSpec::Cforall,
47 /*bitfieldWidth*/ NULL,
48 new BasicType( noQualifiers, BasicType::SignedInt ),
49 /*init*/ NULL
50 );
51 ObjectDecl exception_obj(
52 "__exception_inst",
53 Type::StorageClasses(),
54 LinkageSpec::Cforall,
55 /*bitfieldWidth*/ NULL,
56 new PointerType(
57 noQualifiers,
58 new BasicType( noQualifiers, BasicType::SignedInt )
59 ),
60 /*init*/ NULL
61 );
62 ObjectDecl bool_obj(
63 "__ret_bool",
64 Type::StorageClasses(),
65 LinkageSpec::Cforall,
66 /*bitfieldWidth*/ NULL,
67 new BasicType(noQualifiers, BasicType::Bool),
68 /*init*/ NULL
69 );
70 ObjectDecl voidptr_obj(
71 "__hook",
72 Type::StorageClasses(),
73 LinkageSpec::Cforall,
74 NULL,
75 new PointerType(
76 noQualifiers,
77 new VoidType(
78 noQualifiers
79 ),
80 std::list<Attribute *>{new Attribute("unused")}
81 ),
82 NULL
83 );
84
85 catch_func_t.get_parameters().push_back( index_obj.clone() );
86 catch_func_t.get_parameters().push_back( exception_obj.clone() );
87 match_func_t.get_returnVals().push_back( index_obj.clone() );
88 match_func_t.get_parameters().push_back( exception_obj.clone() );
89 handle_func_t.get_returnVals().push_back( bool_obj.clone() );
90 handle_func_t.get_parameters().push_back( exception_obj.clone() );
91 finally_func_t.get_parameters().push_back( voidptr_obj.clone() );
92
93 init_complete = true;
94 }
95
96 // Buricratic Helpers (Not having to do with the paritular operation.)
97
98 typedef std::list<CatchStmt*> CatchList;
99
100 void split( CatchList& allHandlers, CatchList& terHandlers,
101 CatchList& resHandlers ) {
102 while ( !allHandlers.empty() ) {
103 CatchStmt * stmt = allHandlers.front();
104 allHandlers.pop_front();
105 if (CatchStmt::Terminate == stmt->get_kind()) {
106 terHandlers.push_back(stmt);
107 } else {
108 resHandlers.push_back(stmt);
109 }
110 }
111 }
112
113 void appendDeclStmt( CompoundStmt * block, Declaration * item ) {
114 block->push_back(new DeclStmt(noLabels, item));
115 }
116
117 Expression * nameOf( DeclarationWithType * decl ) {
118 return new VariableExpr( decl );
119 }
120
121 // ThrowStmt Mutation Helpers
122
123 Statement * create_given_throw(
124 const char * throwFunc, ThrowStmt * throwStmt ) {
125 // There is an extra copy here we might be able to remove with
126 // references.
127 // { int NAME = EXPR; throwFunc( &NAME ); }
128 CompoundStmt * result = new CompoundStmt( noLabels );
129 ObjectDecl * local = new ObjectDecl(
130 "__local_exception_copy",
131 Type::StorageClasses(),
132 LinkageSpec::Cforall,
133 NULL,
134 new BasicType( noQualifiers, BasicType::SignedInt ),
135 new SingleInit( throwStmt->get_expr() )
136 );
137 appendDeclStmt( result, local );
138 UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) );
139 call->get_args().push_back( new AddressExpr( nameOf( local ) ) );
140 result->push_back( new ExprStmt( throwStmt->get_labels(), call ) );
141 throwStmt->set_expr( nullptr );
142 delete throwStmt;
143 return result;
144 }
145
146 Statement * create_terminate_throw( ThrowStmt *throwStmt ) {
147 // { int NAME = EXPR; __throw_terminate( &NAME ); }
148 return create_given_throw( "__cfaehm__throw_terminate", throwStmt );
149 }
150
151 Statement * create_terminate_rethrow( ThrowStmt *throwStmt,
152 ObjectDecl *handler_except_decl ) {
153 // { `handler_except_decl` = NULL; __rethrow_terminate(); }
154 assert( nullptr == throwStmt->get_expr() );
155 assert( handler_except_decl );
156
157 CompoundStmt * result = new CompoundStmt( throwStmt->get_labels() );
158 result->push_back( new ExprStmt( noLabels, UntypedExpr::createAssign(
159 nameOf( handler_except_decl ),
160 new ConstantExpr( Constant::null(
161 new PointerType(
162 noQualifiers,
163 handler_except_decl->get_type()->clone()
164 )
165 ) )
166 ) ) );
167 result->push_back( new ExprStmt(
168 noLabels,
169 new UntypedExpr( new NameExpr( "__cfaehm__rethrow_terminate" ) )
170 ) );
171 delete throwStmt;
172 return result;
173 }
174
175 Statement * create_resume_throw( ThrowStmt *throwStmt ) {
176 // __throw_resume( EXPR );
177 return create_given_throw( "__cfaehm__throw_resume", throwStmt );
178 }
179
180 Statement * create_resume_rethrow( ThrowStmt *throwStmt ) {
181 // return false;
182 Statement * result = new ReturnStmt(
183 throwStmt->get_labels(),
184 new ConstantExpr( Constant::from_bool( false ) )
185 );
186 delete throwStmt;
187 return result;
188 }
189
190 // TryStmt Mutation Helpers
191
192 CompoundStmt * take_try_block( TryStmt *tryStmt ) {
193 CompoundStmt * block = tryStmt->get_block();
194 tryStmt->set_block( nullptr );
195 return block;
196 }
197 FunctionDecl * create_try_wrapper( CompoundStmt *body ) {
198
199 return new FunctionDecl( "try", Type::StorageClasses(),
200 LinkageSpec::Cforall, try_func_t.clone(), body );
201 }
202
203 FunctionDecl * create_terminate_catch( CatchList &handlers ) {
204 std::list<CaseStmt *> handler_wrappers;
205
206 FunctionType *func_type = catch_func_t.clone();
207 DeclarationWithType * index_obj = func_type->get_parameters().front();
208 DeclarationWithType * except_obj = func_type->get_parameters().back();
209
210 // Index 1..{number of handlers}
211 int index = 0;
212 CatchList::iterator it = handlers.begin();
213 for ( ; it != handlers.end() ; ++it ) {
214 ++index;
215 CatchStmt * handler = *it;
216
217 // INTEGERconstant Version
218 // case `index`:
219 // {
220 // `handler.decl` {inserted} = { except_obj };
221 // `handler.body`
222 // }
223 // return;
224 CompoundStmt * block = new CompoundStmt( noLabels );
225
226 // Just copy the exception value.
227 // TODO: Or just store an ObjectDecl?
228 ObjectDecl * handler_decl =
229 dynamic_cast<ObjectDecl*>( handler->get_decl() );
230 assert( handler_decl );
231 ObjectDecl * local_except = handler_decl->clone();
232 local_except->set_init(
233 new ListInit({ new SingleInit( nameOf( except_obj ) ) }) );
234#if 0
235 // Virtual Exception Vision
236 // case `index`:
237 // {
238 // `handler.decl` = { (virtual `decl.type`)`except` };
239 // `handler.body`;
240 // }
241 // return;
242
243 // Save a cast copy of the exception (should always succeed).
244 ObjectDecl * local_except = handler->get_decl()->clone();
245 local_except.set_init(
246 new ListInit({ new SingleInit(
247 new VirtualCastExpr( nameOf( except_obj ),
248 local_except->get_type()
249 )
250 ) }) );
251#endif
252 block->push_back( new DeclStmt( noLabels, local_except ) );
253
254 // Add the cleanup attribute.
255 local_except->get_attributes().push_back( new Attribute(
256 "cleanup",
257 { new NameExpr( "__cfaehm__cleanup_terminate" ) }
258 ) );
259
260 // Update variables in the body to point to this local copy.
261 {
262 VarExprReplacer::DeclMap mapping;
263 mapping[ handler_decl ] = local_except;
264 VarExprReplacer mapper( mapping );
265 handler->get_body()->accept( mapper );
266 }
267
268 block->push_back( handler->get_body() );
269 handler->set_body( nullptr );
270
271 std::list<Statement *> caseBody
272 { block, new ReturnStmt( noLabels, nullptr ) };
273 handler_wrappers.push_back( new CaseStmt(
274 noLabels,
275 new ConstantExpr( Constant::from_int( index ) ),
276 caseBody
277 ) );
278 }
279 // TODO: Some sort of meaningful error on default perhaps?
280
281 std::list<Statement*> stmt_handlers;
282 while ( !handler_wrappers.empty() ) {
283 stmt_handlers.push_back( handler_wrappers.front() );
284 handler_wrappers.pop_front();
285 }
286
287 SwitchStmt * handler_lookup = new SwitchStmt(
288 noLabels,
289 nameOf( index_obj ),
290 stmt_handlers
291 );
292 CompoundStmt * body = new CompoundStmt( noLabels );
293 body->push_back( handler_lookup );
294
295 return new FunctionDecl("catch", Type::StorageClasses(),
296 LinkageSpec::Cforall, func_type, body);
297 }
298
299 // Create a single check from a moddified handler.
300 // except_obj is referenced, modded_handler will be freed.
301 CompoundStmt *create_single_matcher(
302 DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
303 CompoundStmt * block = new CompoundStmt( noLabels );
304
305 ObjectDecl * local_except =
306 dynamic_cast<ObjectDecl *>( modded_handler->get_decl() );
307 assert( local_except );
308 block->push_back( new DeclStmt( noLabels, local_except ) );
309#if 0
310 // Virtual Exception Version
311 // {
312 // `modded_handler.decl`
313 // if ( `decl.name = (virtual)`except`
314 // [&& `modded_handler.cond`] ) {
315 // `modded_handler.body`
316 // }
317 // }
318
319 // Check for type match.
320 Expression * cond = UntypedExpr::createAssign( nameOf( local_except ),
321 new VirtualCastExpr( nameOf( except_obj ),
322 local_except->get_type()->clone() ) );
323#endif
324
325 // INTEGERconstant Version
326 // {
327 // `modded_handler.decl` = *`except`
328 // if ( `decl.name` == `modded_handler.cond` ) {
329 // `modded_handler.body`
330 // }
331 // }
332 ConstantExpr * number =
333 dynamic_cast<ConstantExpr*>( modded_handler->get_cond() );
334 assert( number );
335 modded_handler->set_cond( nullptr );
336
337 Expression * cond;
338 {
339 std::list<Expression *> args;
340 args.push_back( number );
341
342 std::list<Expression *> rhs_args;
343 rhs_args.push_back( nameOf( except_obj ) );
344 Expression * rhs = new UntypedExpr(
345 new NameExpr( "*?" ), rhs_args );
346 args.push_back( rhs );
347
348 cond = new UntypedExpr( new NameExpr( "?==?" /*???*/), args );
349 }
350
351 // Add the check on the conditional if it is provided.
352 if ( modded_handler->get_cond() ) {
353 cond = new LogicalExpr( cond, modded_handler->get_cond() );
354 }
355 // Construct the match condition.
356 block->push_back( new IfStmt( noLabels,
357 cond, modded_handler->get_body(), nullptr ) );
358
359 modded_handler->set_decl( nullptr );
360 modded_handler->set_cond( nullptr );
361 modded_handler->set_body( nullptr );
362 delete modded_handler;
363 return block;
364 }
365
366 FunctionDecl * create_terminate_match( CatchList &handlers ) {
367 // int match(exception * except) {
368 // HANDLER WRAPPERS { return `index`; }
369 // }
370
371 CompoundStmt * body = new CompoundStmt( noLabels );
372
373 FunctionType * func_type = match_func_t.clone();
374 DeclarationWithType * except_obj = func_type->get_parameters().back();
375
376 // Index 1..{number of handlers}
377 int index = 0;
378 CatchList::iterator it;
379 for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
380 ++index;
381 CatchStmt * handler = *it;
382
383 // Body should have been taken by create_terminate_catch.
384 assert( nullptr == handler->get_body() );
385
386 // Create new body.
387 handler->set_body( new ReturnStmt( noLabels,
388 new ConstantExpr( Constant::from_int( index ) ) ) );
389
390 // Create the handler.
391 body->push_back( create_single_matcher( except_obj, handler ) );
392 *it = nullptr;
393 }
394
395 body->push_back( new ReturnStmt( noLabels, new ConstantExpr(
396 Constant::from_int( 0 ) ) ) );
397
398 return new FunctionDecl("match", Type::StorageClasses(),
399 LinkageSpec::Cforall, func_type, body);
400 }
401
402 CompoundStmt * create_terminate_caller(
403 FunctionDecl * try_wrapper,
404 FunctionDecl * terminate_catch,
405 FunctionDecl * terminate_match) {
406 // { __cfaehm__try_terminate(`try`, `catch`, `match`); }
407
408 UntypedExpr * caller = new UntypedExpr( new NameExpr(
409 "__cfaehm__try_terminate" ) );
410 std::list<Expression *>& args = caller->get_args();
411 args.push_back( nameOf( try_wrapper ) );
412 args.push_back( nameOf( terminate_catch ) );
413 args.push_back( nameOf( terminate_match ) );
414
415 CompoundStmt * callStmt = new CompoundStmt( noLabels );
416 callStmt->push_back( new ExprStmt( noLabels, caller ) );
417 return callStmt;
418 }
419
420 FunctionDecl * create_resume_handler( CatchList &handlers ) {
421 // bool handle(exception * except) {
422 // HANDLER WRAPPERS { `hander->body`; return true; }
423 // }
424 CompoundStmt * body = new CompoundStmt( noLabels );
425
426 FunctionType * func_type = match_func_t.clone();
427 DeclarationWithType * except_obj = func_type->get_parameters().back();
428
429 CatchList::iterator it;
430 for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
431 CatchStmt * handler = *it;
432
433 // Modifiy body.
434 CompoundStmt * handling_code =
435 dynamic_cast<CompoundStmt*>( handler->get_body() );
436 if ( ! handling_code ) {
437 handling_code = new CompoundStmt( noLabels );
438 handling_code->push_back( handler->get_body() );
439 }
440 handling_code->push_back( new ReturnStmt( noLabels,
441 new ConstantExpr( Constant::from_bool( true ) ) ) );
442 handler->set_body( handling_code );
443
444 // Create the handler.
445 body->push_back( create_single_matcher( except_obj, handler ) );
446 *it = nullptr;
447 }
448
449 body->push_back( new ReturnStmt( noLabels, new ConstantExpr(
450 Constant::from_bool( false ) ) ) );
451
452 return new FunctionDecl("handle", Type::StorageClasses(),
453 LinkageSpec::Cforall, func_type, body);
454 }
455
456 CompoundStmt * create_resume_wrapper(
457 StructDecl * node_decl,
458 Statement * wraps,
459 FunctionDecl * resume_handler ) {
460 CompoundStmt * body = new CompoundStmt( noLabels );
461
462 // struct __try_resume_node __resume_node
463 // __attribute__((cleanup( __cfaehm__try_resume_cleanup )));
464 // ** unwinding of the stack here could cause problems **
465 // ** however I don't think that can happen currently **
466 // __cfaehm__try_resume_setup( &__resume_node, resume_handler );
467
468 std::list< Attribute * > attributes;
469 {
470 std::list< Expression * > attr_params;
471 attr_params.push_back( new NameExpr(
472 "__cfaehm__try_resume_cleanup" ) );
473 attributes.push_back( new Attribute( "cleanup", attr_params ) );
474 }
475
476 ObjectDecl * obj = new ObjectDecl(
477 "__resume_node",
478 Type::StorageClasses(),
479 LinkageSpec::Cforall,
480 nullptr,
481 new StructInstType(
482 Type::Qualifiers(),
483 node_decl
484 ),
485 nullptr,
486 attributes
487 );
488 appendDeclStmt( body, obj );
489
490 UntypedExpr *setup = new UntypedExpr( new NameExpr(
491 "__cfaehm__try_resume_setup" ) );
492 setup->get_args().push_back( new AddressExpr( nameOf( obj ) ) );
493 setup->get_args().push_back( nameOf( resume_handler ) );
494
495 body->push_back( new ExprStmt( noLabels, setup ) );
496
497 body->push_back( wraps );
498 return body;
499 }
500
501 FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ) {
502 // void finally() { <finally code> }
503 FinallyStmt * finally = tryStmt->get_finally();
504 CompoundStmt * body = finally->get_block();
505 finally->set_block( nullptr );
506 delete finally;
507 tryStmt->set_finally( nullptr );
508
509 return new FunctionDecl("finally", Type::StorageClasses(),
510 LinkageSpec::Cforall, finally_func_t.clone(), body);
511 }
512
513 ObjectDecl * create_finally_hook(
514 StructDecl * hook_decl, FunctionDecl * finally_wrapper ) {
515 // struct __cfaehm__cleanup_hook __finally_hook
516 // __attribute__((cleanup( finally_wrapper )));
517
518 // Make Cleanup Attribute.
519 std::list< Attribute * > attributes;
520 {
521 std::list< Expression * > attr_params;
522 attr_params.push_back( nameOf( finally_wrapper ) );
523 attributes.push_back( new Attribute( "cleanup", attr_params ) );
524 }
525
526 return new ObjectDecl(
527 "__finally_hook",
528 Type::StorageClasses(),
529 LinkageSpec::Cforall,
530 nullptr,
531 new StructInstType(
532 noQualifiers,
533 hook_decl
534 ),
535 nullptr,
536 attributes
537 );
538 }
539
540
541 class ExceptionMutatorCore : public WithGuards {
542 enum Context { NoHandler, TerHandler, ResHandler };
543
544 // Also need to handle goto, break & continue.
545 // They need to be cut off in a ResHandler, until we enter another
546 // loop, switch or the goto stays within the function.
547
548 Context cur_context;
549
550 // The current (innermost) termination handler exception declaration.
551 ObjectDecl * handler_except_decl;
552
553 // We might not need this, but a unique base for each try block's
554 // generated functions might be nice.
555 //std::string curFunctionName;
556 //unsigned int try_count = 0;
557
558 StructDecl *node_decl;
559 StructDecl *hook_decl;
560
561 public:
562 ExceptionMutatorCore() :
563 cur_context(NoHandler),
564 handler_except_decl( nullptr ),
565 node_decl( nullptr ), hook_decl( nullptr )
566 {}
567
568 void premutate( CatchStmt *catchStmt );
569 void premutate( StructDecl *structDecl );
570 Statement * postmutate( ThrowStmt *throwStmt );
571 Statement * postmutate( TryStmt *tryStmt );
572 };
573
574 void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
575 // Currently, we make up the declaration, as there isn't one for
576 // integers.
577 ObjectDecl * tmp = new ObjectDecl(
578 "_hidden_local",
579 Type::StorageClasses(),
580 LinkageSpec::Cforall,
581 nullptr,
582 new PointerType(
583 noQualifiers,
584 new BasicType( noQualifiers, BasicType::SignedInt )
585 ),
586 nullptr
587 );
588 catchStmt->set_decl( tmp );
589
590 GuardValue( cur_context );
591 if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
592 cur_context = TerHandler;
593
594 GuardValue( handler_except_decl );
595 handler_except_decl = tmp;
596 //handler_except_decl = catchStmt->get_decl();
597 } else {
598 cur_context = ResHandler;
599 }
600 }
601
602 void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
603 if ( !structDecl->has_body() ) {
604 // Skip children?
605 return;
606 } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) {
607 assert( nullptr == node_decl );
608 node_decl = structDecl;
609 } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) {
610 assert( nullptr == hook_decl );
611 hook_decl = structDecl;
612 }
613 // Later we might get the exception type as well.
614 }
615
616 Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) {
617 // Ignoring throwStmt->get_target() for now.
618 if ( ThrowStmt::Terminate == throwStmt->get_kind() ) {
619 if ( throwStmt->get_expr() ) {
620 return create_terminate_throw( throwStmt );
621 } else if ( TerHandler == cur_context ) {
622 return create_terminate_rethrow(
623 throwStmt, handler_except_decl );
624 } else {
625 assertf(false, "Invalid throw in %s at %i\n",
626 throwStmt->location.filename.c_str(),
627 throwStmt->location.linenumber);
628 return nullptr;
629 }
630 } else {
631 if ( throwStmt->get_expr() ) {
632 return create_resume_throw( throwStmt );
633 } else if ( ResHandler == cur_context ) {
634 return create_resume_rethrow( throwStmt );
635 } else {
636 assertf(false, "Invalid throwResume in %s at %i\n",
637 throwStmt->location.filename.c_str(),
638 throwStmt->location.linenumber);
639 return nullptr;
640 }
641 }
642 }
643
644 Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) {
645 assert( node_decl );
646 assert( hook_decl );
647
648 // Generate a prefix for the function names?
649
650 CompoundStmt * block = new CompoundStmt( noLabels );
651 CompoundStmt * inner = take_try_block( tryStmt );
652
653 if ( tryStmt->get_finally() ) {
654 // Define the helper function.
655 FunctionDecl * finally_block =
656 create_finally_wrapper( tryStmt );
657 appendDeclStmt( block, finally_block );
658 // Create and add the finally cleanup hook.
659 appendDeclStmt( block,
660 create_finally_hook( hook_decl, finally_block ) );
661 }
662
663 CatchList termination_handlers;
664 CatchList resumption_handlers;
665 split( tryStmt->get_catchers(),
666 termination_handlers, resumption_handlers );
667
668 if ( resumption_handlers.size() ) {
669 // Define the helper function.
670 FunctionDecl * resume_handler =
671 create_resume_handler( resumption_handlers );
672 appendDeclStmt( block, resume_handler );
673 // Prepare hooks
674 inner = create_resume_wrapper( node_decl, inner, resume_handler );
675 }
676
677 if ( termination_handlers.size() ) {
678 // Define the three helper functions.
679 FunctionDecl * try_wrapper = create_try_wrapper( inner );
680 appendDeclStmt( block, try_wrapper );
681 FunctionDecl * terminate_catch =
682 create_terminate_catch( termination_handlers );
683 appendDeclStmt( block, terminate_catch );
684 FunctionDecl * terminate_match =
685 create_terminate_match( termination_handlers );
686 appendDeclStmt( block, terminate_match );
687 // Build the call to the try wrapper.
688 inner = create_terminate_caller(
689 try_wrapper, terminate_catch, terminate_match );
690 }
691
692 // Embed the try block.
693 block->push_back( inner );
694
695 return block;
696 }
697
698 void translateEHM( std::list< Declaration *> & translationUnit ) {
699 init_func_types();
700
701 PassVisitor<ExceptionMutatorCore> translator;
702 mutateAll( translationUnit, translator );
703 }
704}
Note: See TracBrowser for help on using the repository browser.