diff --git a/py/bc.h b/py/bc.h index 065daece47..d7e6aa70eb 100644 --- a/py/bc.h +++ b/py/bc.h @@ -9,6 +9,8 @@ typedef struct _mp_exc_stack { const byte *handler; // bit 0 is saved currently_in_except_block value mp_obj_t *val_sp; + // Saved exception, valid if currently_in_except_block bit is 1 + mp_obj_t prev_exc; // We might only have 2 interesting cases here: SETUP_EXCEPT & SETUP_FINALLY, // consider storing it in bit 1 of val_sp. TODO: SETUP_WITH? byte opcode; diff --git a/py/vm.c b/py/vm.c index 7316742665..b96cca1425 100644 --- a/py/vm.c +++ b/py/vm.c @@ -51,10 +51,12 @@ typedef enum { exc_sp->opcode = op; \ exc_sp->handler = ip + unum; \ exc_sp->val_sp = MP_TAGPTR_MAKE(sp, currently_in_except_block); \ + exc_sp->prev_exc = nlr.ret_val; \ currently_in_except_block = 0; /* in a try block now */ #define POP_EXC_BLOCK() \ currently_in_except_block = MP_TAGPTR_TAG(exc_sp->val_sp); /* restore previous state */ \ + if (currently_in_except_block) { nlr.ret_val = exc_sp->prev_exc; } \ exc_sp--; /* pop back to previous exception handler */ mp_vm_return_kind_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_args, const mp_obj_t *args2, uint n_args2, mp_obj_t *ret) { diff --git a/tests/basics/try-reraise2.py b/tests/basics/try-reraise2.py new file mode 100644 index 0000000000..9ab8d9c099 --- /dev/null +++ b/tests/basics/try-reraise2.py @@ -0,0 +1,23 @@ +# Reraise not the latest occured exception +def f(): + try: + raise ValueError("val", 3) + except: + try: + raise TypeError + except: + try: + try: + raise AttributeError + except: + pass + raise + except TypeError: + pass + # This should raise original ValueError, not the most recently occurred AttributeError + raise + +try: + f() +except ValueError as e: + print(repr(e))