[Python-checkins] gh-99708: fix bug where compiler crashes on if expression with an empty body block (GH-99732)
iritkatriel
webhook-mailer at python.org
Thu Nov 24 05:59:14 EST 2022
https://github.com/python/cpython/commit/ae185fdcca9d48aef425468de8a8a31300280932
commit: ae185fdcca9d48aef425468de8a8a31300280932
branch: main
author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com>
committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com>
date: 2022-11-24T10:59:07Z
summary:
gh-99708: fix bug where compiler crashes on if expression with an empty body block (GH-99732)
files:
A Misc/NEWS.d/next/Core and Builtins/2022-11-23-18-16-18.gh-issue-99708.7MuaiR.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 791f20bbad03..998ce57927f1 100644
--- a/Lib/test/test_compile.py
+++ b/Lib/test/test_compile.py
@@ -1146,6 +1146,17 @@ def test_compare_positions(self):
with self.subTest(source):
self.assertEqual(actual_positions, expected_positions)
+ def test_if_expression_expression_empty_block(self):
+ # See regression in gh-99708
+ exprs = [
+ "assert (False if 1 else True)",
+ "def f():\n\tif not (False if 1 else True): raise AssertionError",
+ "def f():\n\tif not (False if 1 else True): return 12",
+ ]
+ for expr in exprs:
+ with self.subTest(expr=expr):
+ compile(expr, "<single>", "exec")
+
@requires_debug_ranges()
class TestSourcePositions(unittest.TestCase):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-11-23-18-16-18.gh-issue-99708.7MuaiR.rst b/Misc/NEWS.d/next/Core and Builtins/2022-11-23-18-16-18.gh-issue-99708.7MuaiR.rst
new file mode 100644
index 000000000000..47f385c2eefe
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-11-23-18-16-18.gh-issue-99708.7MuaiR.rst
@@ -0,0 +1 @@
+Fix bug where compiler crashes on an if expression with an empty body block.
diff --git a/Python/compile.c b/Python/compile.c
index 366321143a54..dd8596defb8e 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -512,7 +512,7 @@ static int compiler_match(struct compiler *, stmt_ty);
static int compiler_pattern_subpattern(struct compiler *,
pattern_ty, pattern_context *);
-static void remove_redundant_nops(basicblock *bb);
+static int remove_redundant_nops(basicblock *bb);
static PyCodeObject *assemble(struct compiler *, int addNone);
@@ -8666,6 +8666,17 @@ static void
propagate_line_numbers(basicblock *entryblock);
#ifndef NDEBUG
+
+static bool
+no_redundant_nops(cfg_builder *g) {
+ for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
+ if (remove_redundant_nops(b) != 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
static bool
no_redundant_jumps(cfg_builder *g) {
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
@@ -9435,7 +9446,7 @@ inline_small_exit_blocks(basicblock *bb) {
return 0;
}
-static void
+static int
remove_redundant_nops(basicblock *bb) {
/* Remove NOPs when legal to do so. */
int dest = 0;
@@ -9483,7 +9494,9 @@ remove_redundant_nops(basicblock *bb) {
prev_lineno = lineno;
}
assert(dest <= bb->b_iused);
+ int num_removed = bb->b_iused - dest;
bb->b_iused = dest;
+ return num_removed;
}
static int
@@ -9694,10 +9707,11 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
b->b_iused = 0;
}
}
- eliminate_empty_basic_blocks(g);
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
remove_redundant_nops(b);
}
+ eliminate_empty_basic_blocks(g);
+ assert(no_redundant_nops(g));
if (remove_redundant_jumps(g) < 0) {
return -1;
}
More information about the Python-checkins
mailing list