CVS difference for ai05s/ai05-0234-1.txt

Differences between 1.7 and version 1.8
Log of other versions for file ai05s/ai05-0234-1.txt

--- ai05s/ai05-0234-1.txt	2011/03/05 05:38:06	1.7
+++ ai05s/ai05-0234-1.txt	2011/03/10 03:29:56	1.8
@@ -1,4 +1,4 @@
-!standard  6.5(21/3)                               11-02-07    AI05-0234-1/02
+!standard  6.5(21/3)                               11-02-16    AI05-0234-1/03
 !class binding interpretation 10-11-15
 !status work item 10-11-15
 !status received 10-10-31
@@ -238,92 +238,162 @@
 
 !discussion
 
-The language already specifies accessibility checks for access discriminants in
-the case of allocators (to ensure that discriminant values refer do not refer to
-something that is shorter-lived than the access type) and for function results
-(to ensure that discriminant values do not refer to something that is
-shorter-lived than the eventual destination of the function result, as
-determined by the point of call).
-
-In the case where the designated type of an access type is classwide, say
-T'Class, it needs to be made clear that this check is based on the tag of the
-allocated object. A check may be required even if, for example, T is
-undiscriminated.
+This Ai addresses two separate problems.
 
-In the case where a function result type is classwide, a similar check is
-needed. The problem is illustrated by the following two examples:
+1) An issue described in the !question section
+    having to do with runtime accessibility checks
+    for discriminants in cases involving classwide
+    types where the existence of the discriminant
+    is not known statically. This issue is illustrated
+    by the Cw_Alloc and Cw_Return examples in
+    the !example section.
+
+    This turns out to be the smaller part of this AI.
+
+2) The general problem of runtime accessibilty checks for
+    objects whose masters and accessibility levels are not
+    constant. In the cases where a runtime accessibility check
+    is performed to ensure that some entity is at least as long-lived
+    as some object, the check should be performed not against the
+    current accessibility level of the object, but against the
+    accessibility level that the object will (or at least may)
+    eventually end up with. To handle this case, the terms
+    "ultimate master" and "ultimate accessibility level" are
+    defined.
+
+    There were previously no runtime accessibility checks associated
+    with the access discriminant values specified for an aggregate.
+    It might seem that an aggregate cannot possibly refer to anything
+    shorter-lived than itself, so there is no need for any such check.
+    There are, however, ways (described in the AI) that an aggregate's
+    lifetime may be extended, which introduces the need for such a check.
+    This issue is illustrated by the Agg_Check example in the
+    !example section.
+
+    One could view this problem as a consequence of introducing
+    defaulted access discriminants for limited types. This introduces
+    the need to either check aggregates (the approach taken in
+    this version of the AI) or somehow check arbitrarily deeply nested
+    subcomponents at the point of a function return (the approach
+    taken by the previous version of this AI).
+
+    We don't want to repeat checks at the point where an
+    object's accessibility level changes; we want to perform
+    the checks against the correct accessibility level in the
+    first place so that checks are performed while we still have
+    useful info about both of whatever pair of accessibility levels
+    are being compared.
+
+    This means that we have to know the "ultimate
+    accessibility level" of the aggregate result object
+    at the point where the discriminant value is given.
+    It seems that this is implementable using the approach outlined
+    in AI05-0051, but this needs to be confirmed. In particular,
+    we need to look at combinations such as a non-build-in-place
+    function call used to initialize an allocator where the
+    function result owns a coextension, etc.
+
+    Having defined "ultimate master" and "ultimate accessibility level"
+    for use with aggregates, we may as ell use it elsewhere (see the
+    second change to 6.5(21)) even if the only holes that this fixes
+    are related to coextensions (and are therefore less important, at
+    least to some folks).
 
+!example
+
+   with Text_IO;
    procedure Cw_Alloc is
      type Root is tagged null record;
      type Ref is access Root'Class;
+     type Extension (Discrim : access Integer) is
+       new Root with null record;
 
-     type Extension (Discrim : access Integer)
-       is new Root with null record;
-
      function Bad_News return Ref is
