summaryrefslogtreecommitdiffstats
path: root/Python/compile.c
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2020-09-25 13:04:19 (GMT)
committerGitHub <noreply@github.com>2020-09-25 13:04:19 (GMT)
commit02d126aa09d96d03dcf9c5b51c858ce5ef386601 (patch)
tree85817061b2ed79451edc432495040fc279067e7d /Python/compile.c
parent05cc881cbcf5d73a312568c78c7149eae3195072 (diff)
downloadcpython-02d126aa09d96d03dcf9c5b51c858ce5ef386601.zip
cpython-02d126aa09d96d03dcf9c5b51c858ce5ef386601.tar.gz
cpython-02d126aa09d96d03dcf9c5b51c858ce5ef386601.tar.bz2
bpo-39934: Account for control blocks in 'except' in compiler. (GH-22395)
* Account for control blocks in 'except' in compiler. Fixes #39934.
Diffstat (limited to 'Python/compile.c')
-rw-r--r--Python/compile.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/Python/compile.c b/Python/compile.c
index 0f9e5c2..f2563d7 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -108,8 +108,8 @@ It's called a frame block to distinguish it from a basic block in the
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;
@@ -1623,9 +1623,7 @@ compiler_push_fblock(struct compiler *c, enum fblocktype t, basicblock *b,
{
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;
@@ -1665,6 +1663,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
{
switch (info->fb_type) {
case WHILE_LOOP:
+ case EXCEPTION_HANDLER:
return 1;
case FOR_LOOP:
@@ -1675,7 +1674,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
ADDOP(c, POP_TOP);
return 1;
- case EXCEPT:
+ case TRY_EXCEPT:
ADDOP(c, POP_BLOCK);
return 1;
@@ -3060,14 +3059,17 @@ compiler_try_except(struct compiler *c, stmt_ty s)
return 0;
ADDOP_JUMP(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_JUMP(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);
@@ -3152,6 +3154,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
}
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);