[Python-checkins] bpo-38640: Allow break and continue in always false while loops (GH-16992)

Pablo Galindo webhook-mailer at python.org
Wed Oct 30 07:53:30 EDT 2019


https://github.com/python/cpython/commit/6c3e66a34b95fff07df0ad5086104dd637a091ce
commit: 6c3e66a34b95fff07df0ad5086104dd637a091ce
branch: master
author: Pablo Galindo <Pablogsal at gmail.com>
committer: GitHub <noreply at github.com>
date: 2019-10-30T11:53:26Z
summary:

bpo-38640: Allow break and continue in always false while loops (GH-16992)

files:
A Misc/NEWS.d/next/Core and Builtins/2019-10-30-11-25-25.bpo-38640.4sAFh5.rst
M Lib/test/test_compile.py
M Python/compile.c

diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py
index 9d77f7af05d6f..566ca27fca893 100644
--- a/Lib/test/test_compile.py
+++ b/Lib/test/test_compile.py
@@ -731,6 +731,24 @@ def unused_block_while_else():
             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 0000000000000..d99db3cce49a6
--- /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 3b2188e6e7438..f26ad3c775255 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);



More information about the Python-checkins mailing list