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