Version 1.3 of ais/ai-00229.txt

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

!standard 3.10.2 (32)          01-05-04 AI95-00229/01
!class binding interpretation 00-04-10
!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 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 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.

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

Questions? Ask the ACAA Technical Agent