11.3 Raise Statements and Raise Expressions
Syntax
Reason: Unlike conditional expressions,
this doesn't say "immediately surrounded"; the only requirement
is that it is somehow within a pair of parentheses that is part of the
expression.
We need this restriction in order that
raise_expressions
cannot be syntactically confused with immediately following constructs
(such as
aspect_specifications).
Discussion: We only need to require that
a right parenthesis appear somewhere between the
raise_expression
and the surrounding context; that's all we need to specify in order to
eliminate the ambiguities. Moreover, we don't care at all where the left
parenthesis is (so long as it is legal, of course).
For instance,
the following is illegal by this rule:
Obj : Boolean := Func_Call or else raise TBD_Error with Atomic;
as the "with
Atomic" could be part of the raise_expression or part of
the object declaration. Both of the following are legal:
Obj : Boolean := Func_Call or else (raise TBD_Error) with Atomic;
Obj : Boolean := (Func_Call or else raise TBD_Error) with Atomic;
and if the
with
belongs to the
raise_expression,
then both of the following are legal:
Obj : Boolean := Func_Call or else (raise TBD_Error with Atomic);
Obj : Boolean := (Func_Call or else raise TBD_Error with Atomic);
This rule only
requires parentheses for
raise_expressions
that are part of the "top-level" of an
expression
in one of the named contexts; the
raise_expression
is either the entire
expression,
or part of a chain of logical operations. In practice, the
raise_expression
will almost always be last in interesting top-level
expressions;
anything that follows it could never be executed, so that should be rare.
Other contexts such as conditional expressions, qualified expressions,
aggregates, and even function calls, provide the needed parentheses.
All of the following are legal, no additional parens are needed:
Pre : Boolean := (if not Is_Valid(Param) then raise Not_Valid_Error);
A : A_Tagged := (Some_Tagged'(raise TBD_Error) with Comp => 'A');
B : Some_Array := (1, 2, 3, others => raise Not_Valid_Error);
C : Natural := Func (Val => raise TBD_Error);
Parentheses that
are part of the context of the
expression
don't count. For instance, the parentheses around the
raise_expression
are required in the following:
D : A_Tagged := ((raise TBD_Error) with Comp => 'A');
This English-language rule could have been implemented
instead by adding nonterminals
initial_expression
and
initial_relation, which are the same as
choice_expression
and
choice_relation
except for the inclusion of membership in
initial_relation.
Then,
initial_expresion could be used in place
of
expression
in all of the contexts noted. We did not do that because of the large
amount of change required, both to the grammar and to language rules
that refer to the grammar. A complete grammar is given in
AI12-0152-1.
Legality Rules
Name Resolution Rules
Dynamic Semantics
{
AI95-00361-01}
{
AI12-0022-1}
{
AI12-0152-1}
To
raise an exception is to raise a new occurrence
of that exception[, as explained in
11.4].
For the execution of a
raise_statement
with an
exception_name,
the named exception is raised. Similarly, for the evaluation of a
raise_expression,
the named exception is raised. [In both of these cases, if a
string_expression
or
string_simple_expression
is present, the expression is evaluated and its value is associated with
the exception occurrence.]
For the execution of a
re-raise statement, the exception occurrence that caused transfer of
control to the innermost enclosing handler is raised [again].
Proof: {
AI95-00361-01}
The definition of Exceptions.Exception_Message includes a statement that
the string is returned (see
11.4.1). We
describe the use of the string here so that we don't have an unexplained
parameter in this subclause.
Implementation Note: For a re-raise statement,
the implementation does not create a new Exception_Occurrence, but instead
propagates the same Exception_Occurrence value. This allows the original
cause of the exception to be determined.
Examples
Examples of raise
statements:
{
AI95-00433-01}
raise Ada.IO_Exceptions.Name_Error; --
see A.13
raise Queue_Error
with "Buffer Full"; --
see 9.11
raise; -- re-raise the current exception
Wording Changes from Ada 83
The fact that the
name
in a
raise_statement
has to denote an exception is not clear from RM83. Clearly that was the
intent, since the italicized part of the syntax rules so indicate, but
there was no explicit rule. RM83-1.5(11) doesn't seem to give the italicized
parts of the syntax any force.
Extensions to Ada 95
{
AI95-00361-01}
The syntax of a
raise_statement
is extended to include a string message. This is more convenient than
calling Exceptions.Exception_Message (
exception_name'Identity,
string_expression),
and should encourage the use of message strings when raising exceptions.
Extensions to Ada 2012
{
AI12-0022-1}
{
AI12-0152-1}
{
AI12-0159-1}
Corrigendum: The
raise_expression
is new. This construct is necessary to allow conversion of existing specifications
to use preconditions and predicates without changing the exceptions raised.
It is considered important enough to be added to Ada 2012 rather than
waiting for Ada 202x.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe