source: src/ControlStruct/ExceptTranslate.cc@ 95cb63b

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 95cb63b was 66ba544, checked in by Andrew Beach <ajbeach@…>, 5 years ago

Dead code elimination in the try block translation.

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