Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/MultiLevelExit.cpp

    r400b8be r891f707  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Nov  1 13:48:00 2021
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Mar 28  9:42:00 2022
    13 // Update Count     : 34
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Feb  2 23:07:54 2022
     13// Update Count     : 33
    1414//
    1515
     
    4040
    4141        enum Kind {
    42                 ForStmtK, WhileDoStmtK, CompoundStmtK, IfStmtK, CaseClauseK, SwitchStmtK, TryStmtK
     42                ForStmtK, WhileDoStmtK, CompoundStmtK, IfStmtK, CaseStmtK, SwitchStmtK, TryStmtK
    4343        } kind;
    4444
     
    5858        Entry( const IfStmt *stmt, Label breakExit ) :
    5959                stmt( stmt ), firstTarget( breakExit ), secondTarget(), kind( IfStmtK ) {}
    60         Entry( const CaseClause *, const CompoundStmt *stmt, Label fallExit ) :
    61                 stmt( stmt ), firstTarget( fallExit ), secondTarget(), kind( CaseClauseK ) {}
     60        Entry( const CaseStmt *stmt, Label fallExit ) :
     61                stmt( stmt ), firstTarget( fallExit ), secondTarget(), kind( CaseStmtK ) {}
    6262        Entry( const SwitchStmt *stmt, Label breakExit, Label fallDefaultExit ) :
    6363                stmt( stmt ), firstTarget( breakExit ), secondTarget( fallDefaultExit ), kind( SwitchStmtK ) {}
     
    6666
    6767        bool isContTarget() const { return kind <= WhileDoStmtK; }
    68         bool isBreakTarget() const { return kind != CaseClauseK; }
    69         bool isFallTarget() const { return kind == CaseClauseK; }
     68        bool isBreakTarget() const { return kind != CaseStmtK; }
     69        bool isFallTarget() const { return kind == CaseStmtK; }
    7070        bool isFallDefaultTarget() const { return kind == SwitchStmtK; }
    7171
    7272        // These routines set a target as being "used" by a BranchStmt
    7373        Label useContExit() { assert( kind <= WhileDoStmtK ); return useTarget(secondTarget); }
    74         Label useBreakExit() { assert( kind != CaseClauseK ); return useTarget(firstTarget); }
    75         Label useFallExit() { assert( kind == CaseClauseK );  return useTarget(firstTarget); }
     74        Label useBreakExit() { assert( kind != CaseStmtK ); return useTarget(firstTarget); }
     75        Label useFallExit() { assert( kind == CaseStmtK );  return useTarget(firstTarget); }
    7676        Label useFallDefaultExit() { assert( kind == SwitchStmtK ); return useTarget(secondTarget); }
    7777
    7878        // These routines check if a specific label for a statement is used by a BranchStmt
    7979        bool isContUsed() const { assert( kind <= WhileDoStmtK ); return secondTarget.used; }
    80         bool isBreakUsed() const { assert( kind != CaseClauseK ); return firstTarget.used; }
    81         bool isFallUsed() const { assert( kind == CaseClauseK ); return firstTarget.used; }
     80        bool isBreakUsed() const { assert( kind != CaseStmtK ); return firstTarget.used; }
     81        bool isFallUsed() const { assert( kind == CaseStmtK ); return firstTarget.used; }
    8282        bool isFallDefaultUsed() const { assert( kind == SwitchStmtK ); return secondTarget.used; }
    8383        void seenDefault() { fallDefaultValid = false; }
     
    115115        void previsit( const ForStmt * );
    116116        const ForStmt * postvisit( const ForStmt * );
    117         const CaseClause * previsit( const CaseClause * );
     117        const CaseStmt * previsit( const CaseStmt * );
    118118        void previsit( const IfStmt * );
    119119        const IfStmt * postvisit( const IfStmt * );
     
    123123        void previsit( const TryStmt * );
    124124        void postvisit( const TryStmt * );
    125         void previsit( const FinallyClause * );
     125        void previsit( const FinallyStmt * );
    126126
    127127        const Stmt * mutateLoop( const Stmt * body, Entry& );
     
    288288                  auto switchStmt = strict_dynamic_cast< const SwitchStmt * >( targetEntry->stmt );
    289289                  bool foundDefault = false;
    290                   for ( auto caseStmt : switchStmt->cases ) {
     290                  for ( auto subStmt : switchStmt->stmts ) {
     291                          const CaseStmt * caseStmt = subStmt.strict_as<CaseStmt>();
    291292                          if ( caseStmt->isDefault() ) {
    292293                                  foundDefault = true;
     
    364365}
    365366
    366 const CaseClause * MultiLevelExitCore::previsit( const CaseClause * stmt ) {
     367const CaseStmt * MultiLevelExitCore::previsit( const CaseStmt * stmt ) {
    367368        visit_children = false;
    368369
     
    374375
    375376        // The cond may not exist, but if it does update it now.
    376         visitor->maybe_accept( stmt, &CaseClause::cond );
     377        visitor->maybe_accept( stmt, &CaseStmt::cond );
    377378
    378379        // Just save the mutated node for simplicity.
    379         CaseClause * mutStmt = mutate( stmt );
    380 
    381         Label fallLabel = newLabel( "fallThrough", stmt->location );
     380        CaseStmt * mutStmt = mutate( stmt );
     381
     382        Label fallLabel = newLabel( "fallThrough", stmt );
    382383        if ( ! mutStmt->stmts.empty() ) {
    383                 // These should already be in a block.
    384                 auto first = mutStmt->stmts.front().get_and_mutate();
    385                 auto block = strict_dynamic_cast<CompoundStmt *>( first );
    386 
    387384                // Ensure that the stack isn't corrupted by exceptions in fixBlock.
    388385                auto guard = makeFuncGuard(
    389                         [&](){ enclosing_control_structures.emplace_back( mutStmt, block, fallLabel ); },
     386                        [&](){ enclosing_control_structures.emplace_back( mutStmt, fallLabel ); },
    390387                        [this](){ enclosing_control_structures.pop_back(); }
    391388                        );
    392389
     390                // These should already be in a block.
     391                auto block = mutate( mutStmt->stmts.front().strict_as<CompoundStmt>() );
    393392                block->kids = fixBlock( block->kids, true );
    394393
     
    397396                Entry & entry = enclosing_control_structures.back();
    398397                if ( entry.isFallUsed() ) {
    399                         mutStmt->stmts.push_back( labelledNullStmt( block->location, entry.useFallExit() ) );
     398                        mutStmt->stmts.push_back( labelledNullStmt( mutStmt->location, entry.useFallExit() ) );
    400399                }
    401400        }
     
    434433}
    435434
    436 static bool isDefaultCase( const ptr<CaseClause> & caseClause ) {
    437         return caseClause->isDefault();
     435bool isDefaultCase( const ptr<Stmt> & stmt ) {
     436        const CaseStmt * caseStmt = stmt.strict_as<CaseStmt>();
     437        return caseStmt->isDefault();
    438438}
    439439
    440440void MultiLevelExitCore::previsit( const SwitchStmt * stmt ) {
    441441        Label label = newLabel( "switchBreak", stmt );
    442         auto it = find_if( stmt->cases.rbegin(), stmt->cases.rend(), isDefaultCase );
    443 
    444         const CaseClause * defaultCase = it != stmt->cases.rend() ? (*it) : nullptr;
    445         Label defaultLabel = defaultCase ? newLabel( "fallThroughDefault", defaultCase->location ) : Label( stmt->location, "" );
     442        auto it = find_if( stmt->stmts.rbegin(), stmt->stmts.rend(), isDefaultCase );
     443
     444        const CaseStmt * defaultCase = it != stmt->stmts.rend() ? (it)->strict_as<CaseStmt>() : nullptr;
     445        Label defaultLabel = defaultCase ? newLabel( "fallThroughDefault", defaultCase ) : Label( stmt->location, "" );
    446446        enclosing_control_structures.emplace_back( stmt, label, defaultLabel );
    447447        GuardAction( [this]() { enclosing_control_structures.pop_back(); } );
     
    449449        // Collect valid labels for fallthrough. It starts with all labels at this level, then remove as each is seen during
    450450        // traversal.
    451         for ( const CaseClause * caseStmt : stmt->cases ) {
     451        for ( const Stmt * stmt : stmt->stmts ) {
     452                auto * caseStmt = strict_dynamic_cast< const CaseStmt * >( stmt );
    452453                if ( caseStmt->stmts.empty() ) continue;
    453454                auto block = caseStmt->stmts.front().strict_as<CompoundStmt>();
     
    470471                // exit label and break to the last case, create a default case if no cases.
    471472                SwitchStmt * mutStmt = mutate( stmt );
    472                 if ( mutStmt->cases.empty() ) {
    473                         mutStmt->cases.push_back( new CaseClause( mutStmt->location, nullptr, {} ) );
    474                 }
    475 
    476                 auto caseStmt = mutStmt->cases.back().get();
     473                if ( mutStmt->stmts.empty() ) {
     474                        mutStmt->stmts.push_back( new CaseStmt( mutStmt->location, nullptr, {} ) );
     475                }
     476
     477                auto caseStmt = mutStmt->stmts.back().strict_as<CaseStmt>();
    477478                auto mutCase = mutate( caseStmt );
    478                 mutStmt->cases.back() = mutCase;
     479                mutStmt->stmts.back() = mutCase;
    479480
    480481                Label label( mutCase->location, "breakLabel" );
     
    513514}
    514515
    515 void MultiLevelExitCore::previsit( const FinallyClause * ) {
     516void MultiLevelExitCore::previsit( const FinallyStmt * ) {
    516517        GuardAction([this, old = move( enclosing_control_structures)](){ enclosing_control_structures = move(old); });
    517518        enclosing_control_structures = vector<Entry>();
Note: See TracChangeset for help on using the changeset viewer.