Resolve the control flow out of a finally block. This means returning if there was a return, propagating exceptions, break/continue (soon), or just continuing on.
(
builder: IRBuilder,
cleanup_block: BasicBlock,
finally_control: FinallyNonlocalControl,
old_exc: Value,
ret_reg: Register | AssignmentTarget | None,
)
| 840 | |
| 841 | |
| 842 | def try_finally_resolve_control( |
| 843 | builder: IRBuilder, |
| 844 | cleanup_block: BasicBlock, |
| 845 | finally_control: FinallyNonlocalControl, |
| 846 | old_exc: Value, |
| 847 | ret_reg: Register | AssignmentTarget | None, |
| 848 | ) -> BasicBlock: |
| 849 | """Resolve the control flow out of a finally block. |
| 850 | |
| 851 | This means returning if there was a return, propagating |
| 852 | exceptions, break/continue (soon), or just continuing on. |
| 853 | """ |
| 854 | line = builder.fn_info.fitem.line |
| 855 | reraise, rest = BasicBlock(), BasicBlock() |
| 856 | builder.add(Branch(old_exc, rest, reraise, Branch.IS_ERROR, line)) |
| 857 | |
| 858 | # Reraise the exception if there was one |
| 859 | builder.activate_block(reraise) |
| 860 | builder.call_c(reraise_exception_op, [], NO_TRACEBACK_LINE_NO) |
| 861 | builder.add(Unreachable(line)) |
| 862 | builder.builder.pop_error_handler() |
| 863 | |
| 864 | # If there was a return, keep returning |
| 865 | if ret_reg: |
| 866 | builder.activate_block(rest) |
| 867 | return_block, rest = BasicBlock(), BasicBlock() |
| 868 | # For spill targets in try/finally, use nullable read to avoid AttributeError |
| 869 | if isinstance(ret_reg, AssignmentTargetAttr) and ret_reg.attr.startswith(TEMP_ATTR_NAME): |
| 870 | ret_val = builder.read_nullable_attr(ret_reg.obj, ret_reg.attr, line) |
| 871 | else: |
| 872 | ret_val = builder.read(ret_reg, line) |
| 873 | builder.add(Branch(ret_val, rest, return_block, Branch.IS_ERROR, line)) |
| 874 | |
| 875 | builder.activate_block(return_block) |
| 876 | builder.nonlocal_control[-1].gen_return(builder, ret_val, line) |
| 877 | |
| 878 | # TODO: handle break/continue |
| 879 | builder.activate_block(rest) |
| 880 | out_block = BasicBlock() |
| 881 | builder.goto(out_block) |
| 882 | |
| 883 | # If there was an exception, restore again |
| 884 | builder.activate_block(cleanup_block) |
| 885 | finally_control.gen_cleanup(builder, line) |
| 886 | builder.call_c(keep_propagating_op, [], NO_TRACEBACK_LINE_NO) |
| 887 | builder.add(Unreachable()) |
| 888 | |
| 889 | return out_block |
| 890 | |
| 891 | |
| 892 | def transform_try_finally_stmt( |
no test coverage detected
searching dependent graphs…