[3.9] bpo-39934: Account for control blocks in 'except' in compiler. (GH-22395) (GH-23303)
* bpo-39934: backport PR 22395 to 3.9
diff --git a/Python/compile.c b/Python/compile.c
index 51af28b..722d52d 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -84,8 +84,8 @@
compiler IR.
*/
-enum fblocktype { WHILE_LOOP, FOR_LOOP, EXCEPT, FINALLY_TRY, FINALLY_END,
- WITH, ASYNC_WITH, HANDLER_CLEANUP, POP_VALUE };
+enum fblocktype { WHILE_LOOP, FOR_LOOP, TRY_EXCEPT, FINALLY_TRY, FINALLY_END,
+ WITH, ASYNC_WITH, HANDLER_CLEANUP, POP_VALUE, EXCEPTION_HANDLER };
struct fblockinfo {
enum fblocktype fb_type;
@@ -1624,9 +1624,7 @@
{
struct fblockinfo *f;
if (c->u->u_nfblocks >= CO_MAXBLOCKS) {
- PyErr_SetString(PyExc_SyntaxError,
- "too many statically nested blocks");
- return 0;
+ return compiler_error(c, "too many statically nested blocks");
}
f = &c->u->u_fblock[c->u->u_nfblocks++];
f->fb_type = t;
@@ -1666,6 +1664,7 @@
{
switch (info->fb_type) {
case WHILE_LOOP:
+ case EXCEPTION_HANDLER:
return 1;
case FOR_LOOP:
@@ -1676,7 +1675,7 @@
ADDOP(c, POP_TOP);
return 1;
- case EXCEPT:
+ case TRY_EXCEPT:
ADDOP(c, POP_BLOCK);
return 1;
@@ -3064,14 +3063,17 @@
return 0;
ADDOP_JREL(c, SETUP_FINALLY, except);
compiler_use_next_block(c, body);
- if (!compiler_push_fblock(c, EXCEPT, body, NULL, NULL))
+ if (!compiler_push_fblock(c, TRY_EXCEPT, body, NULL, NULL))
return 0;
VISIT_SEQ(c, stmt, s->v.Try.body);
ADDOP(c, POP_BLOCK);
- compiler_pop_fblock(c, EXCEPT, body);
+ compiler_pop_fblock(c, TRY_EXCEPT, body);
ADDOP_JREL(c, JUMP_FORWARD, orelse);
n = asdl_seq_LEN(s->v.Try.handlers);
compiler_use_next_block(c, except);
+ /* Runtime will push a block here, so we need to account for that */
+ if (!compiler_push_fblock(c, EXCEPTION_HANDLER, NULL, NULL, NULL))
+ return 0;
for (i = 0; i < n; i++) {
excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET(
s->v.Try.handlers, i);
@@ -3156,6 +3158,7 @@
}
compiler_use_next_block(c, except);
}
+ compiler_pop_fblock(c, EXCEPTION_HANDLER, NULL);
ADDOP(c, RERAISE);
compiler_use_next_block(c, orelse);
VISIT_SEQ(c, stmt, s->v.Try.orelse);