diff --git a/src/builtin.cpp b/src/builtin.cpp index 78030a4d8..7dd35f1c7 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -271,6 +271,7 @@ static maybe_t builtin_break_continue(parser_t &parser, io_streams_t &strea } // Paranoia: ensure we have a real loop. + // This is checked in the AST but we may be invoked dynamically, e.g. just via "eval break". bool has_loop = false; for (const auto &b : parser.blocks()) { if (b.type() == block_type_t::while_block || b.type() == block_type_t::for_block) { diff --git a/tests/checks/basic.fish b/tests/checks/basic.fish index e230c8aed..1cf4a6902 100644 --- a/tests/checks/basic.fish +++ b/tests/checks/basic.fish @@ -406,6 +406,34 @@ while contains $i a end #CHECK: Doop +# break and continue may be dynamically invoked. +set dyn_break break +set dyn_continue continue + +while true + $dyn_break + echo "I should be unreachable" +end + +for foo in 1 2 3 + $dyn_continue + echo "I should be unreachable" +end + +# Check that these error correctly. +# Simplify __fish_print_help, as it's noisy. +function __fish_print_help + echo $argv[2..] +end +$dyn_break +eval break +#CHECKERR: break: Not inside of loop +#CHECKERR: break: Not inside of loop +$dyn_continue +eval continue +#CHECKERR: continue: Not inside of loop +#CHECKERR: continue: Not inside of loop + # Test implicit cd. This should do nothing. ./