summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2018-09-03 17:41:02 +1000
committerDamien George <damien.p.george@gmail.com>2018-09-03 17:41:02 +1000
commit3cd2c281d7cf990b3afb78287a58cf4ee3f23ca5 (patch)
treeaf1ec7ff9ae66946cf02c96f37c989979291ce18
parentb735208403a54774f9fd3d966f7c1a194c41870f (diff)
py/emitnative: Cancel caught exception once handled to prevent reraise.
The native emitter keeps the current exception in a slot in its C stack (instead of on its Python value stack), so when it catches an exception it must explicitly clear that slot so the same exception is not reraised later on.
-rw-r--r--py/emitnative.c4
-rw-r--r--tests/basics/try_finally1.py13
2 files changed, 16 insertions, 1 deletions
diff --git a/py/emitnative.c b/py/emitnative.c
index 5db496a22..a5075eead 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -1892,7 +1892,9 @@ STATIC void emit_native_pop_block(emit_t *emit) {
}
STATIC void emit_native_pop_except(emit_t *emit) {
- (void)emit;
+ // Cancel any active exception so subsequent handlers don't see it
+ ASM_MOV_REG_IMM(emit->as, REG_TEMP0, (mp_uint_t)mp_const_none);
+ ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0);
}
STATIC void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) {
diff --git a/tests/basics/try_finally1.py b/tests/basics/try_finally1.py
index 2416f6d18..1e821deb6 100644
--- a/tests/basics/try_finally1.py
+++ b/tests/basics/try_finally1.py
@@ -69,3 +69,16 @@ try: # top-level catch-all except to not fail script
except:
print("catch-all except")
print()
+
+# case where a try-except within a finally cancels the exception
+print("exc-finally-subexcept")
+try:
+ print("try1")
+finally:
+ try:
+ print("try2")
+ foo
+ except:
+ print("except2")
+ print("finally1")
+print()