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

Differences between 1.4 and version 1.5
Log of other versions for file ai05s/ai05-0186-1.txt

--- ai05s/ai05-0186-1.txt	2010/01/28 04:39:09	1.4
+++ ai05s/ai05-0186-1.txt	2010/02/02 04:49:02	1.5
@@ -1,4 +1,4 @@
-!standard 13.3.4 (0)                                10-01-26  AI05-0186-1/03
+!standard 13.3.4 (0)                                10-02-01  AI05-0186-1/04
 !class amendment 09-11-02
 !status work item 09-11-02
 !status received 09-11-02
@@ -66,7 +66,8 @@
     Annotation_List ::= ( Annotation_Item {, Annotation_Item} )
 
     Annotation_Item ::= *object_*name | *access_*subtype_mark |
-                         NULL | OTHERS [IN *package*name] |
+                         NULL | ACCESS subtype_mark |
+                         OTHERS [IN *package*name] |
                          GENERIC *formal_parameter_*name
 
 The names in these items resolve with the same visibility as other aspect
@@ -75,16 +76,17 @@
 
 [Editor's note: We need the keyword GENERIC here, so that we can tell the
 difference between references to the initialization and the referenced data
-for formal access types in annotations. Both use the access type name.
-An alternative would be to add a keyword to the *access_*subtype_mark
-case instead, but nothing that isn't ambiguous seems appropriate. My best
-idea was *access_*subtype_mark.ALL .]
+for formal pool-specific access types in annotations. Both use the access
+type name. An alternative would be to add a keyword to the
+*access_*subtype_mark case instead, but nothing that isn't ambiguous seems
+appropriate. My best idea was *access_*subtype_mark.ALL .]
 
 Aspect_Mark in out => Annotation_List is semantically equivalent to
 Aspect_Mark in => Annotation_List, Aspect_Mark out => Annotation_List.
 
 AARM Discussion: All of the rules are defined in terms of "Aspect_Mark in"
-and "Aspect_Mark out". The rules are applied twice to "Aspect_Mark in out".
+and "Aspect_Mark out". The rules are applied twice (once for "in" and once
+for "out") to "Aspect_Mark in out".
 
 Aspects Global, Global'Class, and Global'Access are defined.
 
@@ -99,12 +101,19 @@
     * The annotation item OTHERS with a package name P occurs in the list, and
       O denotes part of an object declared in P, or O denotes a part of an object
       produced by a dereference of an object of an pool-specific access type whose
-      pool is declared in P; or
+      pool is declared in P;
+    * O denotes a part of an object produced by a dereference of an object with
+      designated type T, and the type D given in an ACCESS D
+      annotation item covers T; or
     * O denotes a part of an object produced by a dereference of an object of
-      an access type named in the Annotation_List.
+      a pool-specific access type named in the Annotation_List.
 
-AARM Ramification: "others" by itself allows anything to be read or written.
+AARM Ramification: OTHERS by itself allows anything to be read or written.
 
+AARM Discussion: ACCESS D represents reading/writing of any aliased or tagged
+object (including those allocated from pools) with a type covered by the
+type D.
+
 "Statically denotes" does not include dereferences, so the first rule only
 applies to statically declared objects.
 
@@ -201,6 +210,9 @@
 An *object*_name given in an Annotation_List shall statically denote some
 object.
 
+An *access*_subtype_mark given in an Annotation_List shall denote a pool-specific
+access type.
+
 A *formal_parameter_*name given in an Annotation_List shall statically denote
 some generic formal parameter of an enclosing generic unit; the formal parameter
 shall be a formal type, a formal subprogram, or a formal IN OUT object.
@@ -229,16 +241,25 @@
     AARM Reason: Allocate and Deallocate can be called here if the implementation
     chooses; we have to assume the worst.
 
-  * The Allocate routine associated with the storage pool for the type of
-    each allocator in the subprogram body shall have a compatible Global in
-    annotation.
+  * The Allocate and Deallocate routines associated with the storage pool for the
+    type of each allocator in the subprogram body shall have compatible Global in
+    annotations.
+
+    AARM Reason: Again, Deallocate can be called here if the implementation chooses;
+    we have to assume the worst.
+
   * For each attribute A'Storage_Size in the subprogram body where A is an access
     type, the Storage_Size routine associated with the storage pool of A shall
     have a compatible Global in annotation.
 
