Version 1.9 of ais/ai-00135.txt
!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; --
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)
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 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)
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 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.
****************************************************************
Questions? Ask the ACAA Technical Agent