11.4 Exception Handling

23
Jan

11.4 Exception Handling

1 [When an exception occurrence is raised, normal program execution is abandoned and control is transferred to an applicable exception_handler, if any. {handle (an exception occurrence)} To handle an exception occurrence is to respond to the exceptional event. {propagate} To propagate an exception occurrence is to raise it again in another context; that is, to fail to respond to the exceptional event in the present context.] 

1.a Ramification: In other words, if the execution of a given construct raises an exception, but does not handle it, the exception is propagated to an enclosing execution (except in the case of a task_body).

1.b/1 Propagation involves re-raising the same exception occurrence. For example, calling an entry of an uncallable task raises Tasking_Error; this is not propagation.

Dynamic Semantics

2 {dynamically enclosing (of one execution by another)} {execution (dynamically enclosing)} Within a given task, if the execution of construct a is defined by this International Standard to consist (in part) of the execution of construct b, then while b is executing, the execution of a is said to dynamically enclose the execution of b. {innermost dynamically enclosing} The innermost dynamically enclosing execution of a given execution is the dynamically enclosing execution that started most recently. 

2.a To be honest: {included (one execution by another)} {execution (included by another execution)} If the execution of a dynamically encloses that of b, then we also say that the execution of b is included in the execution of a.

2.b Ramification: Examples: The execution of an if_statement dynamically encloses the evaluation of the condition after the if (during that evaluation). (Recall that “execution” includes both “elaboration” and “evaluation”, as well as other executions.) The evaluation of a function call dynamically encloses the execution of the sequence_of_statements of the function_body (during that execution). Note that, due to recursion, several simultaneous executions of the same construct can be occurring at once during the execution of a particular task.

2.c Dynamically enclosing is not defined across task boundaries; a task's execution does not include the execution of any other tasks.

2.d Dynamically enclosing is only defined for executions that are occurring at a given moment in time; if an if_statement is currently executing the sequence_of_statements after then, then the evaluation of the condition is no longer dynamically enclosed by the execution of the if_statement (or anything else).

3 {raise (an exception occurrence)} When an exception occurrence is raised by the execution of a given construct, the rest of the execution of that construct is abandoned; that is, any portions of the execution that have not yet taken place are not performed. The construct is first completed, and then left, as explained in 7.6.1. Then:

  • 4 If the construct is a task_body, the exception does not propagate further;

4.a Ramification: When an exception is raised by the execution of a task_body, there is no dynamically enclosing execution, so the exception does not propagate any further. If the exception occurred during the activation of the task, then the activator raises Tasking_Error, as explained in 9.2, “Task Execution - Task Activation”, but we don't define that as propagation; it's a special rule. Otherwise (the exception occurred during the execution of the handled_sequence_of_statements of the task), the task silently disappears. Thus, abnormal termination of tasks is not always considered to be an error.

  • 5 If the construct is the sequence_of_statements of a handled_sequence_of_statements that has a handler with a choice covering the exception, the occurrence is handled by that handler;
  • 6 {propagate (an exception occurrence by an execution, to a dynamically enclosing execution)} Otherwise, the occurrence is propagated to the innermost dynamically enclosing execution, which means that the occurrence is raised again in that context.

6.a To be honest: {propagate (an exception by an execution)} {propagate (an exception by a construct)} As shorthands, we refer to the propagation of an exception, and the propagation by a construct, if the execution of the construct propagates an exception occurrence.

7 {handle (an exception occurrence)} {execution (handler) [partial]} {elaboration (choice_parameter_specification) [partial]} When an occurrence is handled by a given handler, the choice_parameter_specification, if any, is first elaborated, which creates the choice parameter and initializes it to the occurrence. Then, the sequence_of_statements of the handler is executed; this execution replaces the abandoned portion of the execution of the sequence_of_statements.

7.a/2 Ramification: This “replacement” semantics implies that the handler can do pretty much anything the abandoned sequence could do; for example, in a function, the handler can execute a return statement that applies to the function.

7.b Ramification: The rules for exceptions raised in library units, main subprograms and partitions follow from the normal rules, plus the semantics of the environment task described in Section 10 (for example, the environment task of a partition elaborates library units and calls the main subprogram). If an exception is propagated by the main subprogram, it is propagated to the environment task, which then terminates abnormally, causing the partition to terminate abnormally. Although abnormal termination of tasks is not necessarily an error, abnormal termination of a partition due to an exception is an error.

NOTES

8 (1)  Note that exceptions raised in a declarative_part of a body are not handled by the handlers of the handled_sequence_of_statements of that body.