-         Local_Int : aliased Integer := 123;
-         Local_Ext : aliased Extension (Discrim => Local_Int'Access);
-         type Local_Ref is access all Root'Class;
-         for Local_Ref'Storage_Size use 0;
-         Local_Ptr : Local_Ref :=  Local_Ext'Access;
+       Local_Int : aliased Integer := 123;
+       Local_Ext : aliased Extension (Discrim => Local_Int'access);
+       type Local_Ref is access all Root'Class;
+       for Local_Ref'Storage_Size use 0;
+       Local_Ptr : Local_Ref := Local_Ext'access;
      begin
-         return new Root'Class'(Local_Ptr.all);
-         -- fails accessibility check? (yes)
+       return new Root'Class'(Local_Ptr.all);
+       -- allocator should fail, but RM 4.8(10) doesn't capture this
+       -- correctly (with or without the changes of AI05-0051)
      end Bad_News;
 
      Ptr : Ref := Bad_News;
+     procedure Do_Nothing is
+     begin
+       null;
+     end Do_Nothing;
    begin
-     -- If we reach this point, Ptr.Discrim is a dangling reference
-     ...
+     Text_IO.Put_Line
+       ("*** Test failed - an exception should have been raised");
+     Text_IO.Put_Line
+       (" Ptr.Discrim.all =" &
+        Integer'Image (Extension (Ptr.all).Discrim.all));
+     Do_Nothing;
+     Text_IO.Put_Line
+       (" Ptr.Discrim.all =" &
+        Integer'Image (Extension (Ptr.all).Discrim.all));
    end Cw_Alloc;
 
+
+   with Text_IO;
    procedure Cw_Return is
      type Root is tagged null record;
-     type Extension (Discrim : access Integer)
-       is new Root with null record;
-
+     type Extension (Discrim : access Integer) is
+       new Root with null record;
      function Bad_News return Root'Class is
-         Local_Int : aliased Integer := 123;
-         Local_Ext : aliased Extension (Discrim => Local_Int'Access);
-         type Local_Ref is access all Root'Class;
-         for Local_Ref'Storage_Size use 0;
-         Local_Ptr : Local_Ref :=  Local_Ext'Access;
+       Local_Int : aliased Integer := 123;
+       Local_Ext : aliased Extension (Discrim => Local_Int'access);
+       type Local_Ref is access all Root'Class;
+       for Local_Ref'Storage_Size use 0;
+       Local_Ptr : Local_Ref := Local_Ext'access;
      begin
          return Local_Ptr.all;
-         -- fails accessibility check? (yes)
+         -- return should fail, but RM 6.5(21) doesn't capture this
+         -- correctly (with or without the changes of AI05-0051)
      end Bad_News;
-
      Obj : Root'Class := Bad_News;
-
    begin
-     -- If we reach this point, Obj.Discrim is a dangling reference
-     ...
+     Text_IO.Put_Line
+       ("*** Test failed - an exception should have been raised");
+     Text_IO.Put_Line
+       (" Obj.Discrim.all =" &
+        Integer'Image (Extension (Obj).Discrim.all));
    end Cw_Return;
 
-In addition, these checks also need to be generalized to handle the case of a
-subcomponent which has defaulted access discriminant values, as in
-
-    X : aliased Integer;
-
-    type Subcomponent_Type (Discrim : access Integer := X'Access)
-      is limited null record;
-
-    type Component_Type is record S : Subcomponent_Type; end record;
 
-    type Undiscriminated is record
-      Fld : Component_Type;
-    end record;
+   procedure Agg_Check is
+     type Subcomponent_Type (Discrim : access Integer := null)
+       is limited null record;
+     type Component_Type is
+       record
+         S : Subcomponent_Type;
+       end record;
+     type Rec is
+       record
+         Fld : Component_Type;
+       end record;
+     type Ref1 is access Rec;
+     Ptr1 : Ref1;
+
+     procedure Nested is
+       type Ref2 is access Rec;
+       Ptr2 : Ref2;
+
+       Local : aliased Integer;
+
+       function F return Rec is
+       begin
+         return (Fld => (S => (Discrim => Local'access)));
+       end F;
 
-    function F return Undiscriminated is
-        Local : aliaed Integer;
-    begin
-        return X : Untagged
-          := (Fld => (S => (Discrim => Local'Access))) do
-
-          Foo;
-        end return;
-        -- raises Program_Error after calling Foo.
-    end F;
+       Ptr2 := new Rec'(F); -- ok
+       Ptr1 := new Rec'(F); -- fails accessibility check
+   begin
+     Nested;
+   end Agg_Check;
 
 !ACATS Test
 
@@ -2118,3 +2188,18 @@
 check]. Enjoy. :-)
 
 ****************************************************************
+
+From: Steve Baird
+Sent: Wednesday, February 16, 2011  2:51 PM
+
+> Steve Baird:
+>     * AI05-0234-1 Add missing wording, consider class-wide coextension 
+> cases. [Need !discussion
+
+Here is a !discussion and !example section for AI05-0234 The Agg_Check example
+is new; the other two examples are taken from the previous version of the AI.
+
+[Editor's note: This is version /03 of the AI.]
+
+****************************************************************
+

Questions? Ask the ACAA Technical Agent