Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/MultiLevelExit.cpp

    r0577df2 rf75e25b  
    1818#include "AST/Pass.hpp"
    1919#include "AST/Stmt.hpp"
    20 #include "Common/CodeLocationTools.hpp"
    2120#include "LabelGeneratorNew.hpp"
    2221
     
    149148};
    150149
    151 NullStmt * labelledNullStmt( const CodeLocation & cl, const Label & label ) {
     150NullStmt * labelledNullStmt(
     151        const CodeLocation & cl, const Label & label ) {
    152152        return new NullStmt( cl, vector<Label>{ label } );
    153153}
     
    163163
    164164const CompoundStmt * MultiLevelExitCore::previsit(
    165                 const CompoundStmt * stmt ) {
     165        const CompoundStmt * stmt ) {
    166166        visit_children = false;
    167167
     
    188188}
    189189
    190 size_t getUnusedIndex( const Stmt * stmt, const Label & originalTarget ) {
     190size_t getUnusedIndex(
     191        const Stmt * stmt, const Label & originalTarget ) {
    191192        const size_t size = stmt->labels.size();
    192193
     
    208209}
    209210
    210 const Stmt * addUnused( const Stmt * stmt, const Label & originalTarget ) {
     211const Stmt * addUnused(
     212        const Stmt * stmt, const Label & originalTarget ) {
    211213        size_t i = getUnusedIndex( stmt, originalTarget );
    212214        if ( i == stmt->labels.size() ) {
     
    226228        // Labels on different stmts require different approaches to access
    227229        switch ( stmt->kind ) {
    228         case BranchStmt::Goto:
     230          case BranchStmt::Goto:
    229231                return stmt;
    230         case BranchStmt::Continue:
    231         case BranchStmt::Break: {
    232                 bool isContinue = stmt->kind == BranchStmt::Continue;
    233                 // Handle unlabeled break and continue.
    234                 if ( stmt->target.empty() ) {
    235                         if ( isContinue ) {
    236                                 targetEntry = findEnclosingControlStructure( isContinueTarget );
    237                         } else {
    238                                 if ( enclosing_control_structures.empty() ) {
     232          case BranchStmt::Continue:
     233          case BranchStmt::Break: {
     234                  bool isContinue = stmt->kind == BranchStmt::Continue;
     235                  // Handle unlabeled break and continue.
     236                  if ( stmt->target.empty() ) {
     237                          if ( isContinue ) {
     238                                  targetEntry = findEnclosingControlStructure( isContinueTarget );
     239                          } else {
     240                                  if ( enclosing_control_structures.empty() ) {
    239241                                          SemanticError( stmt->location,
    240242                                                                         "'break' outside a loop, 'switch', or labelled block" );
    241                                 }
    242                                 targetEntry = findEnclosingControlStructure( isBreakTarget );
    243                         }
    244                         // Handle labeled break and continue.
    245                 } else {
    246                         // Lookup label in table to find attached control structure.
    247                         targetEntry = findEnclosingControlStructure(
    248                                 [ targetStmt = target_table.at(stmt->target) ](auto entry){
     243                                  }
     244                                  targetEntry = findEnclosingControlStructure( isBreakTarget );
     245                          }
     246                          // Handle labeled break and continue.
     247                  } else {
     248                          // Lookup label in table to find attached control structure.
     249                          targetEntry = findEnclosingControlStructure(
     250                                  [ targetStmt = target_table.at(stmt->target) ](auto entry){
    249251                                          return entry.stmt == targetStmt;
    250                                 } );
    251                 }
    252                 // Ensure that selected target is valid.
    253                 if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && ! isContinueTarget( *targetEntry ) ) ) {
    254                         SemanticError( stmt->location, toString( (isContinue ? "'continue'" : "'break'"),
     252                                  } );
     253                  }
     254                  // Ensure that selected target is valid.
     255                  if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && ! isContinueTarget( *targetEntry ) ) ) {
     256                          SemanticError( stmt->location, toString( (isContinue ? "'continue'" : "'break'"),
    255257                                                        " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "),
    256258                                                        stmt->originalTarget ) );
    257                 }
    258                 break;
    259         }
    260         // handle fallthrough in case/switch stmts
    261         case BranchStmt::FallThrough: {
    262                 targetEntry = findEnclosingControlStructure( isFallthroughTarget );
    263                 // Check that target is valid.
    264                 if ( targetEntry == enclosing_control_structures.rend() ) {
    265                         SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
    266                 }
    267                 if ( ! stmt->target.empty() ) {
    268                         // Labelled fallthrough: target must be a valid fallthough label.
    269                         if ( ! fallthrough_labels.count( stmt->target ) ) {
    270                                 SemanticError( stmt->location, toString( "'fallthrough' target must be a later case statement: ",
     259                  }
     260                  break;
     261          }
     262          // handle fallthrough in case/switch stmts
     263          case BranchStmt::FallThrough: {
     264                  targetEntry = findEnclosingControlStructure( isFallthroughTarget );
     265                  // Check that target is valid.
     266                  if ( targetEntry == enclosing_control_structures.rend() ) {
     267                          SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
     268                  }
     269                  if ( ! stmt->target.empty() ) {
     270                          // Labelled fallthrough: target must be a valid fallthough label.
     271                          if ( ! fallthrough_labels.count( stmt->target ) ) {
     272                                  SemanticError( stmt->location, toString( "'fallthrough' target must be a later case statement: ",
    271273                                                                                                                   stmt->originalTarget ) );
    272                         }
    273                         return new BranchStmt( stmt->location, BranchStmt::Goto, stmt->originalTarget );
    274                 }
    275                 break;
    276         }
    277         case BranchStmt::FallThroughDefault: {
    278                 targetEntry = findEnclosingControlStructure( isFallthroughDefaultTarget );
    279 
    280                 // Check if in switch or choose statement.
    281                 if ( targetEntry == enclosing_control_structures.rend() ) {
    282                         SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
    283                 }
    284 
    285                 // Check if switch or choose has default clause.
    286                 auto switchStmt = strict_dynamic_cast< const SwitchStmt * >( targetEntry->stmt );
    287                 bool foundDefault = false;
    288                 for ( auto caseStmt : switchStmt->cases ) {
    289                         if ( caseStmt->isDefault() ) {
    290                                 foundDefault = true;
    291                                 break;
    292                         }
    293                 }
    294                 if ( ! foundDefault ) {
    295                         SemanticError( stmt->location, "'fallthrough default' must be enclosed in a 'switch' or 'choose'"
    296                                                   "control structure with a 'default' clause" );
    297                 }
    298                 break;
    299         }
    300         default:
     274                          }
     275                          return new BranchStmt( stmt->location, BranchStmt::Goto, stmt->originalTarget );
     276                  }
     277                  break;
     278          }
     279          case BranchStmt::FallThroughDefault: {
     280                  targetEntry = findEnclosingControlStructure( isFallthroughDefaultTarget );
     281
     282                  // Check if in switch or choose statement.
     283                  if ( targetEntry == enclosing_control_structures.rend() ) {
     284                          SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
     285                  }
     286
     287                  // Check if switch or choose has default clause.
     288                  auto switchStmt = strict_dynamic_cast< const SwitchStmt * >( targetEntry->stmt );
     289                  bool foundDefault = false;
     290                  for ( auto caseStmt : switchStmt->cases ) {
     291                          if ( caseStmt->isDefault() ) {
     292                                  foundDefault = true;
     293                                  break;
     294                          }
     295                  }
     296                  if ( ! foundDefault ) {
     297                          SemanticError( stmt->location, "'fallthrough default' must be enclosed in a 'switch' or 'choose'"
     298                                                        "control structure with a 'default' clause" );
     299                  }
     300                  break;
     301          }
     302          default:
    301303                assert( false );
    302304        }
     
    305307        Label exitLabel( CodeLocation(), "" );
    306308        switch ( stmt->kind ) {
    307         case BranchStmt::Break:
     309          case BranchStmt::Break:
    308310                assert( ! targetEntry->useBreakExit().empty() );
    309311                exitLabel = targetEntry->useBreakExit();
    310312                break;
    311         case BranchStmt::Continue:
     313          case BranchStmt::Continue:
    312314                assert( ! targetEntry->useContExit().empty() );
    313315                exitLabel = targetEntry->useContExit();
    314316                break;
    315         case BranchStmt::FallThrough:
     317          case BranchStmt::FallThrough:
    316318                assert( ! targetEntry->useFallExit().empty() );
    317319                exitLabel = targetEntry->useFallExit();
    318320                break;
    319         case BranchStmt::FallThroughDefault:
     321          case BranchStmt::FallThroughDefault:
    320322                assert( ! targetEntry->useFallDefaultExit().empty() );
    321323                exitLabel = targetEntry->useFallDefaultExit();
     
    325327                }
    326328                break;
    327         default:
     329          default:
    328330                assert(0);
    329331        }
     
    353355
    354356// Mimic what the built-in push_front would do anyways. It is O(n).
    355 void push_front( vector<ptr<Stmt>> & vec, const Stmt * element ) {
     357void push_front(
     358        vector<ptr<Stmt>> & vec, const Stmt * element ) {
    356359        vec.emplace_back( nullptr );
    357360        for ( size_t i = vec.size() - 1 ; 0 < i ; --i ) {
     
    586589
    587590                ptr<Stmt> else_stmt = nullptr;
    588                 const Stmt * loop_kid = nullptr;
     591                Stmt * loop_kid = nullptr;
    589592                // check if loop node and if so add else clause if it exists
    590                 const WhileDoStmt * whilePtr = kid.as<WhileDoStmt>();
    591                 if ( whilePtr && whilePtr->else_ ) {
     593                const WhileDoStmt * whilePtr = dynamic_cast<const WhileDoStmt *>(kid.get());
     594                if ( whilePtr && whilePtr->else_) {
    592595                        else_stmt = whilePtr->else_;
    593                         loop_kid = mutate_field( whilePtr, &WhileDoStmt::else_, nullptr );
    594                 }
    595                 const ForStmt * forPtr = kid.as<ForStmt>();
    596                 if ( forPtr && forPtr->else_ ) {
     596                        WhileDoStmt * mutate_ptr = mutate(whilePtr);
     597                        mutate_ptr->else_ = nullptr;
     598                        loop_kid = mutate_ptr;
     599                }
     600                const ForStmt * forPtr = dynamic_cast<const ForStmt *>(kid.get());
     601                if ( forPtr && forPtr->else_) {
    597602                        else_stmt = forPtr->else_;
    598                         loop_kid = mutate_field( forPtr, &ForStmt::else_, nullptr );
     603                        ForStmt * mutate_ptr = mutate(forPtr);
     604                        mutate_ptr->else_ = nullptr;
     605                        loop_kid = mutate_ptr;
    599606                }
    600607
     
    626633        Pass<MultiLevelExitCore> visitor( labelTable );
    627634        const CompoundStmt * ret = stmt->accept( visitor );
    628         // There are some unset code locations slipping in, possibly by Labels.
    629         const Node * node = localFillCodeLocations( ret->location, ret );
    630         return strict_dynamic_cast<const CompoundStmt *>( node );
     635        return ret;
    631636}
    632637} // namespace ControlStruct
Note: See TracChangeset for help on using the changeset viewer.