CVS difference for ais/ai-00229.txt

Differences between 1.9 and version 1.10
Log of other versions for file ais/ai-00229.txt

--- ais/ai-00229.txt	2001/09/08 01:42:48	1.9
+++ ais/ai-00229.txt	2001/09/08 03:35:06	1.10
@@ -10,9 +10,9 @@
 
 !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.
+The expression P'Access (where P denotes a subprogram declared in a generic) is
+illegal within a generic body if the ultimate ancestor of the expected access
+type is not declared within the generic unit.
 
 !question
 
@@ -55,7 +55,7 @@
 
 !recommendation
 
-See wording.
+(See wording.)
 
 !wording
 
@@ -77,7 +77,124 @@
 references).
 
 The proposed modification fixes the above dangling reference problem without
-unnecessarily impacting existing code.
+unnecessarily impacting existing code. The new rule has to cover the case of
+children of generics in order to prevent the creation of dangling references in
+children. Consider the following variation of the original example:
+
+package Global is
+    type Ref is access procedure;
+    P : 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;
+end G;
+
+generic
+package G.C is
+    pragma Elaborate_Body;
+end;
+
+with Global;
+package body G.C is
+begin
+    Global.P := Foo'Access; -- Illegal
+end G.C;
+
+with G.C;
+with Global;
+procedure Dangle is
+
+    procedure Bar is
+       package I is new G;
+       package J is new I.C; -- Store a reference to Foo in Global.P.
+    begin
+       null;
+    end Bar;
+
+begin
+    Bar;
+    Global.P.all; -- Oops, I.X is gone?
+end Dangle;
+
+Clearly we want to make this example illegal, too, so the rule has to mention
+the body of any generic declared within the declarative region of G (the
+generic where Foo is declared).
+
+Similarly the rule must catch the case where Foo'Access occurs within the body
+of a generic which takes an instantiation of G as a formal parameter, as in:
+
+generic
+package G is
+    procedure Foo;
+end G;
+
+generic
+    with package I is new G;
+package H is
+    pragma Elaborate_Body;
+end H;
+
+with Global;
+package body H is
+begin
+    Global.P := I.Foo'Access; -- Illegal
+end H;
+
+In this case, I.Foo is declared within I, and I is itself within a generic
+package, namely H. So any occurrence of Foo'Access within H is covered by the
+new rule, and is illegal if the access type Ref is not declared within H.
+
+Finally, there is the case where the ancestor subtype of the access type is a
+generic formal type:
+
+generic
+    type Acc is access procedure;
+package G is
+    A : Acc;
+    procedure Foo;
+end G;
+
+package body G is
+    X : Natural := 0;
+    procedure Foo is ... end Foo;
+begin
+    A := Foo'Access; -- Illegal
+end G;
+
+with G;
+procedure Dangle is
+    type Ref is access procedure;
+    P : Ref;
+
+    procedure Bar is
+        package I is new G(Ref); -- Store a reference to I.Foo in I.A.
+    begin
+        P := I.A;
+    end Bar;
+
+begin
+    Bar;
+    P.all; -- Oops, I.X is gone?
+end Dangle;
+
+Even though the formal type is declared within the generic unit, the actual
+type won't be. So we want to disallow this case. That's why the rule has to
+require that the ultimate ancestor be a non-formal access type.
+
+Note that we don't have the same dangling reference issue with objects, because
+in the case of objects we have a runtime check.
 
 !corrigendum 03.10.02(32)
 

Questions? Ask the ACAA Technical Agent