source: src/ControlStruct/ExceptTranslate.cc@ ea6332d

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 ea6332d was d180746, checked in by Thierry Delisle <tdelisle@…>, 8 years ago

Big header cleaning pass - commit 2

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