summaryrefslogtreecommitdiffstats
path: root/Objects/frameobject.c
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2019-08-24 10:11:52 (GMT)
committerGitHub <noreply@github.com>2019-08-24 10:11:52 (GMT)
commitef61c524ddeeb56da3858b86e349e7288d68178e (patch)
treee8a9defe85faff05464db6335140eb0990499f15 /Objects/frameobject.c
parente9c90aa43144b0be1e4e393e8cb549573437a5da (diff)
downloadcpython-ef61c524ddeeb56da3858b86e349e7288d68178e.zip
cpython-ef61c524ddeeb56da3858b86e349e7288d68178e.tar.gz
cpython-ef61c524ddeeb56da3858b86e349e7288d68178e.tar.bz2
bpo-37830: Fix compilation of break and continue in finally. (GH-15320)
Fix compilation of "break" and "continue" in the "finally" block when the corresponding "try" block contains "return" with a non-constant value.
Diffstat (limited to 'Objects/frameobject.c')
-rw-r--r--Objects/frameobject.c23
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. */