Version 1.11 of ais/ai-00169.txt

Unformatted version of ais/ai-00169.txt version 1.11
Other versions for file 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:
the new paragraphs:
!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