-[I can't find any way to share these rules amongst the various kinds of entities.
-The first rule is slightly different for each kind of thing, depending on the
-accessibility or other rule needed.
+  * If the subprogram contains a call on an instance of Unchecked_Conversion with
+    a pool-specific access type A as the target type, the subprogram is
+    illegal if the type A is named as an *access*_subtype_mark annotation item.
+
+    AARM Reason: We assume that objects of type A can only designate objects in
+    the pool of A. The only way to violate this is to use Unchecked_Conversion
+    from a general access type value; if such a conversion exists, we require
+    the subprogram to be annotated as if A is a general access type.
 
 AARM Ramification: Local objects, elementary constant objects (declared anywhere)
 and the parameters of the call do not need to appear in a Global in annotation.
@@ -247,11 +268,19 @@
 
 A write of a dereference of an object P *reads* the object P (and writes the 
 designated object).
+
+The prefix of a protected function call is considered to be
+read; the prefix of a protected procedure or entry call is considered to be
+both read and written. The prefix of a task entry is considered to be read.
+These rules follow from the requirements in 9.5 on whether or not the
+prefix of a protected subprogram call or an entry call can be a constant;
+we don't want to be logically writing constants.
 End AARM Ramification.
 
 AARM Discussion: We don't need a rule for Deallocate calls in Unchecked_Deallocation,
 as it is a call and does not have annotations defined. Thus the above rule will
 always fail and thus we don't care about the annotations on Deallocate.
+End AARM Discussion.
 
 Analogous rules apply to a Global out annotation (replacing "in" by "out" and
 "read" by "written" everywhere).
@@ -304,6 +333,9 @@
        call in E shall have a compatible Global in annotation; and
      * the Allocate routine associated with the storage pool for the type of
        each allocator in E shall have a compatible Global in annotation.
+     * The Allocate and Deallocate routines associated with the storage pool for the
+       type of each allocator in E shall have compatible Global in
+       annotations.
      * For each attribute A'Storage_Size in E where A is an access type, the
        Storage_Size routine associated with the storage pool of A shall have a
        compatible Global in annotation.
@@ -339,6 +371,8 @@
        call in E shall have a compatible Global in annotation; and
      * the Allocate routine associated with the storage pool for the type of
        each allocator in E shall have a compatible Global in annotation.
+     * The Allocate and Deallocate routines associated with the storage pool for the
+       type of each allocator in E shall have compatible Global in annotations.
      * For each attribute A'Storage_Size in E where A is an access type, the
        Storage_Size routine associated with the storage pool of A shall have a
        compatible Global in annotation.
@@ -382,15 +416,18 @@
 
 For the purposes of enforcing these rules in a generic body, the
 Global annotations on the storage pool operations for formal access types are
-assumed to be (others), the Global annotations on generic formal elementary
+assumed to be (others). The Global annotations on generic formal elementary
 types are assumed to be (null).
 
 [This last paragraph is not talking about inside of instances; rechecking is
 done there with the actual annotations. This is the assume-the-worst rule needed
-in generic bodies. We can assume the latter because no elementary type can
-have a "significant" default initialization; and the actual has to be known
-to be elementary. Note that an elementary type could have some other annotations
-that are explicitly specified; those might be ignored inside of the generic.]
+in generic bodies. We can assume the (null) for formal elementary types because
+no elementary type can have a "significant" default initialization; and the actual
+has to be known to be elementary. Note that an elementary type could have some other
+annotations that are explicitly specified; those might be ignored inside of the
+generic. Other annotations are always assumed to be (others); note that we
+provide another way to annotate formal entities and those are recommended
+in most cases.]
 
 
 Implementation Permissions
@@ -400,7 +437,7 @@
 the implementation may omit the call on such a subprogram and simply reuse the
 results produced by an earlier call on the same subprogram provided:
 * No globals that are indicated as read by the Global in annotation for the
-  subprogram are modified between the eariler call and the omitted call;
+  subprogram are modified between the earlier call and the omitted call;
 * None of the parameters are of a limited type;
 * The addresses and values of all by-reference actual parameters, the values
   of all by-copy-in actual parameters, and the values of all object accessible
@@ -412,8 +449,8 @@
 AARM Discussion: This is intended to be the same rules as applies to calls on
 subprograms defined in declared Pure packages (see 10.2.1). Note that we don't
 need to talk about access values embedded in the parameter objects (as we have to
-for Pure), or about objects access from parameters of named access types, as those
-have to be covered by the global annotations.
+for Pure), or about objects accessed from parameters of named access types, as
+those have to be covered by the Global annotations.
 
 AARM Ramification: The part about indicating that no globals read are modified
 via Global in annotations is trivially true for Global in => (null). This makes
@@ -479,6 +516,14 @@
 be seriously incompatible. User-defined equality operators can have annotations,
 of course.
 
