!standard 07.06.01 (13) 99-10-07 AI95-00169/05 !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) 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. 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 to complicating implementations by requiring such exceptions to be converted to Program_Error. !corrigendum 7.06.01(13) @drepl The anonymous objects created by function calls and by @fas are finalized no later than the end of the innermost enclosing @fa or @fa; if that is a @fa, they are finalized before starting the execution of any @fa within the @fa. @dby The anonymous objects created by function calls and by @fas are finalized no later than the end of the innermost enclosing @fa or @fa; if that is a @fa, they are finalized before starting the execution of any @fa within the @fa. 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) @drepl 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: @dby 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) @dinsa @xbullet @dinss @xbullet @xbullet !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" 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. ****************************************************************