source: src/ControlStruct/ExceptTranslate.cc@ e9145a3

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 e9145a3 was e9145a3, checked in by Andrew Beach <ajbeach@…>, 8 years ago

Updated exception tests to exception structures. Should be re-orginized still.

  • Property mode set to 100644
File size: 22.1 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 Aug 17 15:48:00 2017
13// Update Count : 8
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 // TODO: Stoping the function from generating the 'return variable'
390 // entirely would be cleaner. But this does get ride of warnings.
391 CompoundStmt * set_and_ret(DeclarationWithType * var, Expression * val) {
392 CompoundStmt * block = new CompoundStmt( noLabels );
393 block->push_back( new ExprStmt( noLabels,
394 UntypedExpr::createAssign( new VariableExpr( var ), val )
395 ) );
396 block->push_back( new ReturnStmt( noLabels,
397 new VariableExpr( var )
398 ) );
399 return block;
400 }
401
402 FunctionDecl * ExceptionMutatorCore::create_terminate_match(
403 CatchList &handlers ) {
404 // int match(exception * except) {
405 // HANDLER WRAPPERS { return `index`; }
406 // }
407
408 CompoundStmt * body = new CompoundStmt( noLabels );
409
410 FunctionType * func_type = match_func_t.clone();
411 DeclarationWithType * except_obj = func_type->get_parameters().back();
412 DeclarationWithType * index_obj = func_type->get_returnVals().front();
413
414 // Index 1..{number of handlers}
415 int index = 0;
416 CatchList::iterator it;
417 for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
418 ++index;
419 CatchStmt * handler = *it;
420
421 // Body should have been taken by create_terminate_catch.
422 assert( nullptr == handler->get_body() );
423
424 // Create new body.
425 handler->set_body( set_and_ret( index_obj,
426 new ConstantExpr( Constant::from_int( index ) ) ) );
427
428 // Create the handler.
429 body->push_back( create_single_matcher( except_obj, handler ) );
430 *it = nullptr;
431 }
432
433 body->push_back( set_and_ret( index_obj,
434 new ConstantExpr( Constant::from_int( 0 ) ) ) );
435
436 return new FunctionDecl("match", Type::StorageClasses(),
437 LinkageSpec::Cforall, func_type, body);
438 }
439
440 CompoundStmt * ExceptionMutatorCore::create_terminate_caller(
441 FunctionDecl * try_wrapper,
442 FunctionDecl * terminate_catch,
443 FunctionDecl * terminate_match ) {
444 // { __cfaehm__try_terminate(`try`, `catch`, `match`); }
445
446 UntypedExpr * caller = new UntypedExpr( new NameExpr(
447 "__cfaehm__try_terminate" ) );
448 std::list<Expression *>& args = caller->get_args();
449 args.push_back( nameOf( try_wrapper ) );
450 args.push_back( nameOf( terminate_catch ) );
451 args.push_back( nameOf( terminate_match ) );
452
453 CompoundStmt * callStmt = new CompoundStmt( noLabels );
454 callStmt->push_back( new ExprStmt( noLabels, caller ) );
455 return callStmt;
456 }
457
458 FunctionDecl * ExceptionMutatorCore::create_resume_handler(
459 CatchList &handlers ) {
460 // bool handle(exception * except) {
461 // HANDLER WRAPPERS { `hander->body`; return true; }
462 // }
463 CompoundStmt * body = new CompoundStmt( noLabels );
464
465 FunctionType * func_type = handle_func_t.clone();
466 DeclarationWithType * except_obj = func_type->get_parameters().back();
467 DeclarationWithType * bool_obj = func_type->get_returnVals().front();
468
469 CatchList::iterator it;
470 for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
471 CatchStmt * handler = *it;
472
473 // Modifiy body.
474 CompoundStmt * handling_code =
475 dynamic_cast<CompoundStmt*>( handler->get_body() );
476 if ( ! handling_code ) {
477 handling_code = new CompoundStmt( noLabels );
478 handling_code->push_back( handler->get_body() );
479 }
480 handling_code->push_back( set_and_ret( bool_obj,
481 new ConstantExpr( Constant::from_bool( true ) ) ) );
482 handler->set_body( handling_code );
483
484 // Create the handler.
485 body->push_back( create_single_matcher( except_obj, handler ) );
486 *it = nullptr;
487 }
488
489 body->push_back( set_and_ret( bool_obj,
490 new ConstantExpr( Constant::from_bool( false ) ) ) );
491
492 return new FunctionDecl("handle", Type::StorageClasses(),
493 LinkageSpec::Cforall, func_type, body);
494 }
495
496 CompoundStmt * ExceptionMutatorCore::create_resume_wrapper(
497 Statement * wraps,
498 FunctionDecl * resume_handler ) {
499 CompoundStmt * body = new CompoundStmt( noLabels );
500
501 // struct __try_resume_node __resume_node
502 // __attribute__((cleanup( __cfaehm__try_resume_cleanup )));
503 // ** unwinding of the stack here could cause problems **
504 // ** however I don't think that can happen currently **
505 // __cfaehm__try_resume_setup( &__resume_node, resume_handler );
506
507 std::list< Attribute * > attributes;
508 {
509 std::list< Expression * > attr_params;
510 attr_params.push_back( new NameExpr(
511 "__cfaehm__try_resume_cleanup" ) );
512 attributes.push_back( new Attribute( "cleanup", attr_params ) );
513 }
514
515 ObjectDecl * obj = new ObjectDecl(
516 "__resume_node",
517 Type::StorageClasses(),
518 LinkageSpec::Cforall,
519 nullptr,
520 new StructInstType(
521 Type::Qualifiers(),
522 node_decl
523 ),
524 nullptr,
525 attributes
526 );
527 appendDeclStmt( body, obj );
528
529 UntypedExpr *setup = new UntypedExpr( new NameExpr(
530 "__cfaehm__try_resume_setup" ) );
531 setup->get_args().push_back( new AddressExpr( nameOf( obj ) ) );
532 setup->get_args().push_back( nameOf( resume_handler ) );
533
534 body->push_back( new ExprStmt( noLabels, setup ) );
535
536 body->push_back( wraps );
537 return body;
538 }
539
540 FunctionDecl * ExceptionMutatorCore::create_finally_wrapper(
541 TryStmt * tryStmt ) {
542 // void finally() { <finally code> }
543 FinallyStmt * finally = tryStmt->get_finally();
544 CompoundStmt * body = finally->get_block();
545 finally->set_block( nullptr );
546 delete finally;
547 tryStmt->set_finally( nullptr );
548
549 return new FunctionDecl("finally", Type::StorageClasses(),
550 LinkageSpec::Cforall, finally_func_t.clone(), body);
551 }
552
553 ObjectDecl * ExceptionMutatorCore::create_finally_hook(
554 FunctionDecl * finally_wrapper ) {
555 // struct __cfaehm__cleanup_hook __finally_hook
556 // __attribute__((cleanup( finally_wrapper )));
557
558 // Make Cleanup Attribute.
559 std::list< Attribute * > attributes;
560 {
561 std::list< Expression * > attr_params;
562 attr_params.push_back( nameOf( finally_wrapper ) );
563 attributes.push_back( new Attribute( "cleanup", attr_params ) );
564 }
565
566 return new ObjectDecl(
567 "__finally_hook",
568 Type::StorageClasses(),
569 LinkageSpec::Cforall,
570 nullptr,
571 new StructInstType(
572 noQualifiers,
573 hook_decl
574 ),
575 nullptr,
576 attributes
577 );
578 }
579
580 // Visiting/Mutating Functions
581 void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
582 // Validate the Statement's form.
583 ObjectDecl * decl =
584 dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
585 if ( decl && true /* check decl->get_type() */ ) {
586 // Pass.
587 } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
588 throw SemanticError("catch must have exception type");
589 } else {
590 throw SemanticError("catchResume must have exception type");
591 }
592
593 // Track the handler context.
594 GuardValue( cur_context );
595 if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
596 cur_context = TerHandler;
597
598 GuardValue( handler_except_decl );
599 handler_except_decl = decl;
600 } else {
601 cur_context = ResHandler;
602 }
603 }
604
605 void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
606 if ( !structDecl->has_body() ) {
607 // Skip children?
608 return;
609 } else if ( structDecl->get_name() == "__cfaehm__base_exception_t" ) {
610 assert( nullptr == except_decl );
611 except_decl = structDecl;
612 init_func_types();
613 } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) {
614 assert( nullptr == node_decl );
615 node_decl = structDecl;
616 } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) {
617 assert( nullptr == hook_decl );
618 hook_decl = structDecl;
619 }
620 // Later we might get the exception type as well.
621 }
622
623 Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) {
624 assert( except_decl );
625
626 // Ignoring throwStmt->get_target() for now.
627 if ( ThrowStmt::Terminate == throwStmt->get_kind() ) {
628 if ( throwStmt->get_expr() ) {
629 return create_terminate_throw( throwStmt );
630 } else if ( TerHandler == cur_context ) {
631 return create_terminate_rethrow( throwStmt );
632 } else {
633 assertf(false, "Invalid throw in %s at %i\n",
634 throwStmt->location.filename.c_str(),
635 throwStmt->location.linenumber);
636 return nullptr;
637 }
638 } else {
639 if ( throwStmt->get_expr() ) {
640 return create_resume_throw( throwStmt );
641 } else if ( ResHandler == cur_context ) {
642 return create_resume_rethrow( throwStmt );
643 } else {
644 assertf(false, "Invalid throwResume in %s at %i\n",
645 throwStmt->location.filename.c_str(),
646 throwStmt->location.linenumber);
647 return nullptr;
648 }
649 }
650 }
651
652 Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) {
653 assert( except_decl );
654 assert( node_decl );
655 assert( hook_decl );
656
657 // Generate a prefix for the function names?
658
659 CompoundStmt * block = new CompoundStmt( noLabels );
660 CompoundStmt * inner = take_try_block( tryStmt );
661
662 if ( tryStmt->get_finally() ) {
663 // Define the helper function.
664 FunctionDecl * finally_block =
665 create_finally_wrapper( tryStmt );
666 appendDeclStmt( block, finally_block );
667 // Create and add the finally cleanup hook.
668 appendDeclStmt( block, create_finally_hook( finally_block ) );
669 }
670
671 CatchList termination_handlers;
672 CatchList resumption_handlers;
673 split( tryStmt->get_catchers(),
674 termination_handlers, resumption_handlers );
675
676 if ( resumption_handlers.size() ) {
677 // Define the helper function.
678 FunctionDecl * resume_handler =
679 create_resume_handler( resumption_handlers );
680 appendDeclStmt( block, resume_handler );
681 // Prepare hooks
682 inner = create_resume_wrapper( inner, resume_handler );
683 }
684
685 if ( termination_handlers.size() ) {
686 // Define the three helper functions.
687 FunctionDecl * try_wrapper = create_try_wrapper( inner );
688 appendDeclStmt( block, try_wrapper );
689 FunctionDecl * terminate_catch =
690 create_terminate_catch( termination_handlers );
691 appendDeclStmt( block, terminate_catch );
692 FunctionDecl * terminate_match =
693 create_terminate_match( termination_handlers );
694 appendDeclStmt( block, terminate_match );
695 // Build the call to the try wrapper.
696 inner = create_terminate_caller(
697 try_wrapper, terminate_catch, terminate_match );
698 }
699
700 // Embed the try block.
701 block->push_back( inner );
702
703 return block;
704 }
705
706 void translateEHM( std::list< Declaration *> & translationUnit ) {
707 PassVisitor<ExceptionMutatorCore> translator;
708 mutateAll( translationUnit, translator );
709 }
710}
Note: See TracBrowser for help on using the repository browser.