From e5f3f978a6fbccfb0dae438a0a8f108ce7db1e5d Mon Sep 17 00:00:00 2001 From: Kevin Egan Date: Sat, 29 Nov 2025 01:43:59 -0500 Subject: [PATCH 1/2] Add _for_break variable when we break inside of nested do/while(false) loop (#1436) --- source/to_cpp1.h | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/source/to_cpp1.h b/source/to_cpp1.h index ba23101d9..ec3d6f7b2 100644 --- a/source/to_cpp1.h +++ b/source/to_cpp1.h @@ -2409,18 +2409,17 @@ class cppfront printer.print_extra("{"); } - // 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 there's a next-expression, smuggle it in via a nested do/while(false) loop. + // We implement break as "_for_break = true; continue;") if (n.next_expression) { - printer.print_cpp2(" { do ", n.position()); + printer.print_cpp2(" { bool _for_break = false; do ", n.position()); } assert(n.body); emit(*n.body); if (n.next_expression) { - printer.print_cpp2(" while (false); ", n.position()); + printer.print_cpp2(" while (false); if (_for_break) { break; } ", n.position()); emit(*n.next_expression); printer.print_cpp2("; }", n.position()); } @@ -2684,8 +2683,14 @@ class cppfront ); } else { - emit(*n.keyword); - printer.print_cpp2(";", n.position()); + if (*n.keyword == "break" && iteration_statements.back().stmt->next_expression + && *(iteration_statements.back().stmt->identifier) == "for") { + // if we have a next expression there is an nested "do/while(false) loop + printer.print_cpp2("_for_break = true; continue;", n.position()); + } else { + emit(*n.keyword); + printer.print_cpp2(";", n.position()); + } } } From 51f0bb80812b819291df91dff1c907753151cd3c Mon Sep 17 00:00:00 2001 From: Kevin Egan Date: Sat, 29 Nov 2025 01:45:14 -0500 Subject: [PATCH 2/2] Changes in regression-tests adding _for_break variable (#1436) --- .../test-results/mixed-bounds-safety-with-assert-2.cpp | 4 ++-- .../test-results/mixed-bounds-safety-with-assert.cpp | 4 ++-- .../mixed-intro-for-with-counter-include-last.cpp | 4 ++-- regression-tests/test-results/pure2-autodiff-higher-order.cpp | 4 ++-- regression-tests/test-results/pure2-autodiff.cpp | 4 ++-- .../test-results/pure2-for-loop-range-with-lambda.cpp | 4 ++-- regression-tests/test-results/pure2-last-use.cpp | 4 ++-- regression-tests/test-results/pure2-print.cpp | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/regression-tests/test-results/mixed-bounds-safety-with-assert-2.cpp b/regression-tests/test-results/mixed-bounds-safety-with-assert-2.cpp index 1538a6d5b..1408dff0b 100644 --- a/regression-tests/test-results/mixed-bounds-safety-with-assert-2.cpp +++ b/regression-tests/test-results/mixed-bounds-safety-with-assert-2.cpp @@ -46,9 +46,9 @@ auto add_42_to_subrange(auto& rng, cpp2::impl::in start, cpp2::impl::in start, cpp2::impl::in v {1, 2, 3, 4, 5}; auto counter {42}; - for ( auto const& i : cpp2::move(v) ) { do { + for ( auto const& i : cpp2::move(v) ) { bool _for_break = false; do { std::cout << i << " " << counter << "\n"; - } while (false); counter *= 2; } + } while (false); if (_for_break) { break; } counter *= 2; } } diff --git a/regression-tests/test-results/pure2-autodiff-higher-order.cpp b/regression-tests/test-results/pure2-autodiff-higher-order.cpp index 118fe0fd0..17fb559c8 100644 --- a/regression-tests/test-results/pure2-autodiff-higher-order.cpp +++ b/regression-tests/test-results/pure2-autodiff-higher-order.cpp @@ -972,7 +972,7 @@ std::vector> v_d {}; r = 0.0; { auto t_d_iter{CPP2_UFCS(begin)(cpp2::move(v_d))}; - for ( auto const& t : cpp2::move(v) ) { do { + for ( auto const& t : cpp2::move(v) ) { bool _for_break = false; do { { auto const& t_d{*cpp2::impl::assert_not_null(t_d_iter)}; { @@ -981,7 +981,7 @@ auto const& t_d{*cpp2::impl::assert_not_null(t_d_iter)}; } } } - while (false); (++t_d_iter); } + while (false); if (_for_break) { break; } (++t_d_iter); } } return { std::move(r), std::move(r_d) }; } diff --git a/regression-tests/test-results/pure2-autodiff.cpp b/regression-tests/test-results/pure2-autodiff.cpp index f4c551bd4..3948887a4 100644 --- a/regression-tests/test-results/pure2-autodiff.cpp +++ b/regression-tests/test-results/pure2-autodiff.cpp @@ -1186,7 +1186,7 @@ std::vector v_d {}; r = 0.0; { auto t_d_iter{CPP2_UFCS(begin)(cpp2::move(v_d))}; - for ( auto const& t : cpp2::move(v) ) { do { + for ( auto const& t : cpp2::move(v) ) { bool _for_break = false; do { { auto const& t_d{*cpp2::impl::assert_not_null(t_d_iter)}; { @@ -1195,7 +1195,7 @@ auto const& t_d{*cpp2::impl::assert_not_null(t_d_iter)}; } } } - while (false); (++t_d_iter); } + while (false); if (_for_break) { break; } (++t_d_iter); } } return { std::move(r), std::move(r_d) }; } diff --git a/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp b/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp index 1a1256651..23c3d1090 100644 --- a/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp +++ b/regression-tests/test-results/pure2-for-loop-range-with-lambda.cpp @@ -50,7 +50,7 @@ auto main(int const argc_, char** argv_) -> int{ for ( auto const& i : [_0 = args]() mutable -> decltype(auto) { return _0; }() ) static_cast(i); for ( auto const& j : [](auto&& x) -> decltype(auto) { return CPP2_FORWARD(x); }(args) ) static_cast(j); - for ( auto const& k : [](auto&& x) -> decltype(auto) { return CPP2_FORWARD(x); }(args) ) { do static_cast(k); while (false); static_cast([_0 = args]() mutable -> decltype(auto) { return _0; }()); } - for ( auto const& l : [](auto&& x) -> decltype(auto) { return CPP2_FORWARD(x); }(args) ) { do static_cast(l); while (false); static_cast([](auto&& x) -> decltype(auto) { return x; }(args)); } + for ( auto const& k : [](auto&& x) -> decltype(auto) { return CPP2_FORWARD(x); }(args) ) { bool _for_break = false; do static_cast(k); while (false); if (_for_break) { break; } static_cast([_0 = args]() mutable -> decltype(auto) { return _0; }()); } + for ( auto const& l : [](auto&& x) -> decltype(auto) { return CPP2_FORWARD(x); }(args) ) { bool _for_break = false; do static_cast(l); while (false); if (_for_break) { break; } static_cast([](auto&& x) -> decltype(auto) { return x; }(args)); } } diff --git a/regression-tests/test-results/pure2-last-use.cpp b/regression-tests/test-results/pure2-last-use.cpp index 32bbed35e..ce3e79096 100644 --- a/regression-tests/test-results/pure2-last-use.cpp +++ b/regression-tests/test-results/pure2-last-use.cpp @@ -1393,8 +1393,8 @@ auto loops() -> void{ auto x {cpp2_new(0)}; for ( - [[maybe_unused]] auto const& unnamed_param_1 : { 0 } ) { do - {} while (false); f_inout(x); } + [[maybe_unused]] auto const& unnamed_param_1 : { 0 } ) { bool _for_break = false; do + {} while (false); if (_for_break) { break; } f_inout(x); } }); static_cast([]() -> void{ diff --git a/regression-tests/test-results/pure2-print.cpp b/regression-tests/test-results/pure2-print.cpp index 7d2c1c86e..d1cf87cda 100644 --- a/regression-tests/test-results/pure2-print.cpp +++ b/regression-tests/test-results/pure2-print.cpp @@ -140,7 +140,7 @@ requires (true) inline CPP2_CONSTEXPR T outer::object_alias{ 42 }; do {} while ( [&]{ b() ; return true; }() && CPP2_UFCS(empty)(s)); - for ( [[maybe_unused]] auto const& unnamed_param_1 : m ) { { do {goto CONTINUE_label; } while (false); c(); } CPP2_CONTINUE_BREAK(label) } + for ( [[maybe_unused]] auto const& unnamed_param_1 : m ) { { bool _for_break = false; do {goto CONTINUE_label; } while (false); if (_for_break) { break; } c(); } CPP2_CONTINUE_BREAK(label) } #line 47 "pure2-print.cpp2" if (cpp2::impl::is(!(CPP2_UFCS(empty)(s)), (true))) {cpp2::move(a)(); }