bpo-44298: Fix line numbers for early exits in with statements. (GH-26513)

This commit is contained in:
Mark Shannon 2021-06-03 16:45:58 +01:00 committed by GitHub
parent 4eed2821d4
commit 937cebc93b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 3036 additions and 2980 deletions

View File

@ -995,6 +995,52 @@ class TraceTestCase(unittest.TestCase):
(5, 'line'),
(5, 'return')])
def test_early_exit_with(self):
class C:
def __enter__(self):
return self
def __exit__(*args):
pass
def func_break():
for i in (1,2):
with C():
break
pass
def func_return():
with C():
return
self.run_and_compare(func_break,
[(0, 'call'),
(1, 'line'),
(2, 'line'),
(-5, 'call'),
(-4, 'line'),
(-4, 'return'),
(3, 'line'),
(2, 'line'),
(-3, 'call'),
(-2, 'line'),
(-2, 'return'),
(4, 'line'),
(4, 'return')])
self.run_and_compare(func_return,
[(0, 'call'),
(1, 'line'),
(-11, 'call'),
(-10, 'line'),
(-10, 'return'),
(2, 'line'),
(1, 'line'),
(-9, 'call'),
(-8, 'line'),
(-8, 'return'),
(1, 'return')])
class SkipLineEventsTraceTestCase(TraceTestCase):
"""Repeat the trace tests, but with per-line events skipped"""

View File

@ -1796,7 +1796,6 @@ static int
compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
int preserve_tos)
{
int loc;
switch (info->fb_type) {
case WHILE_LOOP:
case EXCEPTION_HANDLER:
@ -1850,7 +1849,6 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
case WITH:
case ASYNC_WITH:
loc = c->u->u_lineno;
SET_LOC(c, (stmt_ty)info->fb_datum);
ADDOP(c, POP_BLOCK);
if (preserve_tos) {
@ -1865,7 +1863,10 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
ADDOP(c, YIELD_FROM);
}
ADDOP(c, POP_TOP);
c->u->u_lineno = loc;
/* The exit block should appear to execute after the
* statement causing the unwinding, so make the unwinding
* instruction artificial */
c->u->u_lineno = -1;
return 1;
case HANDLER_CLEANUP:
@ -3020,12 +3021,17 @@ compiler_return(struct compiler *c, stmt_ty s)
if (preserve_tos) {
VISIT(c, expr, s->v.Return.value);
} else {
/* Emit instruction with line number for expression */
/* Emit instruction with line number for return value */
if (s->v.Return.value != NULL) {
SET_LOC(c, s->v.Return.value);
ADDOP(c, NOP);
}
}
if (s->v.Return.value == NULL || s->v.Return.value->lineno != s->lineno) {
SET_LOC(c, s);
ADDOP(c, NOP);
}
if (!compiler_unwind_fblock_stack(c, preserve_tos, NULL))
return 0;
if (s->v.Return.value == NULL) {
@ -3044,6 +3050,8 @@ static int
compiler_break(struct compiler *c)
{
struct fblockinfo *loop = NULL;
/* Emit instruction with line number */
ADDOP(c, NOP);
if (!compiler_unwind_fblock_stack(c, 0, &loop)) {
return 0;
}
@ -3062,6 +3070,8 @@ static int
compiler_continue(struct compiler *c)
{
struct fblockinfo *loop = NULL;
/* Emit instruction with line number */
ADDOP(c, NOP);
if (!compiler_unwind_fblock_stack(c, 0, &loop)) {
return 0;
}

3544
Python/importlib.h generated

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff