source: src/ControlStruct/ExceptTranslate.cc@ 016b1eb

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 016b1eb was b2de2e0, checked in by Andrew Beach <ajbeach@…>, 5 years ago

Improved the check of the catch[Resume] exception declaration.

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