Skip to content
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