diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 791f20bbad032e..998ce57927f1a9 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, "", "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 00000000000000..47f385c2eefee7 --- /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 366321143a54aa..dd8596defb8efe 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; }