- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/MultiLevelExit.cpp
r491bb81 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 … … 229 228 // Labels on different stmts require different approaches to access 230 229 switch ( stmt->kind ) { 231 case BranchStmt::Goto:230 case BranchStmt::Goto: 232 231 return stmt; 233 case BranchStmt::Continue:234 case BranchStmt::Break: {235 bool isContinue = stmt->kind == BranchStmt::Continue;236 // Handle unlabeled break and continue.237 if ( stmt->target.empty() ) {238 if ( isContinue ) {239 targetEntry = findEnclosingControlStructure( isContinueTarget );240 } else {241 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() ) { 242 241 SemanticError( stmt->location, 243 242 "'break' outside a loop, 'switch', or labelled block" ); 244 }245 targetEntry = findEnclosingControlStructure( isBreakTarget );246 }247 // Handle labeled break and continue.248 } else {249 // Lookup label in table to find attached control structure.250 targetEntry = findEnclosingControlStructure(251 [ 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){ 252 251 return entry.stmt == targetStmt; 253 } );254 }255 // Ensure that selected target is valid.256 if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && ! isContinueTarget( *targetEntry ) ) ) {257 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'"), 258 257 " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), 259 258 stmt->originalTarget ) ); 260 }261 break;262 }263 // handle fallthrough in case/switch stmts264 case BranchStmt::FallThrough: {265 targetEntry = findEnclosingControlStructure( isFallthroughTarget );266 // Check that target is valid.267 if ( targetEntry == enclosing_control_structures.rend() ) {268 SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );269 }270 if ( ! stmt->target.empty() ) {271 // Labelled fallthrough: target must be a valid fallthough label.272 if ( ! fallthrough_labels.count( stmt->target ) ) {273 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: ", 274 273 stmt->originalTarget ) ); 275 }276 return new BranchStmt( stmt->location, BranchStmt::Goto, stmt->originalTarget );277 }278 break;279 }280 case BranchStmt::FallThroughDefault: {281 targetEntry = findEnclosingControlStructure( isFallthroughDefaultTarget );282 283 // Check if in switch or choose statement.284 if ( targetEntry == enclosing_control_structures.rend() ) {285 SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );286 }287 288 // Check if switch or choose has default clause.289 auto switchStmt = strict_dynamic_cast< const SwitchStmt * >( targetEntry->stmt );290 bool foundDefault = false;291 for ( auto caseStmt : switchStmt->cases ) {292 if ( caseStmt->isDefault() ) {293 foundDefault = true;294 break;295 }296 }297 if ( ! foundDefault ) {298 SemanticError( stmt->location, "'fallthrough default' must be enclosed in a 'switch' or 'choose'"299 300 }301 break;302 }303 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: 304 303 assert( false ); 305 304 } … … 308 307 Label exitLabel( CodeLocation(), "" ); 309 308 switch ( stmt->kind ) { 310 case BranchStmt::Break:309 case BranchStmt::Break: 311 310 assert( ! targetEntry->useBreakExit().empty() ); 312 311 exitLabel = targetEntry->useBreakExit(); 313 312 break; 314 case BranchStmt::Continue:313 case BranchStmt::Continue: 315 314 assert( ! targetEntry->useContExit().empty() ); 316 315 exitLabel = targetEntry->useContExit(); 317 316 break; 318 case BranchStmt::FallThrough:317 case BranchStmt::FallThrough: 319 318 assert( ! targetEntry->useFallExit().empty() ); 320 319 exitLabel = targetEntry->useFallExit(); 321 320 break; 322 case BranchStmt::FallThroughDefault:321 case BranchStmt::FallThroughDefault: 323 322 assert( ! targetEntry->useFallDefaultExit().empty() ); 324 323 exitLabel = targetEntry->useFallDefaultExit(); … … 328 327 } 329 328 break; 330 default:329 default: 331 330 assert(0); 332 331 } … … 589 588 } 590 589 590 ptr<Stmt> else_stmt = nullptr; 591 Stmt * loop_kid = nullptr; 592 // check if loop node and if so add else clause if it exists 593 const WhileDoStmt * whilePtr = dynamic_cast<const WhileDoStmt *>(kid.get()); 594 if ( whilePtr && whilePtr->else_) { 595 else_stmt = whilePtr->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_) { 602 else_stmt = forPtr->else_; 603 ForStmt * mutate_ptr = mutate(forPtr); 604 mutate_ptr->else_ = nullptr; 605 loop_kid = mutate_ptr; 606 } 607 591 608 try { 592 ret.push_back( kid->accept( *visitor ) ); 609 if (else_stmt) ret.push_back( loop_kid->accept( *visitor ) ); 610 else ret.push_back( kid->accept( *visitor ) ); 593 611 } catch ( SemanticErrorException & e ) { 594 612 errors.append( e ); 595 613 } 596 614 597 // check if loop node and if so add else clause if it exists 598 const WhileDoStmt * whilePtr = dynamic_cast<const WhileDoStmt *>(kid.get()); 599 if ( whilePtr && whilePtr->else_) ret.push_back(whilePtr->else_); 600 const ForStmt * forPtr = dynamic_cast<const ForStmt *>(kid.get()); 601 if ( forPtr && forPtr->else_) ret.push_back(forPtr->else_); 615 if (else_stmt) ret.push_back(else_stmt); 602 616 603 617 if ( ! break_label.empty() ) { … … 619 633 Pass<MultiLevelExitCore> visitor( labelTable ); 620 634 const CompoundStmt * ret = stmt->accept( visitor ); 621 // There are some unset code locations slipping in, possibly by Labels. 622 const Node * node = localFillCodeLocations( ret->location, ret ); 623 return strict_dynamic_cast<const CompoundStmt *>( node ); 635 return ret; 624 636 } 625 637 } // namespace ControlStruct
Note:
See TracChangeset
for help on using the changeset viewer.