cppfront icon indicating copy to clipboard operation
cppfront copied to clipboard

[BUG] A for loop that uses a 'next' is not broken out of correctly when using 'break'

Open threeifbyair opened this issue 2 months ago • 1 comments

Describe the bug A Cpp2 for loop that uses 'next' is implemented as a do { } while(false) loop inside the main loop -- and the 'next' is done right after the do () while (false). And there's no special treatment for 'break' in that inner loop.

The consequence is that 'break' only breaks out of the do {} while (false) and not the actual loop.

To Reproduce Steps to reproduce the behavior: In this code at Compiler Explorer:

    myarray: std::array<i32, 4> = (0, 1, 2, 3);
    i := 0;
    for myarray next i++ do (member) {
        if member == 0 {
            break;
        }
    }

    std::cout << "i = " << i << std::endl;
    return i;
}

This should print "i = 1" but instead prints "i = 4".

threeifbyair avatar Nov 02 '25 18:11 threeifbyair

It looks like this is a known limitation, from source/to_cpp1.h

            //  If there's a next-expression, smuggle it in via a nested do/while(false) loop
            //  (nested "continue" will work, but "break" won't until we do extra work to implement
            //  that using a flag and implementing "break" as "_for_break = true; continue;")
            if (n.next_expression) {
                printer.print_cpp2(" { do ", n.position());
            }

A workaround is to use a named loop:

    myloop : for myarray next i++ do (member) {
        if member == 0 {
            break myloop;
        }
    }

For reference if you don't use a named loop the cpp1 code that has the issue looks like this:

    for ( auto const& member : cpp2::move(myarray) )  { do {
        if (member == 0) {
            break;
        }
    } while (false); ++i; }

ktegan avatar Nov 29 '25 04:11 ktegan