Changeset 0a6d2045
- Timestamp:
- Dec 20, 2023, 12:04:33 PM (11 months ago)
- Branches:
- master
- Children:
- 523e300
- Parents:
- 9fba8e6
- Files:
-
- 2 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/ExceptTranslate.cpp
r9fba8e6 r0a6d2045 151 151 const ast::DeclWithType * except_obj, ast::CatchClause * modded_handler ); 152 152 ast::FunctionDecl * create_terminate_match( CatchList &handlers ); 153 ast::CompoundStmt * create_terminate_caller( CodeLocation loc, ast::FunctionDecl * try_wrapper, 154 ast::FunctionDecl * terminate_catch, ast::FunctionDecl * terminate_match ); 153 ast::CompoundStmt * create_terminate_caller( const CodeLocation & location, 154 ast::FunctionDecl * try_wrapper, ast::FunctionDecl * terminate_match, 155 CatchList & terminate_handlers ); 155 156 ast::FunctionDecl * create_resume_handler( CatchList &handlers ); 156 157 ast::CompoundStmt * create_resume_wrapper( … … 264 265 // `handler.body`; 265 266 // } 266 // return;267 // break; 267 268 const CodeLocation & location = clause->location; 268 269 … … 295 296 body, 296 297 } ), 297 new ast::ReturnStmt( location, nullptr ), 298 new ast::BranchStmt( location, ast::BranchStmt::Break, 299 ast::Label( location ) ), 298 300 } 299 301 ); … … 391 393 // Index 1..{number of handlers} 392 394 int index = 0; 393 CatchList::iterator it; 394 for ( it = handlers.begin() ; it != handlers.end() ; ++it ) { 395 for ( ast::CatchClause * handler : handlers ) { 395 396 ++index; 396 ast::CatchClause * handler = *it; 397 398 // Body should have been taken by create_terminate_catch. 399 // xxx - just ignore it? 400 // assert( nullptr == handler->get_body() ); 401 402 // Create new body. 403 handler->body = new ast::ReturnStmt( handler->location, 397 398 ast::ptr<ast::Stmt> other_body = new ast::ReturnStmt( handler->location, 404 399 ast::ConstantExpr::from_int( handler->location, index ) ); 405 406 // Create the handler. 400 handler->body.swap( other_body ); 401 407 402 body->push_back( create_single_matcher( except_obj, handler ) ); 408 *it = nullptr; 403 404 handler->body.swap( other_body ); 409 405 } 410 406 … … 425 421 426 422 ast::CompoundStmt * TryMutatorCore::create_terminate_caller( 427 CodeLocationloc,423 const CodeLocation & loc, 428 424 ast::FunctionDecl * try_wrapper, 429 ast::FunctionDecl * terminate_ catch,430 ast::FunctionDecl * terminate_match) {425 ast::FunctionDecl * terminate_match, 426 CatchList & terminate_handlers ) { 431 427 // { 432 428 // int __handler_index = __cfaehm_try_terminate(`try`, `match`); … … 447 443 ); 448 444 445 ast::ObjectDecl * except = make_exception_object( loc ); 446 except->init = new ast::SingleInit( loc, 447 new ast::UntypedExpr( loc, 448 new ast::NameExpr( loc, "__cfaehm_get_current_termination" ) 449 ) 450 ); 451 452 std::vector<ast::ptr<ast::CaseClause>> cases; 453 for ( auto const & [index, handler] : enumerate( terminate_handlers ) ) { 454 cases.emplace_back( 455 create_terminate_catch_case( except, index + 1, handler ) ); 456 } 457 auto switch_stmt = new ast::SwitchStmt( loc, 458 new ast::VariableExpr( loc, index ), std::move( cases ) ); 459 449 460 return new ast::CompoundStmt( loc, { 450 461 new ast::DeclStmt( loc, index ), 451 462 new ast::IfStmt( loc, 452 463 new ast::VariableExpr( loc, index ), 453 new ast::ExprStmt( loc, 454 new ast::UntypedExpr( loc, 455 new ast::VariableExpr( loc, terminate_catch ), 456 { 457 new ast::VariableExpr( loc, index ), 458 new ast::UntypedExpr( loc, 459 new ast::NameExpr( loc, "__cfaehm_get_current_termination" ) 460 ), 461 } 462 ) 463 ) 464 new ast::CompoundStmt( loc, { 465 new ast::DeclStmt( loc, except ), 466 switch_stmt, 467 } ) 464 468 ), 465 469 } ); … … 663 667 664 668 if ( termination_handlers.size() ) { 665 // Define the t hreehelper functions.669 // Define the two helper functions. 666 670 ast::FunctionDecl * try_wrapper = create_try_wrapper( inner ); 667 671 appendDeclStmt( block, try_wrapper ); 668 ast::FunctionDecl * terminate_catch =669 create_terminate_catch( termination_handlers );670 appendDeclStmt( block, terminate_catch );671 672 ast::FunctionDecl * terminate_match = 672 673 create_terminate_match( termination_handlers ); … … 674 675 // Build the call to the try wrapper. 675 676 inner = create_terminate_caller(inner->location, 676 try_wrapper, terminate_ catch, terminate_match);677 try_wrapper, terminate_match, termination_handlers ); 677 678 } 678 679 -
src/ControlStruct/MultiLevelExit.cpp
r9fba8e6 r0a6d2045 35 35 InTryWithHandler, 36 36 InResumeHandler, 37 InTerminateHandler,38 37 InFinally, 39 38 }; … … 512 511 context = "catchResume clause"; 513 512 break; 514 case ReturnContext::InTerminateHandler:515 context = "catch clause";516 break;517 513 case ReturnContext::InFinally: 518 514 context = "finally clause"; … … 524 520 } 525 521 522 bool hasTerminate( const TryStmt * stmt ) { 523 for ( auto clause : stmt->handlers ) { 524 if ( ast::Terminate == clause->kind ) return true; 525 } 526 return false; 527 } 528 526 529 void MultiLevelExitCore::previsit( const TryStmt * stmt ) { 530 visit_children = false; 531 527 532 bool isLabeled = ! stmt->labels.empty(); 528 533 if ( isLabeled ) { … … 533 538 534 539 // Try statements/try blocks are only sealed with a termination handler. 535 for ( auto clause : stmt->handlers ) { 536 if ( ast::Terminate == clause->kind ) { 537 return enterSealedContext( ReturnContext::InTryWithHandler ); 538 } 539 } 540 if ( hasTerminate( stmt ) ) { 541 // This is just enterSealedContext except scoped to the block. 542 // And that is because the state must change for a single field. 543 ValueGuard< ReturnContext > guard0( ret_context ); 544 ret_context = ReturnContext::InTryWithHandler; 545 auto guard = makeFuncGuard( [](){}, [this, old = std::move(enclosing_control_structures)](){ enclosing_control_structures = std::move(old); }); 546 enclosing_control_structures = vector<Entry>(); 547 visitor->maybe_accept( stmt, &TryStmt::body ); 548 } else { 549 visitor->maybe_accept( stmt, &TryStmt::body ); 550 } 551 552 visitor->maybe_accept( stmt, &TryStmt::handlers ); 553 visitor->maybe_accept( stmt, &TryStmt::finally ); 540 554 } 541 555 … … 551 565 552 566 void MultiLevelExitCore::previsit( const CatchClause * clause ) { 553 ReturnContext context = ( ast::Terminate == clause->kind )554 ? ReturnContext::InTerminateHandler : ReturnContext::InResumeHandler;555 enterSealedContext( context );567 if ( ast::Resume == clause->kind ) { 568 enterSealedContext( ReturnContext::InResumeHandler ); 569 } 556 570 } 557 571 -
tests/exceptions/.expect/try-ctrl-flow.txt
r9fba8e6 r0a6d2045 15 15 exceptions/try-ctrl-flow.cfa:148:1 error: "break" outside a loop, "switch", or labelled block 16 16 exceptions/try-ctrl-flow.cfa:159:1 error: "return" may not appear in a try statement with a catch clause 17 exceptions/try-ctrl-flow.cfa:187:1 error: "return" may not appear in a catch clause 18 exceptions/try-ctrl-flow.cfa:195:1 error: "return" may not appear in a catchResume clause 17 exceptions/try-ctrl-flow.cfa:187:1 error: "return" may not appear in a catchResume clause -
tests/exceptions/try-ctrl-flow.cfa
r9fba8e6 r0a6d2045 181 181 } 182 182 183 void return_in_catch() {184 try {185 ;186 } catch (nil_exception *) {187 return;188 }189 }190 191 183 void return_in_catchResume() { 192 184 try {
Note: See TracChangeset
for help on using the changeset viewer.