Version 1.2 of ais/ai-00135.txt

Unformatted version of ais/ai-00135.txt version 1.2
Other versions for file ais/ai-00135.txt

!standard 08.05.04 (05)          99-08-08 AI95-00135/03
!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
!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:
5 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.
The wording of the recommendation refers to the effect of the rule in 8.5.4(5), rather than stating the exact cases explicitly, because the explicit definition would be complicated. Here's another way to state the rule: Start from the renaming-as-body in question. Follow all renamings-as-declaration. Follow all renamings-as-body that occur before their own freezing point. Do not follow other renamings-as-body. If you eventually get back to the declaration of the subprogram in question, then it's illegal.
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)
Replace the paragraph:
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.
by:
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 is frozen, and the renaming renames the subprogram itself, either directly or indirectly.
!corrigendum 8.05.04(8)
Insert after the paragraph:
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.
the new paragraph:
Bounded (Run-Time) Errors
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 an indefinite loop.
!ACATS test
A B-Test should be created to check the illegal case. The B-Test should include the legal cases as well. (Note that a C-Test can't be usefully constructed, as any call would never terminate.)
!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.

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

Questions? Ask the ACAA Technical Agent