py: Handle case of return within the finally block of try-finally.
Addresses issue #1636.
This commit is contained in:
parent
117158fcd5
commit
8047340d75
8
py/vm.c
8
py/vm.c
|
@ -1032,6 +1032,14 @@ unwind_jump:;
|
|||
|
||||
ENTRY(MP_BC_RETURN_VALUE):
|
||||
MARK_EXC_IP_SELECTIVE();
|
||||
// These next 3 lines pop a try-finally exception handler, if one
|
||||
// is there on the exception stack. Without this the finally block
|
||||
// is executed a second time when the return is executed, because
|
||||
// the try-finally exception handler is still on the stack.
|
||||
// TODO Possibly find a better way to handle this case.
|
||||
if (currently_in_except_block) {
|
||||
POP_EXC_BLOCK();
|
||||
}
|
||||
unwind_return:
|
||||
while (exc_sp >= exc_stack) {
|
||||
if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
# test 'return' within the finally block
|
||||
# it should swallow the exception
|
||||
|
||||
# simple case
|
||||
def f():
|
||||
try:
|
||||
raise ValueError()
|
||||
finally:
|
||||
print('finally')
|
||||
return 0
|
||||
print('got here')
|
||||
print(f())
|
||||
|
||||
# nested, return in outer
|
||||
def f():
|
||||
try:
|
||||
try:
|
||||
raise ValueError
|
||||
finally:
|
||||
print('finally 1')
|
||||
print('got here')
|
||||
finally:
|
||||
print('finally 2')
|
||||
return 2
|
||||
print('got here')
|
||||
print(f())
|
||||
|
||||
# nested, return in inner
|
||||
def f():
|
||||
try:
|
||||
try:
|
||||
raise ValueError
|
||||
finally:
|
||||
print('finally 1')
|
||||
return 1
|
||||
print('got here')
|
||||
finally:
|
||||
print('finally 2')
|
||||
print('got here')
|
||||
print(f())
|
||||
|
||||
# nested, return in inner and outer
|
||||
def f():
|
||||
try:
|
||||
try:
|
||||
raise ValueError
|
||||
finally:
|
||||
print('finally 1')
|
||||
return 1
|
||||
print('got here')
|
||||
finally:
|
||||
print('finally 2')
|
||||
return 2
|
||||
print('got here')
|
||||
print(f())
|
||||
|
||||
# nested with reraise
|
||||
def f():
|
||||
try:
|
||||
try:
|
||||
raise ValueError
|
||||
except:
|
||||
raise
|
||||
print('got here')
|
||||
finally:
|
||||
print('finally')
|
||||
return 0
|
||||
print('got here')
|
||||
print(f())
|
||||
|
||||
# triple nesting with reraise
|
||||
def f():
|
||||
try:
|
||||
try:
|
||||
try:
|
||||
raise ValueError
|
||||
except:
|
||||
raise
|
||||
except:
|
||||
raise
|
||||
finally:
|
||||
print('finally')
|
||||
return 0
|
||||
print(f())
|
||||
|
||||
# exception when matching exception
|
||||
def f():
|
||||
try:
|
||||
raise ValueError
|
||||
except NonExistingError:
|
||||
pass
|
||||
finally:
|
||||
print('finally')
|
||||
return 0
|
||||
print(f())
|
||||
|
||||
# raising exception class, not instance
|
||||
def f():
|
||||
try:
|
||||
raise ValueError
|
||||
finally:
|
||||
print('finally')
|
||||
return 0
|
||||
print(f())
|
Loading…
Reference in New Issue