Changeset 2f52b18
- Timestamp:
- Feb 2, 2022, 11:40:28 PM (3 years ago)
- Branches:
- ADT, ast-experimental, enum, forall-pointer-decay, master, pthread-emulation, qualifiedEnum
- Children:
- 85a2c3f
- Parents:
- 9dc0836
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/MultiLevelExit.cpp
r9dc0836 r2f52b18 10 10 // Created On : Mon Nov 1 13:48:00 2021 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Feb 2 2 0:19:24 202213 // Update Count : 3 012 // Last Modified On : Wed Feb 2 23:07:54 2022 13 // Update Count : 33 14 14 // 15 15 … … 49 49 return target.label; 50 50 } 51 52 51 public: 53 52 Entry( const ForStmt * stmt, Label breakExit, Label contExit ) : … … 168 167 169 168 // if the stmt is labelled then generate a label to check in postvisit if the label is used 170 bool isLabeled = ! stmt->labels.empty();169 bool isLabeled = ! stmt->labels.empty(); 171 170 if ( isLabeled ) { 172 171 Label breakLabel = newLabel( "blockBreak", stmt ); … … 180 179 181 180 if ( isLabeled ) { 182 assert( ! enclosing_control_structures.empty() );181 assert( ! enclosing_control_structures.empty() ); 183 182 Entry & entry = enclosing_control_structures.back(); 184 if ( ! entry.useBreakExit().empty() ) {183 if ( ! entry.useBreakExit().empty() ) { 185 184 break_label = entry.useBreakExit(); 186 185 } … … 254 253 } 255 254 // Ensure that selected target is valid. 256 if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && ! isContinueTarget( *targetEntry ) ) ) {255 if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && ! isContinueTarget( *targetEntry ) ) ) { 257 256 SemanticError( stmt->location, toString( (isContinue ? "'continue'" : "'break'"), 258 257 " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), … … 268 267 SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" ); 269 268 } 270 if ( ! stmt->target.empty() ) {269 if ( ! stmt->target.empty() ) { 271 270 // Labelled fallthrough: target must be a valid fallthough label. 272 if ( ! fallthrough_labels.count( stmt->target ) ) {271 if ( ! fallthrough_labels.count( stmt->target ) ) { 273 272 SemanticError( stmt->location, toString( "'fallthrough' target must be a later case statement: ", 274 273 stmt->originalTarget ) ); 275 274 } 276 return new BranchStmt( 277 stmt->location, BranchStmt::Goto, stmt->originalTarget ); 275 return new BranchStmt( stmt->location, BranchStmt::Goto, stmt->originalTarget ); 278 276 } 279 277 break; … … 307 305 } 308 306 309 // Branch error checks: get the appropriate label name: 310 // (This label is always replaced.) 307 // Branch error checks: get the appropriate label name, which is always replaced. 311 308 Label exitLabel( CodeLocation(), "" ); 312 309 switch ( stmt->kind ) { 313 310 case BranchStmt::Break: 314 assert( ! targetEntry->useBreakExit().empty() );311 assert( ! targetEntry->useBreakExit().empty() ); 315 312 exitLabel = targetEntry->useBreakExit(); 316 313 break; 317 314 case BranchStmt::Continue: 318 assert( ! targetEntry->useContExit().empty() );315 assert( ! targetEntry->useContExit().empty() ); 319 316 exitLabel = targetEntry->useContExit(); 320 317 break; 321 318 case BranchStmt::FallThrough: 322 assert( ! targetEntry->useFallExit().empty() );319 assert( ! targetEntry->useFallExit().empty() ); 323 320 exitLabel = targetEntry->useFallExit(); 324 321 break; 325 322 case BranchStmt::FallThroughDefault: 326 assert( ! targetEntry->useFallDefaultExit().empty() );323 assert( ! targetEntry->useFallDefaultExit().empty() ); 327 324 exitLabel = targetEntry->useFallDefaultExit(); 328 325 // Check that fallthrough default comes before the default clause. 329 if ( ! targetEntry->isFallDefaultValid() ) {326 if ( ! targetEntry->isFallDefaultValid() ) { 330 327 SemanticError( stmt->location, "'fallthrough default' must precede the 'default' clause" ); 331 328 } … … 373 370 // If default, mark seen. 374 371 if ( stmt->isDefault() ) { 375 assert( ! enclosing_control_structures.empty() );372 assert( ! enclosing_control_structures.empty() ); 376 373 enclosing_control_structures.back().seenDefault(); 377 374 } … … 399 396 Entry & entry = enclosing_control_structures.back(); 400 397 if ( entry.isFallUsed() ) { 401 mutStmt->stmts.push_back( 402 labelledNullStmt( mutStmt->location, entry.useFallExit() ) ); 398 mutStmt->stmts.push_back( labelledNullStmt( mutStmt->location, entry.useFallExit() ) ); 403 399 } 404 400 } … … 411 407 if ( entry.isFallDefaultUsed() ) { 412 408 // Add fallthrough default label if necessary. 413 push_front( mutStmt->stmts, labelledNullStmt( 414 stmt->location, entry.useFallDefaultExit() 415 ) ); 409 push_front( mutStmt->stmts, labelledNullStmt( stmt->location, entry.useFallDefaultExit() ) ); 416 410 } 417 411 } … … 420 414 421 415 void MultiLevelExitCore::previsit( const IfStmt * stmt ) { 422 bool labeledBlock = ! stmt->labels.empty();416 bool labeledBlock = ! stmt->labels.empty(); 423 417 if ( labeledBlock ) { 424 418 Label breakLabel = newLabel( "blockBreak", stmt ); … … 429 423 430 424 const IfStmt * MultiLevelExitCore::postvisit( const IfStmt * stmt ) { 431 bool labeledBlock = ! stmt->labels.empty();425 bool labeledBlock = ! stmt->labels.empty(); 432 426 if ( labeledBlock ) { 433 427 auto this_label = enclosing_control_structures.back().useBreakExit(); 434 if ( ! this_label.empty() ) {428 if ( ! this_label.empty() ) { 435 429 break_label = this_label; 436 430 } … … 448 442 auto it = find_if( stmt->stmts.rbegin(), stmt->stmts.rend(), isDefaultCase ); 449 443 450 const CaseStmt * defaultCase = it != stmt->stmts.rend() 451 ? (it)->strict_as<CaseStmt>() : nullptr; 452 Label defaultLabel = defaultCase 453 ? newLabel( "fallThroughDefault", defaultCase ) 454 : Label( stmt->location, "" ); 444 const CaseStmt * defaultCase = it != stmt->stmts.rend() ? (it)->strict_as<CaseStmt>() : nullptr; 445 Label defaultLabel = defaultCase ? newLabel( "fallThroughDefault", defaultCase ) : Label( stmt->location, "" ); 455 446 enclosing_control_structures.emplace_back( stmt, label, defaultLabel ); 456 447 GuardAction( [this]() { enclosing_control_structures.pop_back(); } ); 457 448 458 // Collect valid labels for fallthrough. It starts with all labels at 459 // t his level, then remove as each is seen during traversal.449 // Collect valid labels for fallthrough. It starts with all labels at this level, then remove as each is seen during 450 // traversal. 460 451 for ( const Stmt * stmt : stmt->stmts ) { 461 452 auto * caseStmt = strict_dynamic_cast< const CaseStmt * >( stmt ); … … 471 462 472 463 const SwitchStmt * MultiLevelExitCore::postvisit( const SwitchStmt * stmt ) { 473 assert( ! enclosing_control_structures.empty() );464 assert( ! enclosing_control_structures.empty() ); 474 465 Entry & entry = enclosing_control_structures.back(); 475 466 assert( entry.stmt == stmt ); … … 477 468 // Only run to generate the break label. 478 469 if ( entry.isBreakUsed() ) { 479 // To keep the switch statements uniform (all direct children of a 480 // SwitchStmt should be CastStmts), append the exit label and break 481 // to the last case, create a default case is there are no cases. 470 // To keep the switch statements uniform (all direct children of a SwitchStmt should be CastStmts), append the 471 // exit label and break to the last case, create a default case if no cases. 482 472 SwitchStmt * mutStmt = mutate( stmt ); 483 473 if ( mutStmt->stmts.empty() ) { 484 mutStmt->stmts.push_back( new CaseStmt( 485 mutStmt->location, nullptr, {} )); 474 mutStmt->stmts.push_back( new CaseStmt( mutStmt->location, nullptr, {} ) ); 486 475 } 487 476 … … 507 496 508 497 void MultiLevelExitCore::previsit( const TryStmt * stmt ) { 509 bool isLabeled = ! stmt->labels.empty();498 bool isLabeled = ! stmt->labels.empty(); 510 499 if ( isLabeled ) { 511 500 Label breakLabel = newLabel( "blockBreak", stmt ); … … 516 505 517 506 void MultiLevelExitCore::postvisit( const TryStmt * stmt ) { 518 bool isLabeled = ! stmt->labels.empty();507 bool isLabeled = ! stmt->labels.empty(); 519 508 if ( isLabeled ) { 520 509 auto this_label = enclosing_control_structures.back().useBreakExit(); 521 if ( ! this_label.empty() ) {510 if ( ! this_label.empty() ) { 522 511 break_label = this_label; 523 512 } … … 526 515 527 516 void MultiLevelExitCore::previsit( const FinallyStmt * ) { 528 GuardAction([this, old = move(enclosing_control_structures)](){ 529 enclosing_control_structures = move(old); 530 }); 517 GuardAction([this, old = move( enclosing_control_structures)](){ enclosing_control_structures = move(old); }); 531 518 enclosing_control_structures = vector<Entry>(); 532 519 GuardValue( inFinally ) = true; … … 575 562 template<typename LoopNode> 576 563 const LoopNode * MultiLevelExitCore::posthandleLoopStmt( const LoopNode * loopStmt ) { 577 assert( ! enclosing_control_structures.empty() );564 assert( ! enclosing_control_structures.empty() ); 578 565 Entry & entry = enclosing_control_structures.back(); 579 566 assert( entry.stmt == loopStmt ); 580 567 581 568 // Now check if the labels are used and add them if so. 582 return mutate_field( 583 loopStmt, &LoopNode::body, mutateLoop( loopStmt->body, entry ) ); 569 return mutate_field( loopStmt, &LoopNode::body, mutateLoop( loopStmt->body, entry ) ); 584 570 // this call to mutate_field compares loopStmt->body and the result of mutateLoop 585 571 // if they are the same the node isn't mutated, if they differ then the new mutated node is returned … … 609 595 } 610 596 611 if ( !break_label.empty() ) { 612 ret.push_back( 613 labelledNullStmt( ret.back()->location, break_label ) ); 597 if ( ! break_label.empty() ) { 598 ret.push_back( labelledNullStmt( ret.back()->location, break_label ) ); 614 599 break_label = Label( CodeLocation(), "" ); 615 600 } 616 601 } 617 602 618 if ( ! errors.isEmpty() ) {603 if ( ! errors.isEmpty() ) { 619 604 throw errors; 620 605 }
Note: See TracChangeset
for help on using the changeset viewer.