mirror of https://github.com/m-labs/artiq.git
Correctly handle try/catch try/finally blocks
If we have a try/catch block nested inside a try/finally, then the finally block would not be executed in the event of the exception. This is because the landing pad of the inner try is marked as having no cleanup clause. We now set has_cleanup to False only if there is no outer try block. Signed-off-by: Jonathan Coates <jonathan.coates@oxionics.com>
This commit is contained in:
parent
e1aa8a5a8c
commit
270a417a28
|
@ -703,7 +703,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
||||||
return_action.append(ir.Return(value))
|
return_action.append(ir.Return(value))
|
||||||
final_branch(return_action, return_proxy)
|
final_branch(return_action, return_proxy)
|
||||||
else:
|
else:
|
||||||
landingpad.has_cleanup = False
|
landingpad.has_cleanup = self.unwind_target is not None
|
||||||
|
|
||||||
# we should propagate the clauses to nested try catch blocks
|
# we should propagate the clauses to nested try catch blocks
|
||||||
# so nested try catch will jump to our clause if the inner one does not
|
# so nested try catch will jump to our clause if the inner one does not
|
||||||
|
@ -767,7 +767,6 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
||||||
self.continue_target = old_continue
|
self.continue_target = old_continue
|
||||||
self.return_target = old_return
|
self.return_target = old_return
|
||||||
|
|
||||||
if any(node.finalbody):
|
|
||||||
# create new unwind target for cleanup
|
# create new unwind target for cleanup
|
||||||
final_dispatcher = self.add_block("try.final.dispatch")
|
final_dispatcher = self.add_block("try.final.dispatch")
|
||||||
final_landingpad = ir.LandingPad(cleanup)
|
final_landingpad = ir.LandingPad(cleanup)
|
||||||
|
@ -776,7 +775,6 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
||||||
# make sure that exception clauses are unwinded to the finally block
|
# make sure that exception clauses are unwinded to the finally block
|
||||||
old_unwind, self.unwind_target = self.unwind_target, final_dispatcher
|
old_unwind, self.unwind_target = self.unwind_target, final_dispatcher
|
||||||
|
|
||||||
if any(node.finalbody):
|
|
||||||
# if we have a while:try/finally continue must execute finally
|
# if we have a while:try/finally continue must execute finally
|
||||||
# before continuing the while
|
# before continuing the while
|
||||||
redirect = final_branch
|
redirect = final_branch
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
# RUN: %python -m artiq.compiler.testbench.jit %s >%t
|
||||||
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
# REQUIRES: exceptions
|
||||||
|
|
||||||
|
def doit():
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
raise RuntimeError("Error")
|
||||||
|
except ValueError:
|
||||||
|
print("ValueError")
|
||||||
|
except RuntimeError:
|
||||||
|
print("Caught")
|
||||||
|
finally:
|
||||||
|
print("Cleanup")
|
||||||
|
|
||||||
|
doit()
|
||||||
|
|
||||||
|
# CHECK-L: Caught
|
||||||
|
# CHECK-NEXT-L: Cleanup
|
|
@ -0,0 +1,20 @@
|
||||||
|
# RUN: %python -m artiq.compiler.testbench.jit %s >%t
|
||||||
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
# REQUIRES: exceptions
|
||||||
|
|
||||||
|
def doit():
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
raise RuntimeError("Error")
|
||||||
|
except ValueError:
|
||||||
|
print("ValueError")
|
||||||
|
finally:
|
||||||
|
print("Cleanup")
|
||||||
|
|
||||||
|
try:
|
||||||
|
doit()
|
||||||
|
except RuntimeError:
|
||||||
|
print("Caught")
|
||||||
|
|
||||||
|
# CHECK-L: Cleanup
|
||||||
|
# CHECK-NEXT-L: Caught
|
Loading…
Reference in New Issue