+[Editor's note: We could use a rule more like the one for array components,
+inheriting the annotations from the "=" for the component type, if there is no
+partial view for the type. I didn't do that as the dependence of a partial
+view is a bit weird. Trying to come up with a rule for record types would be
+annoying; it would have to include the union of the "=" for all of the component
+types. Dispatching "=" would still have to use (others) so that future extensions
+would not be restricted.]
+
 Add after 4.5.3:
 
 If C is an elementary type, the predefined concatenation operators have implied
@@ -693,10 +738,10 @@
       -- Creates an element.
 
    function Element (Position : Cursor) return Element_Type with
-      Global in => (others), Global out => (generic Element_Type);
-      -- The dereference of the container can touch anything.
-      -- Even if we had a more specific annotation (perhaps we need
-      -- to add one), this would still prevent many optimizations.
+      Global in  => (access Vector, generic Element_Type),
+      Global out => (generic Element_Type);
+      -- The dereference of the container can touch any Vector object.
+      -- This will prevent many optimizations.
       -- I knew I hated this implicit container semantics, I just
       -- couldn't explain why. Note that the previous routine has
       -- much stronger annotations. Apparently, tools will need to
@@ -713,7 +758,11 @@
    procedure Replace_Element (Container : in out Vector;
                               Position  : in     Cursor;
                               New_item  : in     Element_Type) with
-      Global in => (others), Global out => (generic Element_Type);
+      Global in  => (access Vector, generic Element_Type),
+      Global out => (generic Element_Type);
+      -- The access read is to access the cursor; it has to be
+      -- the same as the Container item or we get an exception,
+      -- but that is beyond the power of these annotations.
 
 ...
 
@@ -858,48 +907,39 @@
 instance).
 
 ---
-
-The objects accessed by an access type are:
 
-For pool-specific types, only the storage pool can be accessed by a dereference.
-For general access types, any aliased or tagged object of the designated type
-(and the storage pool) can be accessed by a dereference. (Recall that any
-tagged parameter, and thus any tagged object can have 'Access taken.)
-
-We allow specifying the name of the access type as an Annotation_Item. This
-provides a convinient way to cover all possible target objects without discussing
-the pool or aliased objects. Tools would have to use rules similar to the above,
-but the the programmer does not need to worry about exactly what is being
-written.
-
-However, if name of the access type is hidden (or no name is available), then
-we have to fall back on OTHERS. But OTHERS is a blunt instrument. For a
-pool-specific type, we can allow just naming the package containing the pool.
-But for a general access type, we can only allow (OTHERS) -- which provides no
-information at all.
-
-An option that was considered was adding a general access Annotation_Item.
-
-     ACCESS subtype_mark
-
-This gives the designated type, and thus would limit references to aliased
-or tagged objects of the appropriate type.
-
-However, we would still need to cover the pool with an appropriate OTHERS.
-And that can't be done cleanly for default pools (especially for anonymous
-access types).
-
-At this point the author gave up and left the problem for all to see.
-
-
-An alternative approach would be to wrap up the entire set of items in
-Global in/out annotations for each access type (that would be disjoint with
-access-to-subprograms use for the same thing). That would include all of the
-Global annotations for the subprograms of the storage pool, an annotation for
-the storage pool object, and ACCESS designated_subtype_mark for general access
-objects. That probably would be easier for tools to use, but harder to write
-and less specific. And it doesn't help the anonymous default pool problem.
-So it doesn't seem to be an improvement, thus we did not use that alternative.
+We allow specifying the name of a pool-specific access type as an Annotation_Item.
+This provides a convinient way to cover all possible target objects without
+discussing the pool. Note that conversions from other access types to a pool-specific
+type are not allowed (other than via Unchecked_Conversion, which we disallow
+explicitly). That means we can treat the pool as local to the package that declares
+the access type, even if the actual pool is allocated somewhere else. This allows
+using OTHERS IN <package_name> for types that are hidden from clients.
+
+We do have to treat such a pool as a global object, even though in many cases
+objects allocated from such hidden access types are not shared and could be considered
+part of other objects. Since we are using static checked, properties that can only
+be verified dynamically effectively require "assume-the-worst" rules. See the
+example of February 1, 2010 found in the !appendix.
+
+For all access types, we provide the ACCESS T annotation item. This item specifies
+any object that could be allocated for a general access type designating T: any
+aliased object of a type covered by T (including those allocated from any pool),
+and, if T is tagged, any object of a type covered by T. (Recall that 'Access can
+always be used on tagged type parameters, so they are effectively aliased for
+this purpose.)
+
+Still, if the name of a designated type is not visible, the only annotation
+available is (OTHERS) (which covers everything).
+
+
+An alternative approach that was considered would be to wrap up the entire set
+of items in Global in/out annotations for each access type (that would be
+disjoint with access-to-subprograms use for the same thing). That would include
+all of the Global annotations for the subprograms of the storage pool, an
+annotation for the storage pool object, and ACCESS designated_subtype_mark for
+general access objects. That doesn't seem to help anything for types that are
+hidden, thus we did not use that alternative.
 
 !example
 
