Skip to content

Commit b142622

Browse files
committed
Make sure implicit returns directly following for-loops have the correct line number.
1 parent 33d3cb8 commit b142622

File tree

4 files changed

+1080
-3358
lines changed

4 files changed

+1080
-3358
lines changed

Lib/test/test_dis.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,14 @@ def bug708901():
131131
12 STORE_FAST 0 (res)
132132
133133
%3d 14 JUMP_ABSOLUTE 10
134-
>> 16 LOAD_CONST 0 (None)
134+
135+
%3d >> 16 LOAD_CONST 0 (None)
135136
18 RETURN_VALUE
136137
""" % (bug708901.__code__.co_firstlineno + 1,
137138
bug708901.__code__.co_firstlineno + 2,
138139
bug708901.__code__.co_firstlineno + 1,
139-
bug708901.__code__.co_firstlineno + 3)
140+
bug708901.__code__.co_firstlineno + 3,
141+
bug708901.__code__.co_firstlineno + 1)
140142

141143

142144
def bug1333982(x=[]):

Python/compile.c

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2754,12 +2754,13 @@ compiler_if(struct compiler *c, stmt_ty s)
27542754
static int
27552755
compiler_for(struct compiler *c, stmt_ty s)
27562756
{
2757-
basicblock *start, *cleanup, *end;
2757+
basicblock *start, *body, *cleanup, *end;
27582758

27592759
start = compiler_new_block(c);
2760+
body = compiler_new_block(c);
27602761
cleanup = compiler_new_block(c);
27612762
end = compiler_new_block(c);
2762-
if (start == NULL || end == NULL || cleanup == NULL) {
2763+
if (start == NULL || body == NULL || end == NULL || cleanup == NULL) {
27632764
return 0;
27642765
}
27652766
if (!compiler_push_fblock(c, FOR_LOOP, start, end, NULL)) {
@@ -2769,6 +2770,7 @@ compiler_for(struct compiler *c, stmt_ty s)
27692770
ADDOP(c, GET_ITER);
27702771
compiler_use_next_block(c, start);
27712772
ADDOP_JUMP(c, FOR_ITER, cleanup);
2773+
compiler_use_next_block(c, body);
27722774
VISIT(c, expr, s->v.For.target);
27732775
VISIT_SEQ(c, stmt, s->v.For.body);
27742776
ADDOP_JUMP(c, JUMP_ABSOLUTE, start);
@@ -5953,7 +5955,7 @@ dump_basicblock(const basicblock *b)
59535955

59545956

59555957
static int
5956-
normalize_basic_block(basicblock *bb) ;
5958+
normalize_cfg(basicblock *bb);
59575959

59585960
static int
59595961
optimize_cfg(struct assembler *a, PyObject *consts);
@@ -5981,10 +5983,8 @@ assemble(struct compiler *c, int addNone)
59815983
ADDOP(c, RETURN_VALUE);
59825984
}
59835985

5984-
for (b = c->u->u_blocks; b != NULL; b = b->b_list) {
5985-
if (normalize_basic_block(b)) {
5986-
goto error;
5987-
}
5986+
if (normalize_cfg(c->u->u_blocks)) {
5987+
goto error;
59885988
}
59895989

59905990
if (ensure_exits_have_lineno(c)) {
@@ -6388,7 +6388,8 @@ normalize_basic_block(basicblock *bb) {
63886388
case RAISE_VARARGS:
63896389
case RERAISE:
63906390
bb->b_exit = 1;
6391-
/* fall through */
6391+
bb->b_nofallthrough = 1;
6392+
break;
63926393
case JUMP_ABSOLUTE:
63936394
case JUMP_FORWARD:
63946395
bb->b_nofallthrough = 1;
@@ -6397,10 +6398,27 @@ normalize_basic_block(basicblock *bb) {
63976398
case POP_JUMP_IF_TRUE:
63986399
case JUMP_IF_FALSE_OR_POP:
63996400
case JUMP_IF_TRUE_OR_POP:
6401+
case FOR_ITER:
64006402
if (i != bb->b_iused-1) {
64016403
PyErr_SetString(PyExc_SystemError, "malformed control flow graph.");
64026404
return -1;
64036405
}
6406+
/* Skip over empty basic blocks. */
6407+
while (bb->b_instr[i].i_target->b_iused == 0) {
6408+
bb->b_instr[i].i_target = bb->b_instr[i].i_target->b_next;
6409+
}
6410+
6411+
}
6412+
}
6413+
return 0;
6414+
}
6415+
6416+
6417+
static int
6418+
normalize_cfg(basicblock *b) {
6419+
for (; b != NULL; b = b->b_list) {
6420+
if (normalize_basic_block(b)) {
6421+
return -1;
64046422
}
64056423
}
64066424
return 0;
@@ -6490,15 +6508,7 @@ optimize_cfg(struct assembler *a, PyObject *consts)
64906508

64916509
static int
64926510
is_exit_without_lineno(basicblock *b) {
6493-
if (!b->b_exit) {
6494-
return 0;
6495-
}
6496-
for (int i = 0; i < b->b_iused; i++) {
6497-
if (b->b_instr[i].i_lineno >= 0) {
6498-
return 0;
6499-
}
6500-
}
6501-
return 1;
6511+
return b->b_exit && b->b_instr[0].i_lineno < 0;
65026512
}
65036513

65046514
/* PEP 626 mandates that the f_lineno of a frame is correct

Python/importlib.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)