diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2019-08-24 10:41:53 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-24 10:41:53 (GMT) |
commit | ed146b52a3b6537689324e3bd9952055f9c6b43d (patch) | |
tree | 7774469736dadc9848896f83b3669ad831ec8a32 /Objects | |
parent | 920ec4b7763d64b3742d7ddd339ad11cdbec62e9 (diff) | |
download | cpython-ed146b52a3b6537689324e3bd9952055f9c6b43d.zip cpython-ed146b52a3b6537689324e3bd9952055f9c6b43d.tar.gz cpython-ed146b52a3b6537689324e3bd9952055f9c6b43d.tar.bz2 |
[3.8] bpo-37830: Fix compilation of break and continue in finally. (GH-15320) (GH-15456)
Fix compilation of "break" and "continue" in the
"finally" block when the corresponding "try" block
contains "return" with a non-constant value.
(cherry picked from commit ef61c524ddeeb56da3858b86e349e7288d68178e)
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/frameobject.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 5deb985..a796a59 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -233,6 +233,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore * the 'finally' blocks. */ memset(blockstack, '\0', sizeof(blockstack)); blockstack_top = 0; + unsigned char prevop = NOP; for (addr = 0; addr < code_len; addr += sizeof(_Py_CODEUNIT)) { unsigned char op = code[addr]; switch (op) { @@ -259,17 +260,24 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore "can't jump into the middle of a block"); return -1; } + int in_for_loop = op == FOR_ITER || code[target_addr] == END_ASYNC_FOR; if (first_in && !second_in) { - if (op != FOR_ITER && code[target_addr] != END_ASYNC_FOR) { - delta_iblock++; + if (!delta_iblock) { + if (in_for_loop) { + /* Pop the iterators of any 'for' and 'async for' loop + * we're jumping out of. */ + delta++; + } + else if (prevop == LOAD_CONST) { + /* Pops None pushed before SETUP_FINALLY. */ + delta++; + } } - else if (!delta_iblock) { - /* Pop the iterators of any 'for' and 'async for' loop - * we're jumping out of. */ - delta++; + if (!in_for_loop) { + delta_iblock++; } } - if (op != FOR_ITER && code[target_addr] != END_ASYNC_FOR) { + if (!in_for_loop) { blockstack[blockstack_top++] = target_addr; } break; @@ -293,6 +301,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore break; } } + prevop = op; } /* Verify that the blockstack tracking code didn't get lost. */ |