- File:
-
- 1 edited
-
src/ControlStruct/MultiLevelExit.cpp (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/MultiLevelExit.cpp
r400b8be r891f707 9 9 // Author : Andrew Beach 10 10 // Created On : Mon Nov 1 13:48:00 2021 11 // Last Modified By : Andrew Beach12 // Last Modified On : Mon Mar 28 9:42:00202213 // Update Count : 3 411 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Feb 2 23:07:54 2022 13 // Update Count : 33 14 14 // 15 15 … … 40 40 41 41 enum Kind { 42 ForStmtK, WhileDoStmtK, CompoundStmtK, IfStmtK, Case ClauseK, SwitchStmtK, TryStmtK42 ForStmtK, WhileDoStmtK, CompoundStmtK, IfStmtK, CaseStmtK, SwitchStmtK, TryStmtK 43 43 } kind; 44 44 … … 58 58 Entry( const IfStmt *stmt, Label breakExit ) : 59 59 stmt( stmt ), firstTarget( breakExit ), secondTarget(), kind( IfStmtK ) {} 60 Entry( const Case Clause *, const CompoundStmt *stmt, Label fallExit ) :61 stmt( stmt ), firstTarget( fallExit ), secondTarget(), kind( Case ClauseK ) {}60 Entry( const CaseStmt *stmt, Label fallExit ) : 61 stmt( stmt ), firstTarget( fallExit ), secondTarget(), kind( CaseStmtK ) {} 62 62 Entry( const SwitchStmt *stmt, Label breakExit, Label fallDefaultExit ) : 63 63 stmt( stmt ), firstTarget( breakExit ), secondTarget( fallDefaultExit ), kind( SwitchStmtK ) {} … … 66 66 67 67 bool isContTarget() const { return kind <= WhileDoStmtK; } 68 bool isBreakTarget() const { return kind != Case ClauseK; }69 bool isFallTarget() const { return kind == Case ClauseK; }68 bool isBreakTarget() const { return kind != CaseStmtK; } 69 bool isFallTarget() const { return kind == CaseStmtK; } 70 70 bool isFallDefaultTarget() const { return kind == SwitchStmtK; } 71 71 72 72 // These routines set a target as being "used" by a BranchStmt 73 73 Label useContExit() { assert( kind <= WhileDoStmtK ); return useTarget(secondTarget); } 74 Label useBreakExit() { assert( kind != Case ClauseK ); return useTarget(firstTarget); }75 Label useFallExit() { assert( kind == Case ClauseK ); return useTarget(firstTarget); }74 Label useBreakExit() { assert( kind != CaseStmtK ); return useTarget(firstTarget); } 75 Label useFallExit() { assert( kind == CaseStmtK ); return useTarget(firstTarget); } 76 76 Label useFallDefaultExit() { assert( kind == SwitchStmtK ); return useTarget(secondTarget); } 77 77 78 78 // These routines check if a specific label for a statement is used by a BranchStmt 79 79 bool isContUsed() const { assert( kind <= WhileDoStmtK ); return secondTarget.used; } 80 bool isBreakUsed() const { assert( kind != Case ClauseK ); return firstTarget.used; }81 bool isFallUsed() const { assert( kind == Case ClauseK ); return firstTarget.used; }80 bool isBreakUsed() const { assert( kind != CaseStmtK ); return firstTarget.used; } 81 bool isFallUsed() const { assert( kind == CaseStmtK ); return firstTarget.used; } 82 82 bool isFallDefaultUsed() const { assert( kind == SwitchStmtK ); return secondTarget.used; } 83 83 void seenDefault() { fallDefaultValid = false; } … … 115 115 void previsit( const ForStmt * ); 116 116 const ForStmt * postvisit( const ForStmt * ); 117 const Case Clause * previsit( const CaseClause* );117 const CaseStmt * previsit( const CaseStmt * ); 118 118 void previsit( const IfStmt * ); 119 119 const IfStmt * postvisit( const IfStmt * ); … … 123 123 void previsit( const TryStmt * ); 124 124 void postvisit( const TryStmt * ); 125 void previsit( const Finally Clause* );125 void previsit( const FinallyStmt * ); 126 126 127 127 const Stmt * mutateLoop( const Stmt * body, Entry& ); … … 288 288 auto switchStmt = strict_dynamic_cast< const SwitchStmt * >( targetEntry->stmt ); 289 289 bool foundDefault = false; 290 for ( auto caseStmt : switchStmt->cases ) { 290 for ( auto subStmt : switchStmt->stmts ) { 291 const CaseStmt * caseStmt = subStmt.strict_as<CaseStmt>(); 291 292 if ( caseStmt->isDefault() ) { 292 293 foundDefault = true; … … 364 365 } 365 366 366 const Case Clause * MultiLevelExitCore::previsit( const CaseClause* stmt ) {367 const CaseStmt * MultiLevelExitCore::previsit( const CaseStmt * stmt ) { 367 368 visit_children = false; 368 369 … … 374 375 375 376 // The cond may not exist, but if it does update it now. 376 visitor->maybe_accept( stmt, &Case Clause::cond );377 visitor->maybe_accept( stmt, &CaseStmt::cond ); 377 378 378 379 // Just save the mutated node for simplicity. 379 Case Clause* mutStmt = mutate( stmt );380 381 Label fallLabel = newLabel( "fallThrough", stmt ->location);380 CaseStmt * mutStmt = mutate( stmt ); 381 382 Label fallLabel = newLabel( "fallThrough", stmt ); 382 383 if ( ! mutStmt->stmts.empty() ) { 383 // These should already be in a block.384 auto first = mutStmt->stmts.front().get_and_mutate();385 auto block = strict_dynamic_cast<CompoundStmt *>( first );386 387 384 // Ensure that the stack isn't corrupted by exceptions in fixBlock. 388 385 auto guard = makeFuncGuard( 389 [&](){ enclosing_control_structures.emplace_back( mutStmt, block,fallLabel ); },386 [&](){ enclosing_control_structures.emplace_back( mutStmt, fallLabel ); }, 390 387 [this](){ enclosing_control_structures.pop_back(); } 391 388 ); 392 389 390 // These should already be in a block. 391 auto block = mutate( mutStmt->stmts.front().strict_as<CompoundStmt>() ); 393 392 block->kids = fixBlock( block->kids, true ); 394 393 … … 397 396 Entry & entry = enclosing_control_structures.back(); 398 397 if ( entry.isFallUsed() ) { 399 mutStmt->stmts.push_back( labelledNullStmt( block->location, entry.useFallExit() ) );398 mutStmt->stmts.push_back( labelledNullStmt( mutStmt->location, entry.useFallExit() ) ); 400 399 } 401 400 } … … 434 433 } 435 434 436 static bool isDefaultCase( const ptr<CaseClause> & caseClause ) { 437 return caseClause->isDefault(); 435 bool isDefaultCase( const ptr<Stmt> & stmt ) { 436 const CaseStmt * caseStmt = stmt.strict_as<CaseStmt>(); 437 return caseStmt->isDefault(); 438 438 } 439 439 440 440 void MultiLevelExitCore::previsit( const SwitchStmt * stmt ) { 441 441 Label label = newLabel( "switchBreak", stmt ); 442 auto it = find_if( stmt-> cases.rbegin(), stmt->cases.rend(), isDefaultCase );443 444 const Case Clause * defaultCase = it != stmt->cases.rend() ? (*it) : nullptr;445 Label defaultLabel = defaultCase ? newLabel( "fallThroughDefault", defaultCase ->location) : Label( stmt->location, "" );442 auto it = find_if( stmt->stmts.rbegin(), stmt->stmts.rend(), isDefaultCase ); 443 444 const CaseStmt * defaultCase = it != stmt->stmts.rend() ? (it)->strict_as<CaseStmt>() : nullptr; 445 Label defaultLabel = defaultCase ? newLabel( "fallThroughDefault", defaultCase ) : Label( stmt->location, "" ); 446 446 enclosing_control_structures.emplace_back( stmt, label, defaultLabel ); 447 447 GuardAction( [this]() { enclosing_control_structures.pop_back(); } ); … … 449 449 // Collect valid labels for fallthrough. It starts with all labels at this level, then remove as each is seen during 450 450 // traversal. 451 for ( const CaseClause * caseStmt : stmt->cases ) { 451 for ( const Stmt * stmt : stmt->stmts ) { 452 auto * caseStmt = strict_dynamic_cast< const CaseStmt * >( stmt ); 452 453 if ( caseStmt->stmts.empty() ) continue; 453 454 auto block = caseStmt->stmts.front().strict_as<CompoundStmt>(); … … 470 471 // exit label and break to the last case, create a default case if no cases. 471 472 SwitchStmt * mutStmt = mutate( stmt ); 472 if ( mutStmt-> cases.empty() ) {473 mutStmt-> cases.push_back( new CaseClause( mutStmt->location, nullptr, {} ) );474 } 475 476 auto caseStmt = mutStmt-> cases.back().get();473 if ( mutStmt->stmts.empty() ) { 474 mutStmt->stmts.push_back( new CaseStmt( mutStmt->location, nullptr, {} ) ); 475 } 476 477 auto caseStmt = mutStmt->stmts.back().strict_as<CaseStmt>(); 477 478 auto mutCase = mutate( caseStmt ); 478 mutStmt-> cases.back() = mutCase;479 mutStmt->stmts.back() = mutCase; 479 480 480 481 Label label( mutCase->location, "breakLabel" ); … … 513 514 } 514 515 515 void MultiLevelExitCore::previsit( const Finally Clause* ) {516 void MultiLevelExitCore::previsit( const FinallyStmt * ) { 516 517 GuardAction([this, old = move( enclosing_control_structures)](){ enclosing_control_structures = move(old); }); 517 518 enclosing_control_structures = vector<Entry>();
Note:
See TracChangeset
for help on using the changeset viewer.