@@ -1584,5 +1624,120 @@
 Steve would like this to preserve the separation of static and dynamic
 semantics. That is the intent - he notes that Pure does not do that. That means
 the wording shouldn't talk about what happens at elaboration.
+
+****************************************************************
+
+Example of access annotations, February 1, 2010, Randy Brukardt
+
+It is often the case that access types hidden in package bodies allocate objects
+that "belong" to particular parameter objects. Verifying this property is
+not possible statically; thus access type annotations have to assume that
+allocated objects are shared amongst top-level objects.
+
+Following is an example of a type that would be problematic without the
+requirement to annotate hidden access types.
+
+package Clones is
+
+    type Clonee is tagged private
+       with Global in out => (others in Clones);
+
+    procedure Create (Obj : in out Clonee; Cnt : Natural; Ave : Float) with
+       Global in out => (others in Clones);
+
+    function Cnt (Obj : in Clonee) return Natural with
+       Global in => (others in Clones), Global out => (null);
+ 
+    function Ave (Obj : in Clonee) return Natural with
+       Global in => (others in Clones), Global out => (null);
+
+    procedure Reset (Obj : in out Clonee; Cnt : Natural; Ave : Float) with
+       Global in out => (others in Clones);
+
+private
+
+    type Data_Type is record
+        Ref_Cnt : Natural := 0;
+        Ave : Float;
+        Cnt : Natural;
+    end record;
+    type Data_Access is access Data;
+
+    type Clonee is tagged record
+        Data : Data_Access;
+    end record;
+
+    procedure Adjust (Obj : in out Clonee) with
+       Global in out => (others in Clones);
+
+    procedure Finalize (Obj : in out Clonee)
+       Global in out => (others in Clones);
+
+end Clones;
+
+
+package body Clones is
+
+    procedure Create (Obj : in out Clonee; Cnt : Natural; Ave : Float) is
+    begin
+        Obj.Data := new Data_Type'(Ref_Cnt => 1, Ave => Ave, Cnt => Cnt);
+    end Create;
+
+    function Cnt (Obj : in Clonee) return Natural is
+    begin
+        return Obj.Data.Cnt;
+    end Cnt;
+ 
+    function Ave (Obj : in Clonee) return Natural is
+    begin
+        return Obj.Data.Ave;
+    end Ave;
+
+    procedure Reset (Obj : in out Clonee; Cnt : Natural; Ave : Float) is
+    begin
+        Obj.Data.Ave := Ave;
+        Obj.Data.Cnt := Cnt;
+    end Reset;
+
+    procedure Adjust (Obj : in out Clonee) is
+    begin
+       Obj.Data.Ref_Cnt := Obj.Data.Ref_Cnt + 1;
+    end Adjust;
+
+    procedure Finalize (Obj : in out Clonee) is
+    begin
+       if Obj.Data /= null then
+          Obj.Data.Ref_Cnt := Obj.Data.Ref_Cnt - 1;
+          if Obj.Data.Ref_Cnt = 0 then
+              Free (Obj.Data);
+          end if;
+       end if;
+    end Finalize;
+
+end Clones;
+
+with Clones;
+procedure Test is
+    A, B : Clones.Clonee;
+begin
+    Clones.Create (A, 10, 1.5);
+    B := A;
+    if Clones.Cnt(B) = 10 then ... -- (1)
+    Clones.Reset (A, 5, 2.5);
+    if Clones.Cnt(B) = 10 then ... -- (2)
+end Test;
+
+Clones.Cnt(B) has the value 10 at (1), and 5 at (2). Since Clones.Cnt
+has a Global out => (null), it is a candidate for the optimization of
+removing the redundant call at (2), most so because the object B
+is the same as before. However, it fails the check that the Global in
+is not modified, so the optimization cannot be performed.
+
+If we allowed the "hidden" access type to be ignored in the annotations,
+this (incorrect) optimization would be allowed. That's no good.
+
+Note that if the Reset operation would have been some call unrelated
+to package Clones, the optimization would have been allowed, as the
+value of B could not have changed (even though it contains "global" data).
 
 ****************************************************************

Questions? Ask the ACAA Technical Agent