Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/MLEMutator.cc

    r720a007 ra16764a6  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar  8 17:08:25 2018
    13 // Update Count     : 219
     12// Last Modified On : Thu Aug  4 11:21:32 2016
     13// Update Count     : 202
    1414//
    1515
     
    3838        }
    3939        namespace {
    40                 bool isLoop( const MLEMutator::Entry & e ) { return dynamic_cast< WhileStmt * >( e.get_controlStructure() ) || dynamic_cast< ForStmt * >( e.get_controlStructure() ); }
    41                 bool isSwitch( const MLEMutator::Entry & e ) { return dynamic_cast< SwitchStmt *>( e.get_controlStructure() ); }
    42 
    43                 bool isBreakTarget( const MLEMutator::Entry & e ) { return isLoop( e ) || isSwitch( e ) || dynamic_cast< CompoundStmt *>( e.get_controlStructure() ); }
    44                 bool isContinueTarget( const MLEMutator::Entry & e ) { return isLoop( e ); }
    45                 bool isFallthroughTarget( const MLEMutator::Entry & e ) { return dynamic_cast< CaseStmt *>( e.get_controlStructure() );; }
    46                 bool isFallthroughDefaultTarget( const MLEMutator::Entry & e ) { return isSwitch( e ); }
    47         } // namespace
     40                Statement * isLoop( Statement * stmt ) { return dynamic_cast< WhileStmt * >( stmt ) ? stmt : dynamic_cast< ForStmt * >( stmt ) ? stmt : 0; }
     41        }
    4842
    4943        // break labels have to come after the statement they break out of, so mutate a statement, then if they inform us
    5044        // through the breakLabel field tha they need a place to jump to on a break statement, add the break label to the
    5145        // body of statements
    52         void MLEMutator::fixBlock( std::list< Statement * > &kids, bool caseClause ) {
    53                 SemanticErrorException errors;
    54 
     46        void MLEMutator::fixBlock( std::list< Statement * > &kids ) {
    5547                for ( std::list< Statement * >::iterator k = kids.begin(); k != kids.end(); k++ ) {
    56                         if ( caseClause ) {
    57                                 // once a label is seen, it's no longer a valid fallthrough target
    58                                 for ( Label & l : (*k)->labels ) {
    59                                         fallthroughLabels.erase( l );
    60                                 }
    61                         }
    62 
    63                         // aggregate errors since the PassVisitor mutate loop was unrollled
    64                         try {
    65                                 *k = (*k)->acceptMutator(*visitor);
    66                         } catch( SemanticErrorException &e ) {
    67                                 errors.append( e );
    68                         }
     48                        *k = (*k)->acceptMutator(*visitor);
    6949
    7050                        if ( ! get_breakLabel().empty() ) {
     
    7555                        } // if
    7656                } // for
    77 
    78                 if ( ! errors.isEmpty() ) {
    79                         throw errors;
    80                 }
    8157        }
    8258
     
    8763                        Label brkLabel = generator->newLabel("blockBreak", cmpndStmt);
    8864                        enclosingControlStructures.push_back( Entry( cmpndStmt, brkLabel ) );
    89                         GuardAction( [this]() { enclosingControlStructures.pop_back(); } );
    9065                } // if
    9166
     
    9974                                set_breakLabel( enclosingControlStructures.back().useBreakExit() );
    10075                        } // if
     76                        enclosingControlStructures.pop_back();
    10177                } // if
    10278        }
     
    136112                                        if ( isContinue ) {
    137113                                                // continue target is outermost loop
    138                                                 targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), isContinueTarget );
     114                                                targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), [](Entry &e) { return isLoop( e.get_controlStructure() ); } );
    139115                                        } else {
    140                                                 // break target is outermost loop, switch, or block control structure
    141                                                 if ( enclosingControlStructures.empty() ) SemanticError( branchStmt->location, "'break' outside a loop, 'switch', or labelled block" );
    142                                                 targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), isBreakTarget );
     116                                                // break target is outmost control structure
     117                                                if ( enclosingControlStructures.empty() ) SemanticError( branchStmt->location, "'break' outside a loop, switch, or labelled block" );
     118                                                targetEntry = enclosingControlStructures.rbegin();
    143119                                        } // if
    144120                                } else {
     
    147123                                } // if
    148124                                // ensure that selected target is valid
    149                                 if ( targetEntry == enclosingControlStructures.rend() || (isContinue && ! isContinueTarget( *targetEntry ) ) ) {
     125                                if ( targetEntry == enclosingControlStructures.rend() || (isContinue && ! isLoop( targetEntry->get_controlStructure() ) ) ) {
    150126                                        SemanticError( branchStmt->location, toString( (isContinue ? "'continue'" : "'break'"), " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), originalTarget ) );
    151127                                } // if
    152128                                break;
    153129                        }
    154                         case BranchStmt::FallThrough:
    155                                 targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), isFallthroughTarget );
    156                                 // ensure that selected target is valid
    157                                 if ( targetEntry == enclosingControlStructures.rend() ) {
    158                                         SemanticError( branchStmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
    159                                 } // if
    160                                 if ( branchStmt->get_target() != "" ) {
    161                                         // labelled fallthrough
    162                                         // target must be in the set of valid fallthrough labels
    163                                         if ( ! fallthroughLabels.count( branchStmt->get_target() ) ) {
    164                                                 SemanticError( branchStmt->location, toString( "'fallthrough' target must be a later case statement: ", originalTarget ) );
    165                                         }
    166                                         return new BranchStmt( originalTarget, BranchStmt::Goto );
    167                                 }
    168                                 break;
    169                         case BranchStmt::FallThroughDefault: {
    170                                 // fallthrough default
    171                                 targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), isFallthroughDefaultTarget );
    172 
    173                                 // ensure that fallthrough is within a switch or choose
    174                                 if ( targetEntry == enclosingControlStructures.rend() ) {
    175                                         SemanticError( branchStmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
    176                                 } // if
    177 
    178                                 // ensure that switch or choose has a default clause
    179                                 SwitchStmt * switchStmt = strict_dynamic_cast< SwitchStmt * >( targetEntry->get_controlStructure() );
    180                                 bool foundDefault = false;
    181                                 for ( Statement * stmt : switchStmt->statements ) {
    182                                         CaseStmt * caseStmt = strict_dynamic_cast< CaseStmt * >( stmt );
    183                                         if ( caseStmt->isDefault() ) {
    184                                                 foundDefault = true;
    185                                         } // if
    186                                 } // for
    187                                 if ( ! foundDefault ) {
    188                                         SemanticError( branchStmt->location, "'fallthrough default' must be enclosed in a 'switch' or 'choose' control structure with a 'default' clause" );
    189                                 }
    190                                 break;
    191                         }
    192 
    193130                        default:
    194131                                assert( false );
     
    206143                                exitLabel = targetEntry->useContExit();
    207144                                break;
    208                   case BranchStmt::FallThrough:
    209                                 assert( targetEntry->useFallExit() != "");
    210                                 exitLabel = targetEntry->useFallExit();
    211                                 break;
    212                   case BranchStmt::FallThroughDefault:
    213                                 assert( targetEntry->useFallDefaultExit() != "");
    214                                 exitLabel = targetEntry->useFallDefaultExit();
    215                                 // check that fallthrough default comes before the default clause
    216                                 if ( ! targetEntry->isFallDefaultValid() ) {
    217                                         SemanticError( branchStmt->location, "'fallthrough default' must precede the 'default' clause" );
    218                                 }
    219                                 break;
    220145                  default:
    221146                                assert(0);                                      // shouldn't be here
     
    262187                Label contLabel = generator->newLabel("loopContinue", loopStmt);
    263188                enclosingControlStructures.push_back( Entry( loopStmt, brkLabel, contLabel ) );
    264                 GuardAction( [this]() { enclosingControlStructures.pop_back(); } );
    265189        }
    266190
     
    273197
    274198                // this will take the necessary steps to add definitions of the previous two labels, if they are used.
    275                 loopStmt->body = mutateLoop( loopStmt->get_body(), e );
     199                loopStmt->set_body( mutateLoop( loopStmt->get_body(), e ) );
     200                enclosingControlStructures.pop_back();
    276201                return loopStmt;
    277202        }
     
    299224                        Label brkLabel = generator->newLabel("blockBreak", ifStmt);
    300225                        enclosingControlStructures.push_back( Entry( ifStmt, brkLabel ) );
    301                         GuardAction( [this]() { enclosingControlStructures.pop_back(); } );
    302226                } // if
    303227        }
     
    309233                                set_breakLabel( enclosingControlStructures.back().useBreakExit() );
    310234                        } // if
     235                        enclosingControlStructures.pop_back();
    311236                } // if
    312237                return ifStmt;
     
    315240        void MLEMutator::premutate( CaseStmt *caseStmt ) {
    316241                visit_children = false;
    317 
    318                 // mark default as seen before visiting its statements to catch default loops
    319                 if ( caseStmt->isDefault() ) {
    320                         enclosingControlStructures.back().seenDefault();
    321                 } // if
    322 
    323242                caseStmt->condition = maybeMutate( caseStmt->condition, *visitor );
    324                 Label fallLabel = generator->newLabel( "fallThrough", caseStmt );
    325                 {
    326                         // ensure that stack isn't corrupted by exceptions in fixBlock
    327                         auto guard = makeFuncGuard( [&]() { enclosingControlStructures.push_back( Entry( caseStmt, fallLabel ) ); }, [this]() { enclosingControlStructures.pop_back(); } );
    328 
    329                         // empty case statement
    330                         if( ! caseStmt->stmts.empty() ) {
    331                                 // the parser ensures that all statements in a case are grouped into a block
    332                                 CompoundStmt * block = strict_dynamic_cast< CompoundStmt * >( caseStmt->stmts.front() );
    333                                 fixBlock( block->kids, true );
    334 
    335                                 // add fallthrough label if necessary
    336                                 assert( ! enclosingControlStructures.empty() );
    337                                 if ( enclosingControlStructures.back().isFallUsed() ) {
    338                                         std::list<Label> ls{ enclosingControlStructures.back().useFallExit() };
    339                                         caseStmt->stmts.push_back( new NullStmt( ls ) );
    340                                 } // if
    341                         } // if
    342                 }
    343                 assert( ! enclosingControlStructures.empty() );
    344                 assertf( dynamic_cast<SwitchStmt *>( enclosingControlStructures.back().get_controlStructure() ), "Control structure enclosing a case clause must be a switch, but is: %s", toCString( enclosingControlStructures.back().get_controlStructure() ) );
    345                 if ( caseStmt->isDefault() ) {
    346                         if ( enclosingControlStructures.back().isFallDefaultUsed() ) {
    347                                 // add fallthrough default label if necessary
    348                                 std::list<Label> ls{ enclosingControlStructures.back().useFallDefaultExit() };
    349                                 caseStmt->stmts.push_front( new NullStmt( ls ) );
    350                         } // if
    351                 } // if
     243                fixBlock( caseStmt->stmts );
    352244        }
    353245
     
    355247                // generate a label for breaking out of a labeled switch
    356248                Label brkLabel = generator->newLabel("switchBreak", switchStmt);
    357                 auto it = std::find_if( switchStmt->statements.rbegin(), switchStmt->statements.rend(), [](Statement * stmt) {
    358                         CaseStmt * caseStmt = strict_dynamic_cast< CaseStmt * >( stmt );
    359                         return caseStmt->isDefault();
    360                 });
    361                 CaseStmt * defaultCase = it != switchStmt->statements.rend() ? strict_dynamic_cast<CaseStmt *>( *it ) : nullptr;
    362                 Label fallDefaultLabel = defaultCase ? generator->newLabel( "fallThroughDefault", defaultCase ) : "";
    363                 enclosingControlStructures.push_back( Entry(switchStmt, brkLabel, fallDefaultLabel) );
    364                 GuardAction( [this]() { enclosingControlStructures.pop_back(); } );
    365 
    366                 // Collect valid labels for fallthrough. This is initially all labels at the same level as a case statement.
    367                 // As labels are seen during traversal, they are removed, since fallthrough is not allowed to jump backwards.
    368                 for ( Statement * stmt : switchStmt->statements ) {
    369                         CaseStmt * caseStmt = strict_dynamic_cast< CaseStmt * >( stmt );
    370                         if ( caseStmt->stmts.empty() ) continue;
    371                         CompoundStmt * block = dynamic_cast< CompoundStmt * >( caseStmt->stmts.front() );
    372                         for ( Statement * stmt : block->kids ) {
    373                                 for ( Label & l : stmt->labels ) {
    374                                         fallthroughLabels.insert( l );
    375                                 }
    376                         }
    377                 }
     249                enclosingControlStructures.push_back( Entry(switchStmt, brkLabel) );
    378250        }
    379251
     
    400272
    401273                assert ( enclosingControlStructures.back() == switchStmt );
     274                enclosingControlStructures.pop_back();
    402275                return switchStmt;
    403276        }
Note: See TracChangeset for help on using the changeset viewer.