Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 6066945

Browse files
committedNov 23, 2022
pythongh-99708: fix bug where compiler crashes on if expression with an empty body block
1 parent 5d9183c commit 6066945

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed
 

‎Lib/test/test_compile.py

+11
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,17 @@ def test_compare_positions(self):
11461146
with self.subTest(source):
11471147
self.assertEqual(actual_positions, expected_positions)
11481148

1149+
def test_if_expression_expression_empty_block(self):
1150+
# See regression in gh-99708
1151+
exprs = [
1152+
"assert (False if 1 else True)",
1153+
"def f():\n\tif not (False if 1 else True): raise AssertionError",
1154+
"def f():\n\tif not (False if 1 else True): return 12",
1155+
]
1156+
for expr in exprs:
1157+
with self.subTest(expr=expr):
1158+
compile(expr, "<single>", "exec")
1159+
11491160

11501161
@requires_debug_ranges()
11511162
class TestSourcePositions(unittest.TestCase):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix bug where compiler crashes on an if expression with an empty body block.

‎Python/compile.c

+19-3
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ static int compiler_match(struct compiler *, stmt_ty);
512512
static int compiler_pattern_subpattern(struct compiler *,
513513
pattern_ty, pattern_context *);
514514

515-
static void remove_redundant_nops(basicblock *bb);
515+
static int remove_redundant_nops(basicblock *bb);
516516

517517
static PyCodeObject *assemble(struct compiler *, int addNone);
518518

@@ -8666,6 +8666,18 @@ static void
86668666
propagate_line_numbers(basicblock *entryblock);
86678667

86688668
#ifndef NDEBUG
8669+
8670+
static bool
8671+
no_redundant_nops(cfg_builder *g) {
8672+
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
8673+
if (remove_redundant_nops(b) != 0) {
8674+
return false;
8675+
}
8676+
}
8677+
return true;
8678+
}
8679+
8680+
86698681
static bool
86708682
no_redundant_jumps(cfg_builder *g) {
86718683
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
@@ -9435,7 +9447,7 @@ inline_small_exit_blocks(basicblock *bb) {
94359447
return 0;
94369448
}
94379449

9438-
static void
9450+
static int
94399451
remove_redundant_nops(basicblock *bb) {
94409452
/* Remove NOPs when legal to do so. */
94419453
int dest = 0;
@@ -9483,7 +9495,9 @@ remove_redundant_nops(basicblock *bb) {
94839495
prev_lineno = lineno;
94849496
}
94859497
assert(dest <= bb->b_iused);
9498+
int num_removed = bb->b_iused - dest;
94869499
bb->b_iused = dest;
9500+
return num_removed;
94879501
}
94889502

94899503
static int
@@ -9688,16 +9702,18 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
96889702
if (mark_reachable(g->g_entryblock)) {
96899703
return -1;
96909704
}
9705+
96919706
/* Delete unreachable instructions */
96929707
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
96939708
if (b->b_predecessors == 0) {
96949709
b->b_iused = 0;
96959710
}
96969711
}
9697-
eliminate_empty_basic_blocks(g);
96989712
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
96999713
remove_redundant_nops(b);
97009714
}
9715+
eliminate_empty_basic_blocks(g);
9716+
assert(no_redundant_nops(g));
97019717
if (remove_redundant_jumps(g) < 0) {
97029718
return -1;
97039719
}

0 commit comments

Comments
 (0)
Please sign in to comment.