source: src/ControlStruct/ExceptTranslate.cc@ cbbd8fd7

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 cbbd8fd7 was 7119daa, checked in by Andrew Beach <ajbeach@…>, 5 years ago

More clean-up in ExceptTranslate.

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