Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/MultiLevelExit.cpp

    r553f032f r4a40fca7  
    1010// Created On       : Mon Nov  1 13:48:00 2021
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Sep  8 17:04:00 2023
    13 // Update Count     : 36
     12// Last Modified On : Wed Sep  6 12:00:00 2023
     13// Update Count     : 35
    1414//
    1515
     
    2727
    2828namespace {
    29 
    30 /// The return context is used to remember if returns are allowed and if
    31 /// 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 };
    3929
    4030class Entry {
     
    136126        void previsit( const TryStmt * );
    137127        void postvisit( const TryStmt * );
    138         void previsit( const CatchClause * );
    139128        void previsit( const FinallyClause * );
    140129
     
    145134        vector<Entry> enclosing_control_structures;
    146135        Label break_label;
    147         ReturnContext ret_context;
     136        bool inFinally;
    148137
    149138        template<typename LoopNode>
     
    155144                const list<ptr<Stmt>> & kids, bool caseClause );
    156145
    157         void enterSealedContext( ReturnContext );
    158 
    159146        template<typename UnaryPredicate>
    160147        auto findEnclosingControlStructure( UnaryPredicate pred ) {
     
    170157MultiLevelExitCore::MultiLevelExitCore( const LabelToStmt & lt ) :
    171158        target_table( lt ), break_label( CodeLocation(), "" ),
    172         ret_context( ReturnContext::MayReturn )
     159        inFinally( false )
    173160{}
    174161
     
    501488
    502489void 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        }
    523493}
    524494
     
    530500                GuardAction([this](){ enclosing_control_structures.pop_back(); } );
    531501        }
    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         }
    539502}
    540503
     
    549512}
    550513
    551 void MultiLevelExitCore::previsit( const CatchClause * clause ) {
    552         ReturnContext context = ( ast::Terminate == clause->kind )
    553                 ? ReturnContext::InTerminateHandler : ReturnContext::InResumeHandler;
    554         enterSealedContext( context );
    555 }
    556 
    557514void 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;
    559518}
    560519
     
    658617}
    659618
    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 
    666619} // namespace
    667620
Note: See TracChangeset for help on using the changeset viewer.