!standard 08.05.04 (05) 00-07-13 AI95-00135/05 !standard 08.05.04 (08) !class binding interpretation 96-05-07 !status Corrigendum 2000 99-08-13 !status WG9 approved (8-0-0) 97-07-04 !status ARG approved (6-0-3) 97-04-11 !status work item 96-05-08 !status received 96-05-07 !reference AI95-00064 !priority Medium !difficulty Medium !qualifier Omission !subject Circular renamings as body !summary A circular renaming-as-body represents infinite recursion. If the renaming-as-body occurs before the subprogram whose body is being defined is frozen, the renaming-as-body is illegal. !question Consider the following example: package Example is function F return Boolean; function G return Boolean renames F; function H return Boolean renames G; private function F return Boolean renames H; -- Legal? (No.) end Example; 8.5.4(5) says: The profile of a renaming-as-body shall be subtype-conformant with that of the renamed callable entity, and shall conform fully to that of the declaration it completes. If the renaming-as-body completes that declaration before the subprogram it declares is frozen, the subprogram it declares takes its convention from the renamed subprogram; otherwise the convention of the renamed subprogram shall not be Intrinsic. In the above example, the renaming-as-body for F occurs before F is frozen. Therefore, F takes its calling convention from H, which comes from G, which comes from F. So what is the calling convention of F? !recommendation For a subprogram whose body is defined by a renaming-as-body, if the rule in 8.5.4(5) requires the calling convention of the subprogram to be taken ultimately from itself, then the renaming-as-body is illegal. !wording (See corrigendum.) !discussion In the above example, the definition of the calling convention of F is not well-defined, because of the circular definition in 8.5.4(5). Therefore, we choose to make this case illegal. An alternative would be to define the calling convention to be Ada in this case. However, the compiler needs to detect the circularity anyway, in order to avoid an infinite loop during semantic analysis. Therefore, we might as well let the compiler give an error message, rather than generating infinitely-recursive code. Note that some circularities are legal. In particular, if the renaming-as-body completes a subprogram *after* that subprogram is frozen, the circularity is legal, and will be infinitely recursive at run time. For example: package Pack_1 is procedure P; end Pack_1; package Pack_2 is procedure Q; end Pack_2; with Pack_2; package body Pack_1 is procedure P renames Pack_2.Q; end Pack_1; with Pack_1; package body Pack_2 is procedure Q renames Pack_1.P; end Pack_2; The above is legal, the convention of P and Q is Ada, and a call to P or Q will be infinitely recursive. Note that we don't want to make *this* case illegal, since it cannot be detected at compile time. Here is another example of legal circularity: type Ptr is access function return Integer: function F return Integer; P: Ptr := F'Access; function F return Integer renames P.all; The convention of P.all is Ada, by 6.3.1(3). F is frozen by the declaration of P, by 13.14(6,4,11). Therefore, 8.5.4(5) does not specify the convention of F; it defaults to Ada, and the subtype conformance required by 8.5.4(5) is satisfied. Any call to F or P.all will result in infinite recursion. !corrigendum 8.05.04(5) @drepl The profile of a renaming-as-body shall be subtype-conformant with that of the renamed callable entity, and shall conform fully to that of the declaration it completes. If the renaming-as-body completes that declaration before the subprogram it declares is frozen, the subprogram it declares takes its convention from the renamed subprogram; otherwise the convention of the renamed subprogram shall not be Intrinsic. @dby The profile of a renaming-as-body shall be subtype-conformant with that of the renamed callable entity, and shall conform fully to that of the declaration it completes. If the renaming-as-body completes that declaration before the subprogram it declares is frozen, the subprogram it declares takes its convention from the renamed subprogram; otherwise the convention of the renamed subprogram shall not be Intrinsic. A renaming-as-body is illegal if the declaration occurs before the subprogram whose declaration it completes is frozen, and the renaming renames the subprogram itself, through one or more subprogram renaming declarations, none of whose subprograms has been frozen. !corrigendum 8.05.04(8) @dinsa For a call on a renaming of a dispatching subprogram that is overridden, if the overriding occurred before the renaming, then the body executed is that of the overriding declaration, even if the overriding declaration is not visible at the place of the renaming; otherwise, the inherited or predefined subprogram is called. @dinst @i<@s8> If a subprogram directly or indirectly renames itself, then it is a bounded error to call that subprogram. Possible consequences are that Program_Error or Storage_Error is raised, or that the call results in infinite recursion. !ACATS test Create a B-Test to check that a renaming-as-body is illegal if the declaration occurs before the subprogram it completes is frozen, and the renaming renames the subprogram itself (directly or indirectly). (Test, 7-1-0, ARG Letter Ballot, February 2001). Check that a legal circular renames (that is, doesn't violate 8.5.4(5/1)) is a bounded error, and raises Program_Error or Storage_Error or goes infinitely recursive (which ought to eventually raise Storage_Error). (No Test, 2-4-2, ARG Letter Ballot, February 2001). Such a test could run for a long time (if it goes infinitely recursive), which violates ACATS tests standards, so this cannot be tested. !appendix !section 8.5.4(05) !subject Renaming as Body !reference RM95-8.5.4(5) !from Ivan B. Cvar 96-04-25 !keywords renaming renaming-as-body body !reference 96-5517.a Ivan B. Cvar 96-4-25>> !discussion Here's a copy of a note I sent to Tucker Taft on this topic, followed by his response... -------------attachment starts here------------- Tucker, Would you mind answering another Ada95 language question? This one's for renaming-as-body declarations that rename themselves via another renaming (eg, circularity). What RM95 rule makes this completion of "&" illegal? Or, is it really legal, but supposedly caught at runtime by elaboration checks when the renaming is called (per 6.3(6), notwithstanding 3.11(10))? I hope it's not a legal completion, but we could not find a rule that would make it illegal. I checked 3.11, 6.all, 7.all, 8.all, etc. And neither 8.3(19) not 8.3(26) apply here. package EXAMPLE is function "&" ( L,R : Integer) return Integer; function OK ( L,R : Integer) return Integer renames "&"; private function "&" ( L,R : Integer) return Integer renames OK; --LEGAL OR NOT? end EXAMPLE; Thanks ...Ivan Date: Tue, 19 Mar 1996 15:37:15 -0500 From: stt@dsd.camb.inmet.com (Tucker Taft) To: ibc@ocsystems.com Subject: Re: Renaming as Body Sounds like a bug in the manual, since there is no way to decide what should be the calling convention for the subprogram, based on 8.5.4(10). The circularity is not by itself illegal, since you might not know at compile-time that there is a circularity (if the circularity involved multiple library units). The semantic model of a renaming-as-body is that one subprogram calls the other, so a circularity is no more illegal than is infinite recursion. (I suppose you could replace any call on such a routine with a "raise Storage_Error" ;-). But a circularity within a single package spec introduces problems because of the calling convention, and hence should be illegal. -Tucker Taft stt@inmet.com -------------attachment ends here------------- **************************************************************** !from Robert Eachus 99-08-08 I added wording to avoid putting an onerous burden on implementors. The intent is to make certain troublesome cases illegal, but the first sentence of the summary: "A circular renaming-as-body represents infinite recursion." is overly specific. This case should actually be a bounded error, allowing for at a minimum infinite recursion, Program_Error, or Storage_Error. I could even make an argument for allowing these cases to be detected and rejected at link time, but it seems to me that raising Program_Error for such circular renamings is easy enough: just flag them as never elaborated. If people think this is exceeding my charter, we can just omit the bounded error paragraph. **************************************************************** !from Randy Brukardt 99-10-07 At the recent ARG meeting, much discussion centered around this wording. The primary problem was: "Is it possible for this problem to occur with a frozen subporgram?" Examples were given. It is clear that at least one subprogram renaming must be unfrozen in order for the loop to be be detectable at compile-time, but it may not be the renaming that closes the loop. One alternative wording given for 8.5.4(5) was: It is illegal for a renaming-as-body that occurs before the subprogram it declares is frozen to rename itself, directly, or indirectly, through one or more renamings, none of which have been frozen. But it was decided this was wrong. One example given was the following: function "+" (A, B : Natural) return Natural; ... function "+" (A, B : Natural) return Natural renames "+"; Since only mode-conformance is required for non-frozen renames, we could end up with a case where the specification is not respected (that is, calls would be made without the constraint checking implied by the specification. It was agreed that this was bad. The wording was tabled. **************************************************************** From: Randy Brukardt Sent: Tuesday, April 11, 2000 6:20 PM The wording we hashed out at the meeting for AI-00135 (the infamous renames-as-body AI) was: A renaming-as-body is illegal if the declaration occurs before the subprogram it declares is frozen, and the renaming renames the subprogram itself through one or more subprogram renaming declarations, none of whose subprograms has been frozen. I'm updating the TC, and it strikes me that there is something wrong with this. A renaming-as-body is a completion, not a declaration, so it doesn't "declare" a subprogram. Shouldn't the wording be "...before the subprogram it completes is frozen..."? **************************************************************** From: Gary Dismukes Sent: Tuesday, April 11, 2000 6:31 PM I agree, the proposed wording is wrong and your suggested rewording sounds reasonable. **************************************************************** From: Tucker Taft Sent: Wednesday, April 12, 2000 7:56 AM You don't "complete" an entity, you "complete" a declaration. Hence, probably better would be something like "... before the freezing of the subprogram whose declaration it completes. **************************************************************** From: Gary Dismukes Sent: Wednesday, April 12, 2000 12:15 PM OK, but note that 3.11.1(1) says "The second part is called the completion of the declaration (and of the entity declared), ..." So it seems okay to talk about completion of entities. If we want to be really pedantic we shouldn't even use the verb 'complete', but only the noun 'completion', since 'complete' isn't a technical term as far as I can see :-) **************************************************************** From: Erhard Ploedereder Sent: Thursday, April 13, 2000 10:40 AM > I'm updating the TC, and it strikes me that there is something wrong with > this. A renaming-as-body is a completion, not a declaration, so it doesn't > "declare" a subprogram. Shouldn't the wording be "...before the subprogram > it completes is frozen..."? Yes. ****************************************************************