Version 1.11 of ais/ai-00169.txt
!standard 07.06.01 (13) 00-08-18 AI95-00169/06
!standard 07.06.01 (14)
!standard 07.06.01 (17)
!class binding interpretation 96-11-16
!status Corrigendum 2000 99-07-28
!status WG9 approved 99-06-12
!status ARG Approved (with changes) 8-0-1 99-03-25
!status work item 99-03-21
!status received 96-11-16
!priority Low
!difficulty Easy
!qualifier Omission
!subject Exceptions raised by Adjust/Finalize -- missing cases
!summary
If a call to Finalize propagates an exception when invoked as part of
the finalization of a master, Program_Error is raised at the point where
normal execution would have continued following the master's finalization.
Any other finalizations due to be performed up to that point are performed
before raising Program_Error.
If a call to Finalize propagates an exception in the case of finalizing an
anonymous object created for a function call or aggregate, Program_Error
is raised at the point where normal execution would have continued
following the object's finalization.
for finalizations of objects that occur as the result of transfers of
control or the raising of an exception, the finalization of an anonymous
object occurs as part of the finalizations due to be performed
for the innermost enclosing master of the anonymous object.
For an explicit call to Adjust or Finalize that propagates an exception,
the exception is propagated as for a normal call to a user-defined
subprogram that propagates an exception.
!question
7.6.1(14-20) list a variety of situations in which Finalize and Adjust
may raise exceptions, and the possible consequences.
It does not seem to indicate what happens when an exception is raised in
a Finalize which is part of the finalization of a master due to the most
normal type of completion--reaching the end of the execution. What is
the intended semantics for this situation? (Any pending finalizations
are performed and Program_Error is raised.)
If the finalization of an anonymous object raises an exception what
should occur? (Program_Error is raised at the point of finalization.)
If a transfer of control or raising of an exception occurs prior to
performing a finalization of an anonymous object, when is the object
finalized? (The anonymous object is finalized as part of the finalization
of the innermost enclosing master.)
If an explicit call to Adjust or Finalize propagates an exception,
is the exception converted to Program_Error? (No.)
!recommendation
(See summary.)
!wording
Add a paragraph to describe the treatment of calls to Finalize that
propagate an exception when called as part of normal finalization
of a master, namely to complete any other finalizations due to be
performed, and raise Program_Error at the point where normal execution
would have continued following finalization of the master (similar
to the description of 7.6.1(18)).
Add a paragraph to indicate the effect of Finalize propagating an
exception when invoked for an anonymous object, namely to raise
Program_Error immediately following the point where the finalization
is invoked.
Clarify what should happen for the finalization of anonymous objects
in the presence of transfers of control or raising of exceptions
that lead to the finalization of objects in a containing master.
Any anonymous objects that have not yet been finalized should be
finalized as part of the finalization of their innermost enclosing
master (i.e., as part of the "finalizations due to be performed"
mentioned in 7.6.1(18-19)).
In 7.6.1(14), clarify that the rules for bounded errors on calls to
Finalize or Adjust do not apply to explicit calls to those operations.
!discussion
The lack of a rule describing what happens when a call to Finalize
propagates an exception during the finalization of a master is
an oversight. The intended semantics is to treat this case
similarly to what happens when Finalize propagates an exception
when invoked by the transfer of control of a return statement
(as defined by 7.6.1(18)). Any finalizations due to be performed
are carried out and Program_Error is raised at the point where
normal execution would have continued.
There is also no mention of what should happen when a call to Finalize
propagates an exception when finalizing an anonymous object. Since
such objects are not directly associated with a master, the rules
of 7.6.1(14-20) don't appear to explain what should happen. The
intended semantics is to raise Program_Error as in the case of other
implicit calls to Finalize. The exception is raised immediately
following the point where the Finalize operation is invoked (as defined
by 7.6.1(13)). Also, in the presence of transfers of control or the
raising of an exception, the finalization of anonymous objects
occurs as part of the "finalizations due to be performed" mentioned
in the rules of 7.6.1(18-19).
In the case of explicitly invoked Adjust and Finalize operations,
any exception propagated by such calls should simply be propagated
as for an exception propagation that occurs as part of a call to
any other user-defined subprogram. There is no benefit in requiring such
exceptions to be converted to Program_Error.
!corrigendum 7.06.01(13)
Insert after the paragraph:
The anonymous objects created by function calls and by aggregates are
finalized no later than the end of the innermost enclosing declarative_item
or statement; if that is a compound_statement, they are finalized
before starting the execution of any statement within the
compound_statement.
the new paragraph:
If a transfer of control or raising of an exception
occurs prior to performing a finalization of an anonymous object, the
anonymous object is finalized as part of the finalizations due to be
performed for the object's innermost enclosing master.
!corrigendum 7.06.01(14)
Replace the paragraph:
It is a bounded error for a call on Finalize or Adjust to propagate an
exception. The possible consequences depend on what action invoked the
Finalize or Adjust operation:
by:
It is a bounded error for a call on Finalize or Adjust that occurs
as part of object finalization or assignment to propagate an exception.
The possible consequences depend on what action invoked the
Finalize or Adjust operation:
!corrigendum 7.06.01(17)
Insert after the paragraph:
- 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.
the new paragraphs:
- For a Finalize invoked as part of the finalization of the anonymous
object created by a function call or aggregate, any other finalizations due to
be performed are performed, and then Program_Error is raised.
- For a Finalize invoked due to reaching the end of the execution of
a master, any other finalizations associated with the master are performed,
and Program_Error is raised immediately after leaving the master.
!ACATS test
Add a C-Test (similar to C761008) to test this in the cases given here.
!appendix
!section 7.6.1(14)
!subject Exceptions raised by Adjust/Finalize -- Missing case
!reference RM95-7.6.1(14)
!from Vince Del Vecchio 96-10-18
!reference 1996-5731.a Vince Del Vecchio 1996-10-18>>
!discussion
RM 7.6.1(14ff) lists a variety of situations in which Finalize and Adjust
may raise exceptions, and the possible consequences.
It does not seem to indicate what happens when an exception is raised in
a Finalize which is part of the finalization of a master due to the most
normal type of completion--reaching the end of the execution.
It would probably make sense to finish finalizing the master, and
raise Program_Error in the enclosing construct, basically the way that
7.6.1(18) describes (except that there is less implementation dependency,
since the point after the finalization of the master currently being
finalized and the point at which normal execution would have continued
are roughly the same).
-Vince Del Vecchio
vdelvecc@inmet.com
****************************************************************
!section 7.6.1(14)
!subject Exceptions raised by Adjust/Finalize -- Missing case
!reference RM95-7.6.1(14)
!reference 1996-5731.a Vince Del Vecchio 1996-10-18
!from Bob Duff
!reference 96-5733.a Robert A Duff 96-10-21>>
!discussion
> RM 7.6.1(14ff) lists a variety of situations in which Finalize and Adjust
> may raise exceptions, and the possible consequences.
>
> It does not seem to indicate what happens when an exception is raised in
> a Finalize which is part of the finalization of a master due to the most
> normal type of completion--reaching the end of the execution.
Indeed.
> It would probably make sense to finish finalizing the master, and
> raise Program_Error in the enclosing construct, basically the way that
> 7.6.1(18) describes (except that there is less implementation dependency,
> since the point after the finalization of the master currently being
> finalized and the point at which normal execution would have continued
> are roughly the same).
Yes. (Kind of embarrassing! A case where the devil is *not* in the
details, but in the usual line of business. ;-))
- Bob
****************************************************************
!section 7.6.1(14)
!subject Exceptions raised by Adjust/Finalize -- Missing case
!reference RM95-7.6.1(14)
!reference 1996-5731.a Vince Del Vecchio 1996-10-18
!from Vince Del Vecchio 96-10-30
!reference 1996-5736.a Vince Del Vecchio 1996-10-30>>
!discussion
There appear to be a few more problems in this area.
In addition to the missing fall-through case in paragraphs 15-20 of 7.6.1,
these paragraphs don't seem to describe what happens if the object
being finalized is an anonymous object which is not associated with
any particular master, as described in 7.6.1(13). The real problem
paragraphs are where it talks about performing any other finalizations
for the same master, since it may not be a real master which is being
finalized.
This certainly needs to be answered in the fall-through case. Presumably
the most reasonable thing to do would be to perform any other
finalizations "due to be performed" and then raise an exception, although
that "due to be performed" wording, which I think is a little bit vague
in the first place, may be even more vague here. The decision about
where to raise the exception doesn't seem to hard. "Where normal
execution would have continued" describes it fine. It is also pretty
much immediately after finishing the finalization.
Anonymous objects created during an assignment statement are presumably
covered in paragraph 15.
It doesn't seem like there should be any anonymous objects to finalize
at an Unchecked_Deallocation (paragraph 17).
For paragraph 18, it is not entirely clear when a transfer of control
happens relative to the end of the statement which causes it. The
finalization of anonymous objects (e.g. from the expression of an
"exit when") has to happen before the end of the statement, but the
finalization of any masters happens as part of the transfer of control.
If the transfer of control happens before the end of the statement,
then anonymous objects may be finalized as part of the transfer of
control. At one point I thought that 5.1(14) seemed to imply that
the end of the statement (and its being left) preceded the transfer
of control (which might involve leaving other constructs). I don't
see that now, but if this is in fact the case, then there shouldn't
be any anonymous objects to finalize in paragraph 18.
It is definitely possible that anonymous objects may be finalized due
to raising an exception (paragraph 19). I'm not sure where the
exception should be raised. Probably as soon as possible, which would
be within the master in which the anonymous object was created.
Paragraph 20 doesn't mention masters, and probably doesn't need
clarification. In the event of an abort or terminate, just ignore
the exception and keep going.
Now for a not-entirely-related nit which you probably can't do anything
about: The wording of paragraph 16 -- "For an Adjust invoked as part of
an assignment operation" -- makes it sound like there may be other cases
in which to worry about Adjust. In fact, Adjusts can _only_ be invoked
as part of an assignment operation, so that clause is redundant (and
slightly confusing in its redundancy).
-Vince Del Vecchio
vdelvecc@inmet.com
****************************************************************
!section 7.6.1(16)
!subject Exceptions raised by Adjust/Finalize -- Missing case
!reference RM95-7.6.1(16)
!reference 1996-5731.a Vince Del Vecchio 1996-10-18
!reference 1996-5736.a Vince Del Vecchio 1996-10-30
!from Robert I. Eachus 96-10-31
!reference 96-5739.a Robert I. Eachus 96-10-31>>
!discussion
Vince Del Vecchio said:
> Now for a not-entirely-related nit which you probably can't do anything
> about: The wording of paragraph 16 -- "For an Adjust invoked as part of
> an assignment operation" -- makes it sound like there may be other cases
> in which to worry about Adjust. In fact, Adjusts can _only_ be invoked
> as part of an assignment operation, so that clause is redundant (and
> slightly confusing in its redundancy).
Not slightly confusing--the user can explicitly call Adjust. It is
a useful feature for debugging, if for no other reason.
Robert I. Eachus
with Standard_Disclaimer;
use Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...
****************************************************************
!section 7.6.1(16)
!subject Exceptions raised by Adjust/Finalize -- Missing case
!reference RM95-7.6.1(16)
!reference 1996-5731.a Vince Del Vecchio 1996-10-18
!reference 1996-5736.a Vince Del Vecchio 1996-10-30
!reference 1996-5739.a Robert I. Eachus 1996-10-31
!from Vince Del Vecchio 96-10-31
!reference 1996-5740.a Vince Del Vecchio 1996-10-31>>
!discussion
>>>>> On Thu, 31 Oct 1996 14:23:53 GMT,
"Robert I. Eachus" <eachus@spectre.mitre.org> said:
> Not slightly confusing--the user can explicitly call Adjust. It is
> a useful feature for debugging, if for no other reason.
Thank you for pointing this out; I missed that one. So it's not redundant,
which means that there should be more clauses indicating what to do if
Adjust (and Finalize as well) propagate exceptions when called explicitly
from user code. Alternatively, paragraph 14 could be modified to indicate
that such cases are not bounded errors.
(It had to be either one thing or the other--either redundant, or
indicative of a missing case. I was just wrong about which it was. :-))
-Vince Del Vecchio
****************************************************************
!section 7.6.1(14)
!subject Exceptions raised by Adjust/Finalize -- Missing case
!reference RM95-7.6.1(14)
!reference 1996-5731.a Vince Del Vecchio 1996-10-18
!reference 1996-5733.a Robert A Duff 96-10-21
!from Norman Cohen
!reference 96-5745.a Norman H. Cohen 96-11-7>>
!discussion
I agree that the 7.6.1(18) rule should apply in the fall-through case. A
compelling argument, I think, is that adding a return statement to the end
of a procedure body or accept statement should not change its behavior, and
the behavior of an exception in finalization triggered by a return
statement is already specified by 7.6.1(18).
Bob Duff writes:
> Yes. (Kind of embarrassing! A case where the devil is *not* in
> the details, but in the
> usual line of business. ;-))
Well, I'm embarassed too, because when I was trying to decipher the rules
in 7.6.1 for the revision of Ada as a Second Language, I somehow inferred a
rule that is not present in either the RM or AARM. On page 656 I wrote:
If the construct was being exited because the end of its sequence of
statements was reached, or because the end of one of its handlers was
reached without another xception having been raised, Program_Error is
raised as if it were propagated by the construct being exited.
(I think that's equivalent to the 7.6.1(18) rule in this case.) Perhaps
there WAS a clear rule in an earlier draft of RM9X, but it somehow got
lost, in which case we both have less reason to be embarassed. Or perhaps
I got an unofficial interpretation from Bob or Tuck in private
correspondence. Or perhaps I was off doing language design on my own. :-)
****************************************************************
!section 7.6.1(16)
!subject Exceptions raised by Adjust/Finalize -- Missing case
!reference RM95-7.6.1(16)
!reference 1996-5731.a Vince Del Vecchio 1996-10-18
!reference 1996-5736.a Vince Del Vecchio 1996-10-30
!reference 1996-5739.a Robert I. Eachus 1996-10-31
!reference 1996-5740.a Vince Del Vecchio 1996-10-31
!from Bob Duff
!reference 96-5756.a Robert A Duff 96-11-8>>
!discussion
It seems to me that if an explicit call to Adjust or Finalize raises an
exception, it should *not* be a bounded error. The exception should
just be propagated in the normal way, as for any other call. The
exception should not be turned into Program_Error. Anybody disagree
with that? It seems what the user would expect, and it seems the
easiest to imlpement.
- Bob
****************************************************************
!section 7.6.1(16)
!subject Exceptions raised by Adjust/Finalize -- Missing case
!reference RM95-7.6.1(16)
!reference 1996-5731.a Vince Del Vecchio 1996-10-18
!reference 1996-5736.a Vince Del Vecchio 1996-10-30
!reference 1996-5739.a Robert I. Eachus 1996-10-31
!reference 1996-5740.a Vince Del Vecchio 1996-10-31
!reference 1996-5756.a Robert A Duff 96-11-8
!from Randy Brukardt 96-11-10
!reference 96-5758.a Randy Brukardt 96-11-10>>
!discussion
>It seems to me that if an explicit call to Adjust or Finalize raises an
>exception, it should *not* be a bounded error. The exception should
>just be propagated in the normal way, as for any other call. The
>exception should not be turned into Program_Error. Anybody disagree
>with that? It seems what the user would expect, and it seems the
>easiest to imlpement.
Easiest to implement is an understatement. I would expect that for most
compilers, Adjust and Finalize will be normal subprograms; all of the magic
will be in the calls to them (mostly from somewhere in the runtime system).
Trying to specially handle exceptions for explicit calls to the routines would
require detecting the routines and making the call in some special way.
That would be an awful lot of additional work for something uncommon AND
counter-intuitive.
****************************************************************
Questions? Ask the ACAA Technical Agent