diff options
-rw-r--r-- | Lib/test/test_compile.py | 18 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2019-10-30-11-25-25.bpo-38640.4sAFh5.rst | 3 | ||||
-rw-r--r-- | Python/compile.c | 8 |
3 files changed, 29 insertions, 0 deletions
diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 9d77f7a..566ca27 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -731,6 +731,24 @@ if 1: self.assertEqual(None, opcodes[0].argval) self.assertEqual('RETURN_VALUE', opcodes[1].opname) + def test_false_while_loop(self): + def break_in_while(): + while False: + break + + def continue_in_while(): + while False: + continue + + funcs = [break_in_while, continue_in_while] + + # Check that we did not raise but we also don't generate bytecode + for func in funcs: + opcodes = list(dis.get_instructions(func)) + self.assertEqual(2, len(opcodes)) + self.assertEqual('LOAD_CONST', opcodes[0].opname) + self.assertEqual(None, opcodes[0].argval) + self.assertEqual('RETURN_VALUE', opcodes[1].opname) class TestExpressionStackSize(unittest.TestCase): # These tests check that the computed stack size for a code object diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-10-30-11-25-25.bpo-38640.4sAFh5.rst b/Misc/NEWS.d/next/Core and Builtins/2019-10-30-11-25-25.bpo-38640.4sAFh5.rst new file mode 100644 index 0000000..d99db3c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-10-30-11-25-25.bpo-38640.4sAFh5.rst @@ -0,0 +1,3 @@ +Fixed a bug in the compiler that was causing to raise in the presence of +break statements and continue statements inside always false while loops. +Patch by Pablo Galindo. diff --git a/Python/compile.c b/Python/compile.c index 3b2188e..f26ad3c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -2738,7 +2738,15 @@ compiler_while(struct compiler *c, stmt_ty s) if (constant == 0) { BEGIN_DO_NOT_EMIT_BYTECODE + // Push a dummy block so the VISIT_SEQ knows that we are + // inside a while loop so it can correctly evaluate syntax + // errors. + if (!compiler_push_fblock(c, WHILE_LOOP, NULL, NULL)) { + return 0; + } VISIT_SEQ(c, stmt, s->v.While.body); + // Remove the dummy block now that is not needed. + compiler_pop_fblock(c, WHILE_LOOP, NULL); END_DO_NOT_EMIT_BYTECODE if (s->v.While.orelse) { VISIT_SEQ(c, stmt, s->v.While.orelse); |