Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-99708: fix bug where compiler crashes on if expression with an empty body block #99732

Merged
merged 1 commit into from
Nov 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Lib/test/test_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix bug where compiler crashes on an if expression with an empty body block.
20 changes: 17 additions & 3 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down