- 14.a
- Ramification: It is not a bounded error for Initialize to propagate an exception. If Initialize propagates an exception, then no further calls on Initialize are performed, and those components that have already been initialized (either explicitly or by default) are finalized in the usual way.
- 15 ·
- For a Finalize invoked as part of an assignment_statement, Program_Error is raised at that point.
- 16 ·
- For an Adjust invoked as part of an assignment operation, any other adjustments due to be performed are performed, and then Program_Error is raised.
- 17 ·
- For a Finalize invoked as part of a call on an instance of Unchecked_Deallocation, any other finalizations due to be performed are performed, and then Program_Error is raised.
- 18 ·
- For a Finalize invoked by the transfer of control of an
exit_, return_, goto_, or requeue_statement, Program_Error is raised no earlier than after the finalization of the master being finalized when the exception occurred, and no later than the point where normal execution would have continued. Any other finalizations due to be performed up to that point are performed before raising Program_Error.
- 18.a
- Ramification: For example, upon leaving a block_statement due to a goto_statement, the Program_Error would be raised at the point of the target statement denoted by the label, or else in some more dynamically nested place, but not so nested as to allow an exception_handler that has visibility upon the finalized object to handle it. For example,
- 18.b
- procedure Main is
begin
<<The_Label>>
Outer_Block_Statement : declare
X : Some_Controlled_Type;
begin
Inner_Block_Statement : declare
Y : Some_Controlled_Type;
Z : Some_Controlled_Type;
begin
goto The_Label;
exception
when Program_Error => ... --Handler number 1.
end;
exception
when Program_Error => ... --Handler number 2.
end;
exception
when Program_Error => ... --Handler number 3.
end Main;
- 18.c
- The goto_statement will first cause Finalize(Y) to be called. Suppose that Finalize(Y) propagates an exception. Program_Error will be raised after leaving Inner_Block_Statement, but before leaving Main. Thus, handler number 1 cannot handle this Program_Error; it will be handled either by handler number 2 or handler number 3. If it is handled by handler number 2, then Finalize(Z) will be done before executing the handler. If it is handled by handler number 3, then Finalize(Z) and Finalize(X) will both be done before executing the handler.
- 19 ·
- For a Finalize invoked by a transfer of control that is due to raising an exception, any other finalizations due to be performed for the same master are performed; Program_Error is raised immediately after leaving the master.
- 19.a
- Ramification: If, in the above example, the goto_statement were replaced by a raise_statement, then the Program_Error would be handled by handler number 2, and Finalize(Z) would be done before executing the handler.
- 19.b
- Reason: We considered treating this case in the same way as the others, but that would render certain exception_handlers useless. For example, suppose the only exception_handler is one for others in the main subprogram. If some deeply nested call raises an exception, causing some Finalize operation to be called, which then raises an exception, then normal execution "would have continued" at the beginning of the exception_handler. Raising Program_Error at that point would cause that handler's code to be skipped. One would need two nested exception_handlers to be sure of catching such cases!
- 19.c
- On the other hand, the exception_handler for a given master should not be allowed to handle exceptions raised during finalization of that master.
- 20 ·
- For a Finalize invoked by a transfer of control due to an abort or selection of a terminate alternative, the exception is ignored; any other finalizations due to be performed are performed.
- 20.a
- Ramification: This case includes an asynchronous transfer of control.
- 20.b
- To be honest: This violates the general principle that it is always possible for a bounded error to raise Program_Error (see 1.1.5, "Classification of Errors").