Version 1.6 of ai05s/ai05-0043-1.txt

Unformatted version of ai05s/ai05-0043-1.txt version 1.6
Other versions for file ai05s/ai05-0043-1.txt

!standard 11.4.1(10.1/2)          07-10-08 AI05-0043-1/02
!standard 11(2)
!class binding interpretation 07-03-27
!status Amendment 201Z 08-11-26
!status WG9 Approved 07-11-08
!status ARG Approved 8-0-2 07-06-03
!status work item 07-03-27
!status received 07-01-19
!priority Low
!difficulty Easy
!qualifier Omission
!subject The Exception_Message for failed language-defined checks.
!summary
The introduction to Section 11 is incorrect.
The Exception_Message for cases not spelled out in 11.4.1(10.1/2) is unspecified.
!question
(1) 11(2) says "An exception is raised initially either by a raise_statement or by the failure of a language-defined check." But this isn't correct (even for Ada 95), since an exception can also be raised initially by a Raise_Exception call.
(2) 11.4.1(10.1/2) describes the operation of Ada.Exceptions.Exception_Message. It seems to intend to list all of the possible ways for a message to be created. But it doesn't mention an exception raised by a language-defined check. Nor does it mention an exception raised in a calling task (9.5.2(24), which is noted in the AARM as a new occurrence).
!recommendation
(See summary.)
!wording
(1) Modify 11(2):
An exception is raised initially by a raise_statement{, by a call to Raise_Exception,} or by the failure of a language-defined check.
(2) Add to 11.4.1(10.1/2): For an occurrence originally raised for some other reason, the message is an unspecified string.
AARM Note: There is Implementation Advice about the contents of this string for language-defined checks.
!discussion
We could say more about occurrences created due to the raising of exceptions in the calling task (that is, 9.5.2(24)), and possibly about occurrences which are created by a stream attribute, but it doesn't seem worthwhile. Implementers will do the most useful thing for their customers, which is likely to be to preserve the most information. And this feature is intended as a debugging aid, not as an information source, so strong rules are not required.
!corrigendum 11(2)
Replace the paragraph:
An exception_declaration declares a name for an exception. An exception is raised initially either by a raise_statement or by the failure of a language-defined check. When an exception arises, control can be transferred to a user-provided exception_handler at the end of a handled_sequence_of_statements, or it can be propagated to a dynamically enclosing execution.
by:
An exception_declaration declares a name for an exception. An exception is raised initially by a raise_statement, by a call to Raise_Exception, or by the failure of a language-defined check. When an exception arises, control can be transferred to a user-provided exception_handler at the end of a handled_sequence_of_statements, or it can be propagated to a dynamically enclosing execution.
!corrigendum 11.4.1(10.1/2)
Replace the paragraph:
Exception_Message returns the message associated with the given Exception_Occurrence. For an occurrence raised by a call to Raise_Exception, the message is the Message parameter passed to Raise_Exception. For the occurrence raised by a raise_statement with an exception_name and a string_expression, the message is the string_expression. For the occurrence raised by a raise_statement with an exception_name but without a string_expression, the message is a string giving implementation-defined information about the exception occurrence. In all cases, Exception_Message returns a string with lower bound 1.
by:
Exception_Message returns the message associated with the given Exception_Occurrence. For an occurrence raised by a call to Raise_Exception, the message is the Message parameter passed to Raise_Exception. For the occurrence raised by a raise_statement with an exception_name and a string_expression, the message is the string_expression. For the occurrence raised by a raise_statement with an exception_name but without a string_expression, the message is a string giving implementation-defined information about the exception occurrence. For an occurrence originally raised for some other reason, the message is an unspecified string. In all cases, Exception_Message returns a string with lower bound 1.
!ACATS test
Since this is unspecified, no useful ACATS test can be constructed.
!appendix

From: Adam Benschan
Date: Friday, January 19, 2007  2:15 PM

!topic Exception_Message and exceptions raised in accept statements
!reference RM05 11.4.1(10.1/2), 9.5.2(24)
!from Adam Beneschan 07-01-19
!discussion

RM05 contains a new paragraph, 11.4.1(10.1), describing
Ada.Exceptions.Exception_Message:

    Exception_Message returns the message associated with the given
    Exception_Occurrence. For an occurrence raised by a call to
    Raise_Exception, the message is the Message parameter passed to
    Raise_Exception. For the occurrence raised by a raise_statement
    with an exception_name and a string_expression, the message is the
    string_expression. For the occurrence raised by a raise_statement
    with an exception_name but without a string_expression, the
    message is a string giving implementation-defined information
    about the exception occurrence. In all cases, Exception_Message
    returns a string with lower bound 1.

