- File:
-
- 1 edited
-
src/ControlStruct/MultiLevelExit.cpp (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/MultiLevelExit.cpp
r0577df2 rf75e25b 18 18 #include "AST/Pass.hpp" 19 19 #include "AST/Stmt.hpp" 20 #include "Common/CodeLocationTools.hpp"21 20 #include "LabelGeneratorNew.hpp" 22 21 … … 149 148 }; 150 149 151 NullStmt * labelledNullStmt( const CodeLocation & cl, const Label & label ) { 150 NullStmt * labelledNullStmt( 151 const CodeLocation & cl, const Label & label ) { 152 152 return new NullStmt( cl, vector<Label>{ label } ); 153 153 } … … 163 163 164 164 const CompoundStmt * MultiLevelExitCore::previsit( 165 const CompoundStmt * stmt ) {165 const CompoundStmt * stmt ) { 166 166 visit_children = false; 167 167 … … 188 188 } 189 189 190 size_t getUnusedIndex( const Stmt * stmt, const Label & originalTarget ) { 190 size_t getUnusedIndex( 191 const Stmt * stmt, const Label & originalTarget ) { 191 192 const size_t size = stmt->labels.size(); 192 193 … … 208 209 } 209 210 210 const Stmt * addUnused( const Stmt * stmt, const Label & originalTarget ) { 211 const Stmt * addUnused( 212 const Stmt * stmt, const Label & originalTarget ) { 211 213 size_t i = getUnusedIndex( stmt, originalTarget ); 212 214 if ( i == stmt->labels.size() ) { … … 226 228 // Labels on different stmts require different approaches to access 227 229 switch ( stmt->kind ) { 228 case BranchStmt::Goto:230 case BranchStmt::Goto: 229 231 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() ) { 239 241 SemanticError( stmt->location, 240 242 "'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){ 249 251 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'"), 255 257 " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), 256 258 stmt->originalTarget ) ); 257 }258 break;259 }260 // handle fallthrough in case/switch stmts261 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: ", 271 273 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: 301 303 assert( false ); 302 304 } … … 305 307 Label exitLabel( CodeLocation(), "" ); 306 308 switch ( stmt->kind ) { 307 case BranchStmt::Break:309 case BranchStmt::Break: 308 310 assert( ! targetEntry->useBreakExit().empty() ); 309 311 exitLabel = targetEntry->useBreakExit(); 310 312 break; 311 case BranchStmt::Continue:313 case BranchStmt::Continue: 312 314 assert( ! targetEntry->useContExit().empty() ); 313 315 exitLabel = targetEntry->useContExit(); 314 316 break; 315 case BranchStmt::FallThrough:317 case BranchStmt::FallThrough: 316 318 assert( ! targetEntry->useFallExit().empty() ); 317 319 exitLabel = targetEntry->useFallExit(); 318 320 break; 319 case BranchStmt::FallThroughDefault:321 case BranchStmt::FallThroughDefault: 320 322 assert( ! targetEntry->useFallDefaultExit().empty() ); 321 323 exitLabel = targetEntry->useFallDefaultExit(); … … 325 327 } 326 328 break; 327 default:329 default: 328 330 assert(0); 329 331 } … … 353 355 354 356 // 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 ) { 357 void push_front( 358 vector<ptr<Stmt>> & vec, const Stmt * element ) { 356 359 vec.emplace_back( nullptr ); 357 360 for ( size_t i = vec.size() - 1 ; 0 < i ; --i ) { … … 586 589 587 590 ptr<Stmt> else_stmt = nullptr; 588 constStmt * loop_kid = nullptr;591 Stmt * loop_kid = nullptr; 589 592 // 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_) { 592 595 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_) { 597 602 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; 599 606 } 600 607 … … 626 633 Pass<MultiLevelExitCore> visitor( labelTable ); 627 634 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; 631 636 } 632 637 } // namespace ControlStruct
Note:
See TracChangeset
for help on using the changeset viewer.