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.
This commit is contained in:
Serhiy Storchaka 2019-08-24 13:11:52 +03:00 • committed by GitHub
parent e9c90aa431
commit ef61c524dd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 305 additions and 194 deletions

View file

@ -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) {
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++;
}
}
if (!in_for_loop) {
delta_iblock++;
}
else if (!delta_iblock) {
/* Pop the iterators of any 'for' and 'async for' loop
* we're jumping out of. */
delta++;
}
}
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. */