Changeset c248b39 for src


Ignore:
Timestamp:
Jul 18, 2024, 12:52:39 PM (5 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
master
Children:
f107afe
Parents:
6804f38
Message:

Unlabelled breaks were not targetting the correct enclosing control structures. Also added a test and improved error messages.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/MultiLevelExit.cpp

    r6804f38 rc248b39  
    8484        bool isFallDefaultTarget() const { return kind == SwitchStmtK; }
    8585
     86        // Check if this entry can be the target of an unlabelled break.
     87        bool isUnlabelledBreakTarget() const { return kind <= WhileDoStmtK || kind == SwitchStmtK; }
     88
    8689        // These routines set a target as being "used" by a BranchStmt
    8790        Label useContExit() { assert( kind <= WhileDoStmtK ); return useTarget(secondTarget); }
     
    114117bool isFallthroughDefaultTarget( const Entry & entry ) {
    115118        return entry.isFallDefaultTarget();
     119}
     120
     121bool isUnlabelledBreakTarget( const Entry & entry ) {
     122        return entry.isUnlabelledBreakTarget();
    116123}
    117124
     
    247254        case BranchStmt::Break: {
    248255                bool isContinue = stmt->kind == BranchStmt::Continue;
    249                 // Handle unlabeled break and continue.
    250                 if ( stmt->target.empty() ) {
    251                         if ( isContinue ) {
    252                                 targetEntry = findEnclosingControlStructure( isContinueTarget );
    253                         } else {
    254                                 if ( enclosing_control_structures.empty() ) {
    255                                           SemanticError( stmt->location,
    256                                                                          "\"break\" outside a loop, \"switch\", or labelled block" );
    257                                 }
    258                                 targetEntry = findEnclosingControlStructure( isBreakTarget );
     256                // Handle unlabeled continue.
     257                if ( isContinue && stmt->target.empty() ) {
     258                        targetEntry = findEnclosingControlStructure( isContinueTarget );
     259                        if ( targetEntry == enclosing_control_structures.rend() ) {
     260                                SemanticError( stmt->location,
     261                                               "\"continue\" outside a loop" );
    259262                        }
    260                         // Handle labeled break and continue.
     263                // Handle unlabeled break.
     264                } else if ( stmt->target.empty() ) {
     265                        targetEntry = findEnclosingControlStructure( isUnlabelledBreakTarget );
     266                        if ( targetEntry == enclosing_control_structures.rend() ) {
     267                                SemanticError( stmt->location,
     268                                               "\"break\" outside a loop or \"switch\"" );
     269                        }
     270                // Handle labeled break and continue.
    261271                } else {
    262272                        // Lookup label in table to find attached control structure.
     
    265275                                          return entry.stmt == targetStmt;
    266276                                } );
    267                 }
    268                 // Ensure that selected target is valid.
    269                 if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && ! isContinueTarget( *targetEntry ) ) ) {
    270                         SemanticError( stmt->location, toString( (isContinue ? "\"continue\"" : "\"break\""),
    271                                                         " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "),
    272                                                         stmt->originalTarget ) );
     277                        // Ensure that selected target is valid.
     278                        if ( targetEntry == enclosing_control_structures.rend()
     279                                        || ( isContinue ? !isContinueTarget( *targetEntry ) : !isBreakTarget( *targetEntry ) ) ) {
     280                                SemanticError( stmt->location, toString( (isContinue ? "\"continue\"" : "\"break\""),
     281                                               " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "),
     282                                               stmt->originalTarget ) );
     283                        }
    273284                }
    274285                break;
Note: See TracChangeset for help on using the changeset viewer.