mirror of
https://github.com/python/cpython.git
synced 2025-08-28 20:56:54 +00:00
bpo-44298: Fix line numbers for early exits in with statements. (GH-26513)
This commit is contained in:
parent
4eed2821d4
commit
937cebc93b
4 changed files with 3036 additions and 2980 deletions
|
@ -995,6 +995,52 @@ class TraceTestCase(unittest.TestCase):
|
||||||
(5, 'line'),
|
(5, 'line'),
|
||||||
(5, 'return')])
|
(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):
|
class SkipLineEventsTraceTestCase(TraceTestCase):
|
||||||
"""Repeat the trace tests, but with per-line events skipped"""
|
"""Repeat the trace tests, but with per-line events skipped"""
|
||||||
|
|
|
@ -1796,7 +1796,6 @@ static int
|
||||||
compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
|
compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
|
||||||
int preserve_tos)
|
int preserve_tos)
|
||||||
{
|
{
|
||||||
int loc;
|
|
||||||
switch (info->fb_type) {
|
switch (info->fb_type) {
|
||||||
case WHILE_LOOP:
|
case WHILE_LOOP:
|
||||||
case EXCEPTION_HANDLER:
|
case EXCEPTION_HANDLER:
|
||||||
|
@ -1850,7 +1849,6 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
|
||||||
|
|
||||||
case WITH:
|
case WITH:
|
||||||
case ASYNC_WITH:
|
case ASYNC_WITH:
|
||||||
loc = c->u->u_lineno;
|
|
||||||
SET_LOC(c, (stmt_ty)info->fb_datum);
|
SET_LOC(c, (stmt_ty)info->fb_datum);
|
||||||
ADDOP(c, POP_BLOCK);
|
ADDOP(c, POP_BLOCK);
|
||||||
if (preserve_tos) {
|
if (preserve_tos) {
|
||||||
|
@ -1865,7 +1863,10 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
|
||||||
ADDOP(c, YIELD_FROM);
|
ADDOP(c, YIELD_FROM);
|
||||||
}
|
}
|
||||||
ADDOP(c, POP_TOP);
|
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;
|
return 1;
|
||||||
|
|
||||||
case HANDLER_CLEANUP:
|
case HANDLER_CLEANUP:
|
||||||
|
@ -3020,12 +3021,17 @@ compiler_return(struct compiler *c, stmt_ty s)
|
||||||
if (preserve_tos) {
|
if (preserve_tos) {
|
||||||
VISIT(c, expr, s->v.Return.value);
|
VISIT(c, expr, s->v.Return.value);
|
||||||
} else {
|
} else {
|
||||||
/* Emit instruction with line number for expression */
|
/* Emit instruction with line number for return value */
|
||||||
if (s->v.Return.value != NULL) {
|
if (s->v.Return.value != NULL) {
|
||||||
SET_LOC(c, s->v.Return.value);
|
SET_LOC(c, s->v.Return.value);
|
||||||
ADDOP(c, NOP);
|
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))
|
if (!compiler_unwind_fblock_stack(c, preserve_tos, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
if (s->v.Return.value == NULL) {
|
if (s->v.Return.value == NULL) {
|
||||||
|
@ -3044,6 +3050,8 @@ static int
|
||||||
compiler_break(struct compiler *c)
|
compiler_break(struct compiler *c)
|
||||||
{
|
{
|
||||||
struct fblockinfo *loop = NULL;
|
struct fblockinfo *loop = NULL;
|
||||||
|
/* Emit instruction with line number */
|
||||||
|
ADDOP(c, NOP);
|
||||||
if (!compiler_unwind_fblock_stack(c, 0, &loop)) {
|
if (!compiler_unwind_fblock_stack(c, 0, &loop)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3062,6 +3070,8 @@ static int
|
||||||
compiler_continue(struct compiler *c)
|
compiler_continue(struct compiler *c)
|
||||||
{
|
{
|
||||||
struct fblockinfo *loop = NULL;
|
struct fblockinfo *loop = NULL;
|
||||||
|
/* Emit instruction with line number */
|
||||||
|
ADDOP(c, NOP);
|
||||||
if (!compiler_unwind_fblock_stack(c, 0, &loop)) {
|
if (!compiler_unwind_fblock_stack(c, 0, &loop)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
3544
Python/importlib.h
generated
3544
Python/importlib.h
generated
File diff suppressed because it is too large
Load diff
2402
Python/importlib_external.h
generated
2402
Python/importlib_external.h
generated
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue