Version 1.9 of ais/ai-00064.txt
!standard 03.11 (10) 00-04-20 AI95-00064/10
!standard 03.11.01 (01)
!standard 08.05.04 (08)
!class binding interpretation 95-07-06
!status Corrigendum 2000 99-05-24
!status WG9 approved (8-0-0) 97-07-04
!status ARG approved (9-0-0) 97-04-11
!status work item (letter ballot was 10-1-1) 96-10-03
!status work item 96-06-14 (returned to ARG by WG9)
!status ARG approved 8-0-2 (by letter ballot) 96-06-05
!status ARG approved (subject to editorial review) 8-0-2 95-11-01
!status received 95-07-06
!reference AI95-00135
!priority High
!difficulty Hard
!qualifier Omission
!subject Elaboration checks for renamings-as-body
!summary
An elaboration check is performed for a call to a subprogram whose body
is given as a renaming-as-body. This check fails if the renaming-as-body
has not yet been elaborated. (As usual, an elaboration check is also
performed for the renamed subprogram, and fails if its body has not yet
been elaborated.)
!question
3.11(10) indicates that an elaboration check is required only when a
subprogram has an explicit body that is a subprogram_body. However,
when a renaming declaration is used as a body, it is possible for the
elaboration of the renaming declaration to require the evaluation of a
name, such as X.all, that implies some sort of elaboration check should
be performed. For example:
function F return Integer;
type Pointer_To_Func is access function return Integer;
X : Pointer_To_Func := Q'access; --
Y : Integer := F; --
....
Z : Pointer_To_Func := X;
function F return Integer renames Z.all;
In the above, clearly we need to wait until the expression "Z.all" is
evaluated before F can be safely called. However, it is not clear that
any check for this is required by 3.11(10).
By the way, where is "body" defined? It presumably includes entry body,
and perhaps renaming-as-body. However, only the syntactic entity BODY is
defined (in 3.11). Where is the unbolded term "body" defined?
!recommendation
(See summary.)
!wording
Define the term "body" to include the syntactic category body, plus
entry_body, plus renaming-as-body, in 3.11.1(1).
Change "subprogram_body" to "body" in 3.11(10).
Add a paragraph before 8.5.4(8) to define the run-time semantics of
renamings-as-body:
For a call to a subprogram whose body is given as a
renaming-as-body, the execution of the renaming-as-body is
equivalent to the execution of a subprogram_body that simply calls
the renamed subprogram with the same parameters.
Change the freezing rule in 13.14(3) to exclude renaming-as-body from
the freezing rules.
!discussion
Since the elaboration of a renaming-as-body may evaluate expressions, it
is clearly necessary that this elaboration be performed before calling
the subprogram. Therefore, an elaboration check should be done on a
subprogram whose body is a renaming-as-body, not just when the body is a
subprogram_body.
It seems that the right model for renaming-as-body that occurs after the
subprogram is frozen should be that of a wrapper subprogram, with its own
elaboration "bit."
Taken together, these rules imply that when calling a subprogram whose
body is a renaming-as-body, a check will be made that the renaming-as-body
has been elaborated, and also that the body of the renamed subprogram has
been elaborated. Furthermore, if the renamed subprogram is in turn
completed by another renaming-as-body, the body of that third subprogram
will also be checked; the rule is transitive.
See DR-0027 (AI95-00135) for a discussion of circularities involving
renamings-as-body.
This issue also adds the missing definition of lower-case "body". This change
makes a renaming-as-body a body. However, doing so triggers the freezing
rule 13.14(3): "A noninstance body other than a renaming-as-body causes
freezing of each entity declared before it within the same declarative_part."
It clearly was the intent of the designers of the language that
renaming-as-body not freeze (otherwise the second sentence of 8.5.4(5) could
never be true), and existing compilers do not freeze when a renaming-as-body
is encountered. We do not want to change this behavior, so we add an exception
to 13.14(3).
!corrigendum 3.11(10)
Replace the paragraph:
- For a call to a (non-protected) subprogram that has an explicit
body, a check is made that the subprogram_body is already
elaborated. This check and the evaluations of any actual
parameters of the call are done in an arbitrary order.
by:
- For a call to a (non-protected) subprogram that has an explicit
body, a check is made that the body is already elaborated. This check and
the evaluations of any actual parameters of the call are done in an
arbitrary order.
!corrigendum 3.11.01(1)
Replace the paragraph:
Declarations sometimes come in two parts. A declaration that requires a
second part is said to require completion. The second part is called the
completion of the declaration (and of the entity declared), and is
either another declaration, a body, or a pragma.
by:
Declarations sometimes come in two parts. A declaration that requires a
second part is said to require completion. The second part is called the
completion of the declaration (and of the entity declared), and is
either another declaration, a body, or a pragma. A body is a body,
an entry_body, or a renaming-as-body (see 8.5.4).
!corrigendum 8.05.04(8)
Insert before 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:
For a call to a subprogram whose body is given as a renaming-as-body, the
execution of the renaming-as-body is equivalent to the execution of a
subprogram_body that simply calls the renamed subprogram with its formal
parameters as the actual parameters and, if it is a function, returns the value
of the call.
!corrigendum 13.14(3)
Replace the paragraph:
The end of a declarative_part, protected_body, or a declaration of a
library package or generic library package, causes freezing of each entity
declared within it, except for incomplete types. A noninstance body causes
freezing of each entity declared before it within the same declarative_part.
by:
The end of a declarative_part, protected_body, or a declaration of a
library package or generic library package, causes freezing of each entity
declared within it, except for incomplete types. A noninstance body other than
a renaming-as-body causes freezing of each entity declared before it within the
same declarative_part.
!ACATS test
ACATS test C854002 was constructed to check this ruling, and checks cases
similiar to the example in the question.
!appendix
!section 3.11(9)
!section 8.5.4(1)
!subject Renaming-as-body and elaboration
!reference RM95 3.11(9,10)
!reference RM95 8.5.4(1)
!from Tucker Taft 95-07-05
!reference as: 95-5208.a Tucker Taft 95-7-5>>
!discussion
In 3.11(10), it indicates that an elaboration check is only
required when a subprogram has an explicit body that is a
subprogram_body. However, when a renaming declaration is
used as a body, it is possible for the elaboration of the
renaming declaration to require the evaluation of a name,
such as X.all, that implies some sort of elaboration check
should be performed. For example:
function F return Integer;
type Pointer_To_Func is access function return Integer;
X : Pointer_To_Func := Q'Access; -- Presume Q already elaborated
Y : Integer := F; -- We need some sort of elaboration check
....
Z : Pointer_To_Func := X;
function F return Integer renames Z.all;
In the above, clearly we need to wait until "Z.all" is elaborated
before calling F. However, it is not clear that any
check for this is required by 3.11(10).
It seems that the right model for renaming-as-body that
occurs after the subprogram is frozen should be that of a wrapper
subprogram, with its own elaboration "bit."
By the way, where is "body" defined? It presumably includes
entry body, and perhaps renaming-as-body. However, only the
syntactic entity BODY is defined (in 3.11). Where is the
unbolded term "body" defined?
-Tuck
****************************************************************
!section 03.11(09)
!subject Call for letter ballot on AI95-00064
!reference AI95-00064/01
!from Norman Cohen 96-04-29
!reference 96-5524.a Norman H. Cohen 96-4-29>>
!discussion
I call for a letter ballot on AI-64 because I believe the elaboration
check needs to be defined more precisely: Presumably, it is checked
both that the renaming declaration has been elaborated and that the
body of the renamed subprogram has been elaborated. (In addition, the
AI should make it obvious that this check is performed at the time of a
call.)
I suggest that the !recommendation be rewritten in
language that parallels 3.11(10) and 3.11(14):
For a call to a (non-protected) subprogram that has a
renaming-as-body, a check is made that the renaming declaration has
already been elaborated, and that the body of the subprogram named in
the renaming declaration has already been elaborated. This check and
the evaluations of any actual parameters of the call are done in an
arbitrary order. The exception Program_Error is raised if this check
fails.
(Perhaps just the first sentence will suffice as the !summary.)
Can this be considered an editorial correction, and a revised version
recirculated for letter ballot, before the next meeting?
****************************************************************
!section 3.11(09)
!subject Call for letter ballot on AI95-00064
!reference 03.11(09)
!reference AI95-00064/01
!reference 96-5524.a Norman Cohen 96-04-29
!reference 96-5543.a Robert A Duff 96-5-8>>
!discussion
Norman says:
> I call for a letter ballot on AI-64 because I believe the elaboration
> check needs to be defined more precisely: Presumably, it is checked
> both that the renaming declaration has been elaborated and that the
> body of the renamed subprogram has been elaborated. (In addition, the
> AI should make it obvious that this check is performed at the time of a
> call.)
>
> I suggest that the !recommendation be rewritten in
> language that parallels 3.11(10) and 3.11(14):
>
> For a call to a (non-protected) subprogram that has a
> renaming-as-body, a check is made that the renaming declaration has
> already been elaborated, and that the body of the subprogram named in
> the renaming declaration has already been elaborated. This check and
> the evaluations of any actual parameters of the call are done in an
> arbitrary order. The exception Program_Error is raised if this check
> fails.
>
> (Perhaps just the first sentence will suffice as the !summary.)
I agree with Norm's complaint. However, I think the above wording fails
to handle the transitive cases. If the body of P renames Q, and the
body of Q renames R, and the body of R renames S, then we need to check
that the bodies of all of P, Q, R, and S have been elaborated. The
above wording only checks P and Q.
I think a better solution is to add something like this to the !wording
section:
Add a paragraph before 8.5.4(8) to define the run-time semantics of
renamings-as-body:
The execution of a renaming-as-body is equivalent to the execution
of a subprogram_body that simply calls the renamed subprogram
with the same parameters.
This makes the rule correctly transitive, and I think is more elegant
anyway.
> Can this be considered an editorial correction, and a revised version
> recirculated for letter ballot, before the next meeting?
Will do.
By the way, I disagree that the !summary needs to be so precise.
Everybody knows that elaboration checks are done at call sites, and the
summary is supposed to be as simple as possible without being outright
wrong.
The !wording section, on the other hand, defines the precise rule (or it
will, soon). (This is one AI that I thought was subtle enough that it
deserved to have a wording section.) So, Norm, I suggest you read the
new !wording when I send it out, and criticize *that* if you think it's
still not right.
- Bob
****************************************************************
From: Erhard Ploedereder
Sent: Monday, April 03, 2000 4:19 AM
Dear ARG members that were not in Phoenix,
On one of the TC items we ran into secondary technical problem. Rather
than have you wait for the minutes, I want to solicit your opinion on
the issue now.
The wording change for the AI that resolves the elaboration question
includes a renaming-as-body in the semantic category "body". However,
noninstance bodies freeze all entities declared before them.
We had a choice to make and we chose to explicitly exclude renaming-as-body
from this freezing rule, largely because we did not want to mess with the
presumed designers' intent that renames don't cause freezing. We noted,
however, that such freezing would solve the circular renaming AI (and the
taking of the convention from the renamed subprogram) trivially.
Was our choice the right one ? If you believe that we should make
renaming-as-body a cause for freezing, speak up now.
****************************************************************
From: Robert Dewar
Sent: Monday, April 03, 2000 8:41 AM
This seems very wrong to me. Renaming-as-body should be semantically
equivalent to the expanded body. Indeed on GNAT that's all it is. I
suppose some glitch can be programmed into the implementation to make
this a special case, but I would find this non-equivalence weird from
a semantic point of view anyway.
****************************************************************
From: Pascal Leroy
Sent: Monday, April 03, 2000 9:07 AM
I agree.
If you think of maintenance it's likely that some bodies will need to be changed
from a renaming-as-body to a true body (or vice-versa). This should be possible
without affecting the legality of the code.
The current rules already make sure that you can switch between a subunit and a
proper body without trouble. I see no reason to use different rules for a
renaming-as-body.
Incidentally our compiler current does not consider that a renaming-as-body
freezes, but changing that is a one-liner.
****************************************************************
From: Ed Schonberg
Sent: Monday, April 03, 2000 8:36 AM
GNAT does not treat the renaming_as_body as a freezing point, we see no
reason to change the rule, so we are happy with the exclusion.
****************************************************************
From: Tucker Taft
Sent: Monday, April 03, 2000 9:23 AM
Renaming as body should not freeze in my opinion.
I think it is important that you can declare several subprograms in the
visible part, and then complete them in the private part via renaming,
without losing the possibility that non-Ada conventions are carried
over from the renamed entity. E.g.:
type My_Int is private;
function Plus(L, R : My_Int) return My_Int;
function Minus(L, R : My_Int) return My_Int;
private
type My_Int is new Integer;
function Plus(L, R : My_Int) return My_Int renames "+";
function Minus(L, R : My_Int) return My_Int renames "-";
This would not work if the first renaming-as-body froze things.
****************************************************************
From: Robert Dewar
Sent: Monday, April 03, 2000 9:35 AM
Ed said
<<GNAT does not treat the renaming_as_body as a freezing point, we see no
reason to change the rule, so we are happy with the exclusion.
>>
OK, so implementation is not an issue in terms of GNAT.
I still find it an odd difference, but am not willing to argue strongly
against the majority conclusion :-)
****************************************************************
From: Tucker Taft
Sent: Monday, April 03, 2000 9:52 AM
Robert Dewar wrote:
>
> This seems very wrong to me. Renaming-as-body should be semantically
> equivalent to the expanded body. Indeed on GNAT that's all it is. I
> suppose some glitch can be programmed into the implementation to make
> this a special case, but I would find this non-equivalence weird from
> a semantic point of view anyway.
There are really two kinds of renaming-as-body. One which
happens before the spec is frozen, and one after the spec is
frozen. If the spec is not yet frozen, the renaming-as-body
must be treated essentially like a deferred renaming-as-spec.
The renaming-as-body is "seen" by all callers in this case,
so you can really just redirect the call to the renamed routine.
A renaming-as-body after the spec is frozen really has to produce
an out-of-line body, even if it consists of only a "jump," unless
you can play various link-time games with redirecting one link-name
to bind to another (of course, that doesn't work if the renaming-as-body
renames blah.all).
So I suppose it would be OK if a renaming-as-body after the spec
is frozen also froze other stuff, but I worry about incompatibilities
where there are several "early" renaming-as-bodies with one
"late" one interspersed, thereby converting all the remaining
"early" renamings into late ones, and preventing non-Ada conventions.
****************************************************************
From: Robert Dewar
Sent: Monday, April 03, 2000 9:55 AM
<<Incidentally our compiler current does not consider that a
renaming-as-body freezes, but changing that is a one-liner.>>
It is vaguely worrying that both Rational and GNAT are "wrong"
here if we change it. What about other Ada 95 front ends?
There is an argument for maintaining the current *behaviuor* if it is
uniform.
****************************************************************
From: Robert A Duff
Sent: Monday, April 03, 2000 10:34 AM
Pascal says:
> If you think of maintenance it's likely that some bodies will need to be
> changed from a renaming-as-body to a true body (or vice-versa). This
> should be possible without affecting the legality of the code.
Ahh, so we need to change the syntax rules to allow proper bodies in
package specs. I wonder if Robert will insist that it be non-binding?
;-) ;-)
During the 9X project, I had the same reaction as Robert: it's ugly for
renaming-as-body to be anything but a short-hand. We discussed the
issue of freezing, in particular. Tucker overruled me at the time,
putting usefulness ahead of uniformity. There's no reason to change
that decision now.
****************************************************************
From: Pascal Leroy
Sent: Tuesday, April 04, 2000 2:51 AM
Yes, to be honest I keep forgetting that a renaming-as-body is legal in a spec.
****************************************************************
From: Robert Dewar
Sent: Wednesday, April 05, 2000 5:05 AM
To be really honest, I did not know (or have forgotten) that it is
legal in a spec. How odd .. seems a real mistake to me, precisely
because it is not orthogonal to the idea of it simply being an
abbreviation.
A nice example of how simplicity at the definitional level (which is
hopefully improved by this peculiar feature) is so different from
simplicitly at the learning level (allowing this in a spec definitely
makes it harder to understand at least to me). Reminds me of
a : aliased string := "asef"
and
a : aliased string (1 .. 4) := "asef";
being different.
Well I guess since this feature is odd, and has no simple semantic
explanation as expansion into a body, making it a bit odder by having
(what appears to the uninitiated as) an exception to the expected
freezing by a body is no big deal.
After all one cannot imagine a program being damaged by the *lack* of
freezing, so if all implementations avoid the freeze, I don't see any
real harm.
I do see harm if we change implementations the other way, since this
can indeed cause working programs to fail.
****************************************************************
From: Robert A Duff
Sent: Wednesday, April 05, 2000 8:06 AM
Generic instantiations can cause bodies to appear in specs, even though
bodies are syntactically illegal in specs. Strange, perhaps, but we've
learned to live with it.
****************************************************************
Questions? Ask the ACAA Technical Agent