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:
Jonathan Coates 2024-11-19 17:24:53 +00:00 committed by Sebastien Bourdeauducq
parent 37330015c4
commit 46c3616a38
3 changed files with 40 additions and 3 deletions

View File

@ -696,7 +696,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
return_action.append(ir.Return(value))
final_branch(return_action, return_proxy)
else:
landingpad.has_cleanup = False
landingpad.has_cleanup = self.unwind_target is not None
# 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
@ -760,7 +760,6 @@ class ARTIQIRGenerator(algorithm.Visitor):
self.continue_target = old_continue
self.return_target = old_return
if any(node.finalbody):
# create new unwind target for cleanup
final_dispatcher = self.add_block("try.final.dispatch")
final_landingpad = ir.LandingPad(cleanup)
@ -769,7 +768,6 @@ class ARTIQIRGenerator(algorithm.Visitor):
# make sure that exception clauses are unwinded to the finally block
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
# before continuing the while
redirect = final_branch

View File

@ -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

View File

@ -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