- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/MultiLevelExit.cpp
r553f032f r4a40fca7 10 10 // Created On : Mon Nov 1 13:48:00 2021 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Sep 8 17:04:00 202313 // Update Count : 3 612 // Last Modified On : Wed Sep 6 12:00:00 2023 13 // Update Count : 35 14 14 // 15 15 … … 27 27 28 28 namespace { 29 30 /// The return context is used to remember if returns are allowed and if31 /// not, why not. It is the nearest local control flow blocking construct.32 enum ReturnContext {33 MayReturn,34 InTryWithHandler,35 InResumeHandler,36 InTerminateHandler,37 InFinally,38 };39 29 40 30 class Entry { … … 136 126 void previsit( const TryStmt * ); 137 127 void postvisit( const TryStmt * ); 138 void previsit( const CatchClause * );139 128 void previsit( const FinallyClause * ); 140 129 … … 145 134 vector<Entry> enclosing_control_structures; 146 135 Label break_label; 147 ReturnContext ret_context;136 bool inFinally; 148 137 149 138 template<typename LoopNode> … … 155 144 const list<ptr<Stmt>> & kids, bool caseClause ); 156 145 157 void enterSealedContext( ReturnContext );158 159 146 template<typename UnaryPredicate> 160 147 auto findEnclosingControlStructure( UnaryPredicate pred ) { … … 170 157 MultiLevelExitCore::MultiLevelExitCore( const LabelToStmt & lt ) : 171 158 target_table( lt ), break_label( CodeLocation(), "" ), 172 ret_context( ReturnContext::MayReturn)159 inFinally( false ) 173 160 {} 174 161 … … 501 488 502 489 void MultiLevelExitCore::previsit( const ReturnStmt * stmt ) { 503 char const * context; 504 switch ( ret_context ) { 505 case ReturnContext::MayReturn: 506 return; 507 case ReturnContext::InTryWithHandler: 508 context = "try statement with a catch clause"; 509 break; 510 case ReturnContext::InResumeHandler: 511 context = "catchResume clause"; 512 break; 513 case ReturnContext::InTerminateHandler: 514 context = "catch clause"; 515 break; 516 case ReturnContext::InFinally: 517 context = "finally clause"; 518 break; 519 default: 520 assert(0); 521 } 522 SemanticError( stmt->location, toString( "'return' may not appear in a ", context ) ); 490 if ( inFinally ) { 491 SemanticError( stmt->location, "'return' may not appear in a finally clause" ); 492 } 523 493 } 524 494 … … 530 500 GuardAction([this](){ enclosing_control_structures.pop_back(); } ); 531 501 } 532 533 // Try statements/try blocks are only sealed with a termination handler.534 for ( auto clause : stmt->handlers ) {535 if ( ast::Terminate == clause->kind ) {536 return enterSealedContext( ReturnContext::InTryWithHandler );537 }538 }539 502 } 540 503 … … 549 512 } 550 513 551 void MultiLevelExitCore::previsit( const CatchClause * clause ) {552 ReturnContext context = ( ast::Terminate == clause->kind )553 ? ReturnContext::InTerminateHandler : ReturnContext::InResumeHandler;554 enterSealedContext( context );555 }556 557 514 void MultiLevelExitCore::previsit( const FinallyClause * ) { 558 enterSealedContext( ReturnContext::InFinally ); 515 GuardAction([this, old = std::move( enclosing_control_structures)](){ enclosing_control_structures = std::move(old); }); 516 enclosing_control_structures = vector<Entry>(); 517 GuardValue( inFinally ) = true; 559 518 } 560 519 … … 658 617 } 659 618 660 void MultiLevelExitCore::enterSealedContext( ReturnContext enter_context ) {661 GuardAction([this, old = std::move(enclosing_control_structures)](){ enclosing_control_structures = std::move(old); });662 enclosing_control_structures = vector<Entry>();663 GuardValue( ret_context ) = enter_context;664 }665 666 619 } // namespace 667 620
Note: See TracChangeset
for help on using the changeset viewer.