Version 1.8 of ais/ai-00229.txt

Unformatted version of ais/ai-00229.txt version 1.8
Other versions for file ais/ai-00229.txt

!standard 3.10.2 (32)          01-05-20 AI95-00229/02
!class binding interpretation 00-04-10
!status ARG approved 6-0-2 01-05-20
!status work item 01-05-04
!status received 00-04-10
!priority Medium
!difficulty Medium
!qualifier Omission
!subject Accessibility rules and generics
!summary
The expression P'Access (where P denotes a subprogram declared in a generic specification) is illegal within a generic body if the expected access type is not declared within the generic unit.
!question
The following piece of code seems to show a case where the accessibility rules allow the creation of reference to a subprogram that doesn't exist anymore.
This case doesn't seem to be caught by the "assume the worst" rule in the last sentence of RM95 3.10.2(32), because Foo is not declared in a generic body.
procedure Dangle is type Ref is access procedure; P : Ref;
generic package G is procedure Foo; end G;
package body G is X : Natural := 0;
procedure Foo is begin X := X + 1; end Foo; begin P := Foo'access; -- Legal? (No.) end G;
procedure Bar is package I is new G; -- Store a reference to I.Foo in P. begin null; end Bar;
begin Bar; P.all; -- Oops, I.X is gone? end Dangle;
!recommendation
See wording.
!wording
Add after the last sentence of RM95 3.10.2(32):
If the subprogram denoted by P is declared within a generic specification, and the expression P'Access occurs within the body of that generic, then the ultimate ancestor of S shall be declared within the generic unit.
!discussion
Evidently we want to disallow the above construct, because dangling references are a very serious safety issue. However, there is a compatibility issue here, because there may be code out there that uses access-to-subprogram types in conjunction with generics, and whatever solution we come up with could possible make existing code invalid (even if that code doesn't actually create dangling references).
The proposed modification fixes the above dangling reference problem without unnecessarily impacting existing code.
!corrigendum 03.10.02(32)
Replace the paragraph:
P'Access yields an access value that designates the subprogram denoted by P. The type of P'Access is an access-to-subprogram type (S), as determined by the expected type. The accessibility level of P shall not be statically deeper than that of S. In addition to the places where Legality Rules normally apply (see 12.3), this rule applies also in the private part of an instance of a generic unit. The profile of P shall be subtype-conformant with the designated profile of S, and shall not be Intrinsic. If the subprogram denoted by P is declared within a generic body, S shall be declared within the generic body.
by:
P'Access yields an access value that designates the subprogram denoted by P. The type of P'Access is an access-to-subprogram type (S), as determined by the expected type. The accessibility level of P shall not be statically deeper than that of S. In addition to the places where Legality Rules normally apply (see 12.3), this rule applies also in the private part of an instance of a generic unit. The profile of P shall be subtype-conformant with the designated profile of S, and shall not be Intrinsic. If the subprogram denoted by P is declared within a generic body, S shall be declared within the generic body. If the subprogram denoted by P is declared within a generic specification, and the expression P'Access occurs within the body of that generic, then ultimate ancestor of S shall be declared within the generic unit.
!ACATS test
A B-Test is needed for this issue.
!appendix

From: Pascal Leroy
Sent: Wednesday, April 05, 2000 3:54 AM

The following piece of code seems to show a case where the accessibility rules
allow the creation of reference to a subprogram that doesn't exist anymore.

This case doesn't seem to be caught by the "assume the worst" rule in the last
sentence of RM95 3.10.2(32), because Foo is not declared in a generic body.  It
seems that we either need a stronger rule (as in: "If the subprogram denoted by
P is declared within a generic, S shall be declared within the generic") or a
runtime check.

Or am I missing something?

procedure Dangle is
    type Ref is access procedure;
    P : Ref;

    generic
    package G is
        procedure Foo;
    end G;

    package body G is
        X : Natural := 0;

        procedure Foo is
        begin
            X := X + 1;
        end Foo;
    begin
        P := Foo'Access; -- You would hope that this would be illegal.
    end G;

    procedure Bar is
        package I is new G; -- Store a reference to I.Foo in P.
    begin
        null;
    end Bar;

begin
    Bar;
    P.all; -- Oops, I.X is gone?
end Dangle;

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

From: Steve Baird
Sent: Thursday, April 06, 2000 3:44 PM

>  It seems that we either need a stronger rule (as in: "If the subprogram
> denoted by P is declared within a generic, S shall be declared within the
> generic") or a runtime check.

That rule is a little more restrictive than is necessary.

If the use of
    Some_Subprogram'Access
occurs within the spec, not the body, of the generic in which
Some_Subprogram is declared, then there is no need to
disallow the construct (because instantiation rechecking will
handle matters if the generic is instantiated in an inner scope).

How bad would it be if Ada95 suddenly started disallowing the following:

    type Ref is access procedure;

    generic
    package G is
        procedure P;
        X : Ref := P'Access;
    end G;

    package body G is ... ;

    package I is new G;

?

The notion of "inside a generic" may also need to be defined fairly
precisely in order to handle interactions with child units of generics.

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

From: Gray, Michael
Sent: Thursday, May 17, 2001 7:22 AM

The following Ada 95 Language issues arose in a development we have
undertaken at Naval Combat Systems, a group within BAeSYSTEMS. I have
collected them together and am submitting them for consideration, as per LRM
Introduction paras (58) et seq.

!topic Shortcomings in the generic contract model w.r.t. access-to-subprogram types
!reference RM95-3.10.2(20)
!from Michael Gray
!discussion

The intent of the language is that access to subprogram types are never
subject to run-time accessibility checks.

Justification for this assertion is:
(i) Rationale sect 3.7.2 para 2 says "Compile-time accessibility rules
ensure that a subprogram designated by an access value cannot be called
after its enclosing scope has exited.",
(ii) LRM 3.10.2 (20) states "For determining whether one level is statically
deeper than another when within a generic package body, the generic package
is presumed to be instantiated at the same level as where it was declared;
run-time checks are needed in the case of more deeply nested instantiations.
Para (29), relating to access-to-object says "A check is made that the
accessibility level of X is not deeper than that of the access type A. If
this check fails, Program_Error is raised." There is no corresponding
statement for access-to-subprogram.

Consider a generic package, where the spec declares a subprogram Q, and an
operation in the body assigns Q'Access to a library-level variable. If the
generic instantiation is not library level, this will give rise to a
dangling reference. The language could either:
(i) make the instantiation illegal because of the assignment in the body -
but that's a violation of the generic contract model, or
(ii) insert a run-time check, but that's a violation of the principle that
access to subprogram types are never subject to run-time accessibility
checks.

At the very least, the LRM is unclear about what is supposed to happen. This
is an area where the generic contract model is rather thin; probably the
least bad solution is to make it clear that run-time checks are required in
the access-to-subprogam case. AI95-00254 covers some similar issues.

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

From: Randy Brukardt
Sent: Wednesday, May 23, 2001 4:21 PM

This issue appears to be the same as the one raised in AI-229. How is this
issue different than the one in that AI (considered at last week's ARG
meeting)?

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

From: Gray, Michael
Sent: Thursday, May 24, 2001 4:13 AM

It is the same issue. Sorry, I'm not up to speed with the protocol for
establishing whether comments have previously been raised. I've just had a
browse around www.ada-auth.org to try to better understand the process.

Since AI-229 was considered at "last week's ARG meeting", I'll defer adding
any comments until the minutes appear at www.ada-auth.org; what's the
expected timescale for that?

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

From: Randy Brukardt
Sent: Thursday, May 24, 2001 11:39 AM

Well, about all you can do is to check the AI cross reference listing for
matches. Usually searching the subjects and by the appropriate section is
most helpful. Don't feel too bad about; everyone misses these from time
to time.

> Since AI-229 was considered at "last week's ARG meeting", I'll defer adding
> any comments until the minutes appear at www.ada-auth.org; what's the expected
> timescale for that?

Minutes usually are finalized just before the next meeting. If it helps,
here are my (raw) notes for AI-229 (I've expanded the names):

> AI-229

> Tuck[er Taft] suggests merging the existing wording sentence with the new one.
> Pascal [Leroy] notes that that would be a bigger change (disallows access in
> spec).

> John [Barnes] then wonders why we don't have this problem with objects.
> Tuck[er Taft] notes that there is a runtime check there; and wonders why this
> does not apply to access-to-subprogram.

> Randy [Brukardt] is asked about the generic sharing problem that led to the
> original rule. He explains that the problem is that the "hidden" instantiation
> data parameter used for all routines declared in a generic unit cannot be added
> when 'Access is used in the body (even through a "thunk" could be generated at
> that point, there is no way to identify the appropriate data when calling
> through the access-to-subprogram ptr.) This is not a problem for access types
> declared in the generic unit as the needed parameter is included in the
> profile for such types.

> Eventually, the rule as proposed is retained.

> Pascal [Leroy] notes that the new sentence should say "ultimate ancestor of the
> access type".

>Approval with changes: 6-0-2

The "changes" in this case is just the wording change as noted by Pascal.

I intend to have the revised AI posted on the web site today.

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

From: Gray, Michael
Sent: Friday, May 25, 2001 5:43 AM

I just checked the website and didn't see an update to AI-229. But from what
you say below, I think the new rule is

"If the subprogram denoted by P is declared within a generic specification,
and the expression P'Access occurs within the body of that generic, then the
ultimate ancestor of the access type S shall be declared within the generic
unit."

This will make some existing code illegal. However, I believe that there is
a systematic way of dealing with this, namely place:

  P_Access : Ref := P'Access;

in the generic spec (in practice, this would generally be put in the private
part of the spec); and within the generic body, replace P'Access by
P_Access. That doesn't seem too bad, in terms of code impact. Of course,
this could also make some existing instantiations illegal; but since they
were instantiations that could give rise to a dangling reference, that
doesn't seem to be a bad thing. And specifically, an instantiation at
library-level accessibility can never be invalidated by this modification.

Do you agree with my analysis?

The new rule seems incomplete with respect to child units. In the new rule,
doesn't "the expression P'Access occurs within the body of that generic"
need to be extended with "or the specification or body of a child of that
generic"?

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

From: Randy Brukardt
Sent: Friday, May 25, 2001 9:18 PM

> Do you agree with my analysis?

Yes. It was expected that some existing code would be made illegal; that's the
cost of eliminating dangling references. The work-around is the same one
recommended for

> The new rule seems incomplete with respect to child units. In the new rule,
> doesn't "the expression P'Access occurs within the body of that generic"
> need to be extended with "or the specification or body of a child of that
> generic"?

I don't claim to understand children of generics very well, but I think that
they are logically generic units in their own right. Thus, the same (original)
rule applies to them as well. Is there a problem case that we haven't thought
of??

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

From: Gray, Michael
Sent: Tuesday, May 29, 2001 4:27 AM


> Yes. It was expected that some existing code would be made illegal; that's
> the cost of eliminating dangling references. The work-around is the same one
> recommended for

... I think you missed some text out here.


How about the following. I had to modify the structure of the original
example 'cos child packages have to be library-level; but it's the same
basic principle.

I think I was incorrect to say that the new rule needs to be extended to
cover the case of P'Access in the /spec/ of a child unit, because I think
that is already illegal by 3.10.2 (32). But the case of P'Access in a child
unit /body/ does need to be caught by the new rule.


----------------------------------

package Global is
  type Ref is access procedure;
  P, Q : Ref;
end Global;

generic
package G is
  procedure Foo;
end G;

with Global;
package body G is
  X : Natural := 0;

  procedure Foo is
  begin
     X := X + 1;
  end Foo;
begin
  Global.P := Foo'Access; -- the new rule makes this illegal.
end G;

generic
package G.C is
  procedure Dummy; -- just to make body non-optional
end;

with Global;
package body G.C is
  procedure Dummy is begin null; end;
begin
  Global.Q := Foo'Access; -- but the new rule does not make this illegal.
end G.C;

with G.C;
with Global;
procedure Dangle is

  procedure Bar is
    package I is new G; -- Store a reference to I.Foo in Global.P.
    package J is new I.C; -- and store another one in Global.Q.
  begin
    null;
  end Bar;

begin
  Bar;
  Global.P.all; -- Oops, I.X is gone?
  Global.Q.all; -- ditto
end Dangle;

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

From: Randy Brukardt
Sent: Thursday, May 31, 2001 9:13 PM

> > Yes. It was expected that some existing code would be made illegal; that's
> > the cost of eliminating dangling references. The work-around is the same one
> > recommended for
>
> ... I think you missed some text out here.

I went to look up a reference, got side-tracked, and never finished the
thought. But it was something to the effect that the work-around is the
standard one for avoiding accessibility checks in generics. (I suspect that
the example I cannot find was deleted from AARM when object types were given
run-time accessibility checks - that was relatively late in the design of
Ada 95.)

> How about the following. I had to modify the structure of the original
> example 'cos child packages have to be library-level; but it's the same
> basic principle.

I think you are correct. Created a slightly modified version of your program
(I just added some Text_IO calls so we can see what's going on).

I compiled it on GNAT 3.14a for grins, and it compiles successfully, and
when I run it, I get:

-- B3A200X - Create dangling references (AI-229)
** B3A200X_G.Foo called!

raised PROGRAM_ERROR : unhandled signal

I then tried ObjectAda 7.2, which also compiles successfully, and when I run
it, I get:

-- B3A200X - Create dangling references (AI-229)
Program terminated by an exception propagated out of the main subprogram.
Exception raised : Constraint_Error
Exception message : access error
Executable name:   C:\PROGRAM
FILES\AONIX\OBJECTADA\W\W-WIN32(INTEL)-DEBUG\B3A20
0X.EXE

Line      Subprogram name                 File
--------  ------------------------------  ------------
      18  b3a200x.bar.i.foo               b3a200x.a
      52  b3a200x                         b3a200x.a
     300  _rtsadamain                     m:\adamagic\src\rts_nt\init.c

End of propagation.
Program aborted.

Obviously, this is a real problem! (If someone would like the program, just
ask me.)

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

From: Gray, Michael
Sent: Thursday, May 31, 2001 6:25 AM

> But the case of P'Access in a child unit /body/ does
> need to be caught by the new rule.
>

and so does the case of P'Access in the body of a generic that takes an
instantiation of G (the package which declares P) as a formal package
parameter.

... which makes me think that some systematic analysis is required to
identify /all/ the cases in which dangling references to subprograms could
arise.


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

From: Randy Brukardt
Sent: Thursday, May 31, 2001 9:43 PM

> > But the case of P'Access in a child unit /body/ does
> > need to be caught by the new rule.
> >
>
> and so does the case of P'Access in the body of a generic that takes an
> instantiation of G (the package which declares P) as a formal package
> parameter.

Ugh.

> ... which makes me think that some systematic analysis is required to
> identify /all/ the cases in which dangling references to subprograms could
> arise.

Sounds like you're doing a good job; keep it up! :-)

Seriously, I'm not sure how anyone could go about a systematic analysis.
These are a bunch of rather weird cases. Keep in mind that a child of a
generic is just syntactic sugar for an implicit generic package parameter
(at least that is how it was sold to the DRs). So it's no surprising that
both have the same problem.

I modified my test program to include a formal package case, with
essentially the same results as the previous version of the program. (That
is, none of the compilers detected an error, and failed at runtime in
various ways.)

It seems to me that the existing rules cover all of the cases except those
in generic bodies. Thus, we simply have to prohibit problems in generic
bodies. Probably the best way is simply to outlaw them. I think a rule
trying to define exactly which generic bodies cannot take 'Access probably
would simply leave more holes for future patching.

So, I suggest fixing the rule as follows:

"If the subprogram denoted by P is declared within a generic specification,
and the ultimate ancestor of S is not declared within the generic unit, then
the expression P'Access shall not occur in any generic body."

(Spelling out the places that are illegal would have to say:
"If the subprogram denoted by P is declared within a generic specification,
and the ultimate ancestor of S is not declared within the generic unit, then
the expression P'Access shall not occur in the generic body, the body of any
child of the generic unit, or in the body of any generic which has a formal
parameter of the generic unit."
Quite a mouthful!)

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

From: Pascal Leroy
Sent: Friday, June 1, 2000 9:19 AM

> and so does the case of P'Access in the body of a generic that takes an
> instantiation of G (the package which declares P) as a formal package
> parameter.

True.  In fact, you don't even need a formal package to do the trick, a formal
subprogram is enough.

I believe that the wording "generic specification" is lousy.  It should say "the
visible or private part of a generic".  Because the formal part is part of the
visible part, the problem you mention should be covered.  Also, it deals nicely
with the case of a generic subprogram, a situation which I overlooked when I did
the initial write-up.

Regarding the issue with children of generics, I believe it would be sufficient
to talk of "the body of any descendant" of the generic in question.

So I guess I am proposing the following wording:

"If the subprogram denoted by P is declared within the visible or private part
of a generic, and the expression P'Access occurs within the body of a descendant
of that generic, then the ultimate ancestor of S shall be declared within the
generic unit."

Comments anyone?

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

From: Randy Brukardt
Sent: Friday, June 1, 2001 7:10 PM

This looks better than my attempt.

However, we now have two very similar rules, which I think we can merge. For
reference, the existing rule is:

"If a subprogram denoted by P is declared within a generic body, S shall be
declared within the generic body."

The predicate can easily be merged. Since there is no outside visibility into a
body, the part about P'Access occuring in the body is redundant.

The interesting question is whether there is any need to restrict S to the
generic body for subprograms declared in the body. I don't think there is for
generic sharing purposes (if there is a reason, it would also apply to the new
rule), and there can't be any accessibility problems. So I think it is OK to
allow S to be declared anywhere in the generic. Thus, we get the following
(which replaces the existing rule):

"If the subprogram denoted by P is declared within a generic, and the expression
P'Access occurs within the body of a descendant of that generic, then the
ultimate ancestor of S shall be declared within the generic unit."

A nice simple rule. It even allows a few cases currently rejected. Does anyone
have an objection to this rule??

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

From: Tucker Taft
Sent: Saturday, June 2, 2001 8:59 AM

The wording needs some work.  First of all, program units don't have
"descendants." Only library units have descendants.  Also, we should probably
always say "generic unit" rather than simply "generic."  Finally, I don't think
we need to even talk about descendants at all, since where else would P be
visible? Here is an attempt at an alternative:

   If the subprogram denoted by P is declared within a generic unit and
   the expression P'Access occurs within a body that does not itself enclose
   the generic unit, then the ultimate ancestor of S shall be declared
   with the generic unit.

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

From: Randy Brukardt
Sent: Saturday, June 2, 2001 9:36 PM

This seems to imply that using a 'Access of something declared in an instance
cannot occur in a body. I suppose the usual hair splitting (about the difference
between a generic and an instance) protects us, but I think it would be better
if we were clearer. The "does not itself enclose the generic unit" is tricky,
too, as it includes the body of the unit itself, but that certainly isn't
obvious to a casual reading.

So, I guess I'd prefer correcting my attempt to repair the problem with
descendants than to make the wording tricky and confusing.

How about the following:

"If the subprogram denoted by P is declared within a generic unit, and the
expression P'Access occurs within the body of that generic unit or in the body
of a descendant of that generic unit, then the ultimate ancestor of S shall be
declared within the generic unit."

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

From: Tucker Taft
Sent: Sunday, June 3, 2001 8:55 AM

You are still using the term "descendant".  How about:

"If the subprogram denoted by P is declared with a generic unit, and the
expression P'Access occurs within the body of that generic unit or of
a generic unit declared within the immediate scope of the subprogram."

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

From: Randy Brukardt
Sent: Monday, June 4, 2001 2:30 PM

Well, Pascal used it first. But I think it is necessary; we're only talking
about library units in that phrase.

> If the subprogram denoted by P is declared with a generic unit, and the
> expression P'Access occurs within the body of that generic unit or of
> a generic unit declared within the immediate scope of the subprogram.

This doesn't cover children of generics, which is the problem. Moreover, I
don't think that the scope of the subprogram has anything to do with it at all.
(Unless this intended to be a backwards way of saying any generic logically
declared in the generic).

The problem occurs in generic bodies, in nested bodies, and in children of
generic units (which necessarily must be generic). We do not want to include
any other cases in the wording; generic specifications will be rechecked (and
code generated for the sharing case) on instantiation, and thus do not cause
problems.

Nested bodies (including generic bodies) are covered by "within the body of
that generic unit", we don't need any wording for them (We didn't say "directly
within"). "...or the body of a descendant of that generic unit" covers the
children. Necessarily, such children are library units so "descendant" applies
to them. Non-library unit generics don't have any descendants, so that phrase
doesn't apply to them.

So, I guess I'm saying I don't understand your objection to "descendant".

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

From: Tucker Taft
Sent: Monday, June 4, 2001 5:15 PM

> Well, Pascal used it first. But I think it is necessary; we're only talking
> about library units in that phrase.

Well, I still don't agree with the usage.  Descendant is
only defined for library units, so you should at least say
something like, "... or, in the case the generic unit is a library unit,
within the body of a descendant of that generic unit, then ...

> > If the subprogram denoted by P is declared with a generic unit, and the
> > expression P'Access occurs within the body of that generic unit or of
> > a generic unit declared within the immediate scope of the subprogram.
>
> This doesn't cover children of generics, which is the problem.

Hmmm....  I guess you are right, if the subprogram is declared within
a package nested in the generic.  So how about:

    If the subprogram denoted by P is declared within a generic unit,
    and the expression P'Access occurs within the body of that generic
    unit, or within the body of a generic unit declared within
    the declarative region of the generic, then the ultimate ancestor
    of P shall be declared within the generic unit.

This avoids the problematic use of the term "descendant."

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

From: Randy Brukardt
Sent: Monday, June 4, 2001 8:28 PM

Sigh. This may be a case where I have to yield to "Tucker knows best" :-)

I'd still be a bit concerned that this seems to imply something not there
(that only uses DIRECTLY within a generic body are affected). But I'll live
with this (with a suitable AARM note to say that the second phrase is really
talking about children of this generic).

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

From: Pascal Leroy
Sent: Tuesday, June 5, 2001 7:45 AM

> The interesting question is whether there is any need to restrict S to the
> generic body for subprograms declared in the body. I don't think there is
> for generic sharing purposes (if there is a reason, it would also apply to
> the new rule), and there can't be any accessibility problems. So I think it
> is OK to allow S to be declared anywhere in the generic. Thus, we get the
> following (which replaces the existing rule):

Well, you are the only one interested in generic sharing at this point, so if
you say it's fine, I suppose I can live with that.  However, during the meeting
Tuck tried to merge the new rule with the existing one, and we came to the
conclusion that it was not worth the effort.  I am a bit concerned with the
notion that we are relaxing an existing rule just because nobody seems to
remember why it was written that way.

>     If the subprogram denoted by P is declared within a generic unit,
>     and the expression P'Access occurs within the body of that generic
>     unit, or within the body of a generic unit declared within
>     the declarative region of the generic, then the ultimate ancestor
>     of P shall be declared within the generic unit.

With the above caveat, this wording looks good to me.

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

From: Randy Brukardt
Sent: Tuesday, June 5, 2001 4:11 PM

> However, during the meeting
> Tuck tried to merge the new rule with the existing one, and we came to the
> conclusion that it was not worth the effort.

True, but at the meeting, we only considered possible mergings where the
(original) new rule was left in the same order. The other day, I realized
that we needed to reorder the rule to merge them, and I'm certain we didn't
consider that (at least out loud!) at the meeting.

> I am a bit concerned with the notion that we are relaxing an existing rule
> just because nobody seems to remember why it was written that way.

I know this is one rule that I insisted on, and I'm 95% sure I know why the
rule is the way it is. I just don't want to assume I know what was going on
in Tuck's head at the time, so I don't want to write a certainty. Here's why
the existing rule doesn't allow the access to be declared in the spec:

(Skip over the following unless you care about generic sharing approaches)

As you know, a subprogram declared in a shared generic includes a (hidden)
parameter which passes the instance data to the subprogram. In order to be
able to point at subprograms declared in a generic body, an access to
subprogram type declared in a generic body needs the same (hidden)
parameter.

(That makes it clear why the original rule should have said subprogram
declared in a generic, rather than just a subprogram declared in a generic
body.)

Anyway, an access to subprogram type declared in a generic specification may
or may not have the hidden parameter. If it does have the hidden parameter,
then any 'Access of a subprogram not declared in the generic needs a thunk
to remove the hidden parameter on a call through the access value. 'Accesses
from inside of the generic do not need a thunk. If it does not have the
hidden parameter, then any 'Access of a subprogram not declared in the
generic does not need a thunk, while any 'Access of a subprogram declared in
the generic does need a thunk. This latter thunk is impossible to build in
the generic body (because it is shared, and therefore there the only way to
access the instance data is via a hidden parameter: but we just said we
can't have any hidden parameter!). It can be built in the instance at
instantiation time. (Note that access to subprogram types declared outside
of the generic behave like the second case).

The original rule was designed to allow both of these implementations of
access to subprograms in the specs. There doesn't seem to be much reason to
choose either implementation over the other -- the best choice would seem to
depend on how the end user actually uses the type. And this seems rare
enough not to lose sleep over.

Anyway, Janus/Ada chooses the first implementation (always having the hidden
parameter), because it is consistent with other subprograms (and access to
subprogram types) declared in a generic specification or body and thus is
what happens "naturally". If indeed I'm the only one who cares about this,
then there is no reason to restrict this rule further and potentially
inconvenience users. Moreover, if the more restrictive rule is adopted, it
has to apply to subprograms in generic specifications as well. This seems
like too much restriction:

    generic
    package Pack is
        procedure Foo;
        type Acc is access procedure;
    private
        V1 : Acc := Foo'Access; -- OK under any rule.
    end Pack;

    package body Pack is
	  procedure Bar is ...
        procedure Foo is ...

	  V2 : Acc := Bar'Access; -- (2)
        V3 : Acc := Foo'Access; -- (3)
    end Pack;

(2) is illegal by the existing rule. If Acc is represented without a hidden
parameter, this needs to be the case for generic sharing implementation. (3)
would be OK by the Leuven approved wording of the new rule. But that has the
same problem for a generic sharing implementation as (2). Thus, if the
Leuven rule stood, Acc would have to be represented with a hidden parameter.
But if that is the case, there is no need for (2) to be illegal.

Anyway, my point is that both (2) and (3) have to be illegal, or we've
constrained the implementation of Acc in a sharing implementation. Thus,
there is no reason for the two rules to be different: it adds nothing except
complexity. And there is no accessibility reason that they have to be
different. So they ought to be merged.

The 5% uncertainty comes from the fact that Tuck at one point had in mind a
bizarre model where the compiler would generate a thunk for every visible
subprogram in a generic just in case it might be used in a 'Access in the
body. This would allow (2) and (3) to have different legality, but I can't
imagine the value of such a rule or implementation: it would generate a lot
of unused code, adds very little value, and greatly complicates the rule.

> >     If the subprogram denoted by P is declared within a generic unit,
> >     and the expression P'Access occurs within the body of that generic
> >     unit, or within the body of a generic unit declared within
> >     the declarative region of the generic, then the ultimate ancestor
> >     of P shall be declared within the generic unit.
>
> With the above caveat, this wording looks good to me.

Hopefully, I've dispelled the caveat. I assume that you are writing up this
AI, so I'll leave it to you to summarize the above in a handful of pithy
sentences in the !discussion section.

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

From: Gray, Michael
Sent: Tuesday, June 12, 2001 3:15 AM

I'm sorry if I'm being stupid, but I don't see how the wording "the expression
P'Access occurs within the body of that generic unit, or within the body of a
generic unit declared within the declarative region of the generic" covers the
case of P'Access occurring within the body of a generic that takes an
instantiation of the generic (that declares P) as a package parameter.

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

From: Tucker Taft
Sent: Tuesday, June 12, 2001 11:18 AM

I made a typo in my wording, as pointed out by Steve Baird.
What it should say is:

    If the subprogram denoted by P is declared within a generic unit,
    and the expression P'Access occurs within the body of that generic
    unit, or within the body of a generic unit declared within
    the declarative region of the generic, then the ultimate ancestor
    of S shall be declared within the generic unit.

I believe this handles the problem, because if P is
inside a formal package, then it is declared (at least
implicitly) within the enclosing generic unit, because that
includes the formal part of the generic.  We require that S
also be declared within the generic unit, so there is no
danger of the access value outliving the generic.

I think... ;-)

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

From: Randy Brukardt
Sent: Tuesday, June 12, 2001  5:07 PM

Humm, this is letter for letter identical with the previous version. So I don't
see any typo here. Unless you made the same typo a second time.

Your explaination seems like a stretch that ought to be mentioned in the AARM,
as it is less than obvious. But it seems OK to me.

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

Questions? Ask the ACAA Technical Agent