One possible objection is that since Exception_Message seems to want
to list all the cases (raised by Raise_Exception, raised by a
raise_statement with a string_expression, raised by a raise_statement
with an exception name but without a string_expression), then why did
it leave out the case of an occurrence raised by the failure of a
language-defined check?  This is a very minor nit, I suppose.  The
implementation advice in 11.4.1(19) says that Exception_Message should
return "something useful for debugging", so it probably can be assumed
that Exception_Message "should" return a string giving some
implementation-defined information about why the exception was raised.
It probably ought to be explicit in 11.4.1(10.1), in my opinion.

However, one case that I think needs to be spelled out is the
exception raised in a calling task, during an entry call, when the
accept statement propagates an exception.  9.5.2(24) says that the
same exception is raised by the execution of the corresponding
entry_call_statement, and AARM 9.5.2(24.b) makes it clear that this is
considered a *new* exception occurrence.  So what happens when
Exception_Message is called on this new exception
occurrence---especially when the exception in the accept was raised by
a Raise_Exception or by a raise statement with a string_exception?  Is
the message for the occurrence in the calling task the same as that
for the raise statement, or is it simply something
implementation-defined (same as for a check failure)?  I don't think
the answer is clear from the RM.

One other nitpick: 11(2) says "An exception is raised initially either
by a raise_statement or by the failure of a language-defined check."
But this isn't correct any more, since an exception can also be raised
initially by a Raise_Exception call.  Of course, this is a very minor
problem. 

****************************************************************

From: Randy Brukardt
Date: Monday, January 22, 2007 11:33 PM

...
> One possible objection is that since Exception_Message seems to want
> to list all the cases (raised by Raise_Exception, raised by a
> raise_statement with a string_expression, raised by a raise_statement
> with an exception name but without a string_expression), then why did
> it leave out the case of an occurrence raised by the failure of a
> language-defined check?  This is a very minor nit, I suppose.  The
> implementation advice in 11.4.1(19) says that Exception_Message should
> return "something useful for debugging", so it probably can be assumed
> that Exception_Message "should" return a string giving some
> implementation-defined information about why the exception was raised.
> It probably ought to be explicit in 11.4.1(10.1), in my opinion.

We don't put "should"s in normative text. We keep them separate in
Implementation Advice sections.

Moreover, there is a difference between saying "For the occurrence raised by
the failure of a language-defined check, the message is a string giving
implementation-defined information
about the language-defined check." and what the Implementation Advice says.
That's because there is a requirement to document everything implementation
defined, while there is only a requirement to document whether
Implementation Advice is followed.

The latter can be done by simply saying "Yes, we do" (without details),
while the latter means that the contents of every string should be
documented. (Since Documentation Requirements aren't checked in any way, I'm
not sure there is any functional difference, but there is a different
intent.)

OTOH, we really do need to say something about occurrences that come from
other places. You mentioned two (language-defined checks, and accept
statements), but I wouldn't be stunned if there are others. Probably the
best thing would be to add a sentence like:

   For an occurrence originally raised for some other reason, the message is
an
   unspecified string.

(I said "originally" so this would not be construed to cover reraises.) One
could argue that it already is unspecified (because it doesn't say), but the
appearance of complete-appearing list makes it odd that other cases aren't
mentioned.

> However, one case that I think needs to be spelled out is the
> exception raised in a calling task, during an entry call, when the
> accept statement propagates an exception.  9.5.2(24) says that the
> same exception is raised by the execution of the corresponding
> entry_call_statement, and AARM 9.5.2(24.b) makes it clear that this is
> considered a *new* exception occurrence.  So what happens when
> Exception_Message is called on this new exception
> occurrence---especially when the exception in the accept was raised by
> a Raise_Exception or by a raise statement with a string_exception?  Is
> the message for the occurrence in the calling task the same as that
> for the raise statement, or is it simply something
> implementation-defined (same as for a check failure)?  I don't think
> the answer is clear from the RM.

Well, I think it is clear that it is unspecified, and that actually is
perfectly OK for this case. Although I'm not completely convinced that it is
actually a new raise; I'd expect it to be a copy of the existing occurrence
(i.e. new but equal). The normative wording is "also raised", which doesn't
clearly state anything whatsoever about the occurrence in question. The AARM
note says something about the intent that it is a new occurrence, but it
gives no clues as to what might be in that occurrence. Which I guess is the
definition of unspecified. ;-)

One could try to nail down this stuff, but then we have to try to figure out
every possible way that an occurrence can be created. (Such as streaming one
in - does that have to preserve the message? Always, or only when it has a
defined result?) It doesn't seem worth the effort to me; do implementers
actually try to make this stuff useless???

> One other nitpick: 11(2) says "An exception is raised initially either
> by a raise_statement or by the failure of a language-defined check."
> But this isn't correct any more, since an exception can also be raised
> initially by a Raise_Exception call.  Of course, this is a very minor
> problem.

Another ancient problem. I don't think anyone looked for Ada 95 wording bugs
this time; we assumed that was already correct.

****************************************************************


Questions? Ask the ACAA Technical Agent