CVS difference for ai05s/ai05-0142-4.txt

Differences between 1.3 and version 1.4
Log of other versions for file ai05s/ai05-0142-4.txt

--- ai05s/ai05-0142-4.txt	2009/05/23 06:34:03	1.3
+++ ai05s/ai05-0142-4.txt	2009/06/26 01:49:35	1.4
@@ -1,4 +1,13 @@
-!standard 3.10(9/2)                                  09-05-22  AI05-0142-4/03
+!standard 3.10(9/2)                                  09-06-25  AI05-0142-4/04
+!standard 3.10.2(13.1/2)
+!standard 6.1(15/2)
+!standard 6.1(23)
+!standard 6.2(3)
+!standard 6.2(10)
+!standard 6.3.1(16/2)
+!standard 6.4.1(6)
+!standard 6.4.1(15)
+!standard 7.6.1(13/3)
 !class Amendment 09-05-17
 !status work item 09-05-17
 !status received 09-05-17
@@ -49,23 +58,19 @@
 parameter_specification, } or component_definition with the reserved word *aliased*, or
 by renaming an aliased view.
 
-Add somewhere in 3.10.2(6-16): [Q: Where??]
+Add after 3.10.2(13.1/2):
 
-The accessibility level of an explicitly aliased formal parameter in a function body
-is the level that the return object will have after a return statement completes
-normally.
+The accessibility level of an explicitly aliased (see 6.1) formal parameter in a function
+body is determined by the point of call (which is the same level that the return object
+ultimately will have).
 
 [That level is defined by 3.10.2(10.1/2).].
 
 [The intent is that this level is such that the checks defined in 6.5 for return
 statements will always succeed (or fail) without any need for any runtime
-checks and associated overhead. (See the Language Design Principles below.) But this depends on what
-we end up doing for AI-51; this works best with the fully dynamic version of that
-AI. If we use Bob's version, then we will have to make a hole in the rules to
-allow this scenario. One way to do that would be use immutably limited results
-only, in that case, the other rules given above would be changed similarly.
-Another option would be a syntax marker on the return that we want a shorter
-lifetime for the result. - RLB]
+checks and associated overhead. (See the Language Design Principles below.) This depends
+on the proposed solution for AI-51; the return object then will have the correct
+level. - RLB]
 
 
 Replace 6.1(15/2) by:
@@ -79,6 +84,12 @@
 An *explicitly aliased parameter* is a formal parameter whose parameter_specification includes
 the reserved word *aliased*.
 
+Modify 6.2(3):
+
+A type is a *by-copy* type if it is an elementary type, or if it is a descendant of a private
+type whose full type is a by-copy type. A parameter of a by-copy type
+{that is not explicitly aliased} is passed by copy.
+
 Modify 6.2(10):
 
 A parameter of a by-reference type is passed by reference{, as is an explicitly aliased parameter
@@ -95,7 +106,7 @@
 
 Language Design Principles
 For explictly aliased parameters of functions, we will ensure at the call site that a part
-of it can be returned as+ part of the function result without creating a dangling pointer.
+of it can be returned as part of the function result without creating a dangling pointer.
 We do this with accessibility checks at the call site that all actual objects
 of explicitly aliased parameters live as long as the function result; then we can allow them
 to be returned as access discriminants or anonymous access results, as those have the
@@ -194,82 +205,90 @@
 
 (Note: The following requires AI05-0143-1 to be approved.)
 Add the following to each Ada.Containers package immediately after
-Update_Element (with suitable substitutions for the names of types) [note that
-the names of the type, discriminant, and function are TBD].
+Update_Element (with suitable substitutions for the names of types).
+
+    type Constant_Reference_Type (Element : not null access constant Element_Type) is
+        tagged limited private;
 
-    type Accessor_Type (Element : not null access Element_Type) is
+    type Reference_Type (Element : not null access Element_Type) is
         tagged limited private;
 
 [Bob recommends just using "E" for the name of the discriminant.]
 
-Accessor_Type needs finalization.
+Constant_Reference_Type and Reference_Type need finalization.
 
-A default-initialized object of type Accessor_Type propagates Program_Error.
+The default initialization of an object of type Constant_Reference_Type or Reference_Type
+propagates Program_Error.
 
-AARM Reason: It is expected that Accessor_Type will be a controlled
-type, for which finalization will have some action to terminate the tampering
-check for the associated container. If the object is created by default,
+AARM Reason: It is expected that Reference_Type (and Constant_Reference_Type)
+will be a controlled type, for which finalization will have some action to terminate
+the tampering check for the associated container. If the object is created by default,
 however, there is no associated container. Since this is useless, and supporting
 this case would take extra work, we define it to raise an exception.
 
+
+    function Constant_Reference (Container : aliased in Vector; Position : in Cursor)
+       return Constant_Reference_Type;
+
+If Position equals No_Element, then Constraint_Error is propagated; if Position
+does not designate an element in Container, then Program_Error is propagated.
+Otherwise, Constant_Reference returns an object whose discriminant is an access
+value that designates the element designated by Position. Program_Error is propagated
+if any operation tampers with the elements of Container while the object returned
+by Constant_Reference exists and has not been finalized.
 
-    function Accessor (Container : aliased in out Vector; Position : in Cursor)
-       return Accessor_Type;
+    function Reference (Container : aliased in out Vector; Position : in Cursor)
+       return Reference_Type;
 
 If Position equals No_Element, then Constraint_Error is propagated; if Position
 does not designate an element in Container, then Program_Error is propagated.
-Otherwise, Accessor returns an object whose discriminant is an access that
-designates the element designated by Position. Program_Error is propagated if
+Otherwise, Reference returns an object whose discriminant is an access value
+that designates the element designated by Position. Program_Error is propagated if
 any operation tampers with the elements of Container while the object returned
-by Accessor exists and has not been finalized.
+by Reference exists and has not been finalized.
 
 The element designated by Position is not an empty element after successful
 completion of this operation. [This is only needed for the Vectors case. - ED]
 
 Add the following to Ada.Containers.Vectors and its relatives.
 
-    function Accessor (Container : aliased in out Vector; Index : in Index_Type)
-       return Accessor_Type;
+    function Constant_Reference (Container : aliased in Vector; Index : in Index_Type)
+       return Reference_Type;
 
 If Index is not in the range First_Index (Container) .. Last_Index (Container),
-then Constraint_Error is propagated. Otherwise,
+then Constraint_Error is propagated. Otherwise, Constant_Reference returns an object
+whose discriminant is an access value that designates the element at position Index.
+Program_Error is propagated if any operation tampers with the elements of Container
+while the object returned by Constant_Reference exists and has not been finalized.
 
-Accessor returns an object whose discriminant is an access that designates the
-element at position Index. Program_Error is propagated if any operation tampers
-with the elements of Container while the object returned by Accessor exists and
-has not been finalized.
+    function Reference (Container : aliased in out Vector; Index : in Index_Type)
+       return Reference_Type;
 
+If Index is not in the range First_Index (Container) .. Last_Index (Container),
+then Constraint_Error is propagated. Otherwise, Reference returns an object whose
+discriminant is an access value that designates the element at position Index.
+Program_Error is propagated if any operation tampers with the elements of Container
+while the object returned by Reference exists and has not been finalized.
+
 The element designated by Position is not an empty element after successful
 completion of this operation.
 
 Add the following to the Erroneous Execution section of each container package:
 
 Execution is erroneous if the vector associated with the result of a call to
-Accessor is finalized before the result object returned by Accessor is
-finalized.
+Reference or Constant_Reference is finalized before the result object returned
+by the call to Reference or Constant_Reference is finalized.
 
-AARM Reason: Each object of Accessor_Type probably contains some reference to
-the originating container. If that container is prematurely finalized (only
-possible via Unchecked_Deallocation, as accessibility checks prevent passing a
-container to Accessor that will not live as long as the result), the
-finalization of the object of Accessor_Type will try to access a non-existent
+AARM Reason: Each object of Reference_Type and Constant_Reference_Type probably
+contains some reference to the originating container. If that container is prematurely
+finalized (which is only possible via Unchecked_Deallocation, as accessibility checks
+prevent passing a container to Reference that will not live as long as the result), the
+finalization of the object of Reference_Type will try to access a non-existent
 object. This is a normal case of a dangling pointer created by
 Unchecked_Deallocation; we have to explicitly mention it here as the pointer in
 question is not visible in the specification of the type. (This is the same
 reason we have to say this for invalid cursors.)
 
-[Q: Should we add the read-only accessors? They would look like:
-
-    type RO_Accessor_Type (Element : not null access constant Element_Type) is
-       tagged limited private;
-
-    function RO_Accessor (Position : aliased in Cursor) return RO_Accessor_Type;
-
-    function RO_Accessor (Container : aliased in Vector; Index : in Index_Type)
-       return RO_Accessor_Type;
-
-The names of all of these functions need work.]
-
 !discussion
 
 The idea is that the accessibility level of explicitly aliased parameters of functions is defined
@@ -286,21 +305,22 @@
 
 ---
 
-Note that the accessibility of the returned object from a call to Accessor will prevent converting
+Note that the accessibility of the returned object from a call to Reference will prevent converting
 the returned access discriminant to any type that lives longer than the returned object. That means
-that we can assume that the discriminant value cannot be accessed after the object disappears.
+that we can assume that the discriminant value cannot be accessed after the object disappears (thus
+we can tie the tampering check to the lifetime of the returned object).
 
-It is possible to use Unchecked_Deallocation to destroy the returned Accessor_Type object
+It is possible to use Unchecked_Deallocation to destroy the returned Reference_Type object
 prematurely, while continuing to use the returned access. The accessibility check on the container
-argument to the Accessor function means that the returned access can't live longer than the
+argument to the Reference function means that the returned access can't live longer than the
 container, but the use of Unchecked_Deallocation would allow tampering on the container. This could
 look like:
 
    declare
-      type AT is access MV.Accessor_Type;
-      procedure Free is new Ada.Unchecked_Deallocation (MV.Accessor_Type, AT);
+      type AT is access MV.Reference_Type;
+      procedure Free is new Ada.Unchecked_Deallocation (MV.Reference_Type, AT);
 
-      PAT : AT := new MV.Accessor_Type'(Vect.Accessor (1))
+      PAT : AT := new MV.Reference_Type'(Vect.Reference (1))
 
       Element : access Element_Type := PAT.Element; -- OK.
 
@@ -308,7 +328,7 @@
       Free (PAT); -- Tampering checking ends here!
 
       Vect.Delete (1); -- No check here.
-      ... Element ... -- Oops, gone.
+      ... Element.all ... -- Oops, gone.
    end;
 
 Obviously, this is highly unlikely to happen by accident. This is more like shooting oneself in
@@ -537,7 +557,7 @@
 
 Assume that Ada.Containers.Vectors has an accessor function defined as follows:
 
-function Accessor (C : aliased in out Vector; I : Index_Type) return access Element_Type;
+function Reference (C : aliased in out Vector; I : Index_Type) return access Element_Type;
 
 Now consider the following program fragments:
 
@@ -601,7 +621,7 @@
       Data.Node_List.Append (New_Item => (D => True, CT => 4)); -- Element 2.
       Data.Node_List.Append (New_Item => (D => False, CF => 26.5)); -- Element 3.
       ...
-      Process.Process_True (Data.Node_List.Accessor (2).all);
+      Process.Process_True (Data.Node_List.Reference (2).all);
       ...
   end Main;
 
@@ -632,7 +652,7 @@
 
 !examples
 
-The new Accessor function could be used (based on a recent example from
+The new Reference function could be used (based on a recent example from
 comp.lang.ada):
 
    with Ada.Containers.Vectors;
@@ -653,47 +673,48 @@
    begin
       IV.Append(42);
       NV.Append(IV);
-      NV.Accessor(0).Element.Append(43);
+      NV.Reference(0).Element.Append(43);
    end Check;
 
 The dereference does not need to be explicitly given in this case, and the fact
-that the object returned by Accessor is limited and (probably) controlled is not
-visible in the code.
+that the object returned by Reference is limited and (probably) controlled is not
+visible in the code as the function call is used directly as a prefix.
 
 You could also save the entire object as long as needed:
 
    declare
-      My_IV : Nested_Vectors.Accessor_Type := NV.Accessor(0);
+      My_IV : Nested_Vectors.Reference_Type := NV.Reference(0);
    begin
 
 (since My_NV would be built-in-place).
 
 Note that this design still works as intended even if the user renames only the
-limited access value:
+discriminant access value:
 
    declare
-      My_IV : Integer_Vectors.Vector renames NV.Accessor(0).Element.all;
+      My_IV : Integer_Vectors.Vector renames NV.Reference(0).Element.all;
    begin
 
-Even in this case, the wrapping finalizable object still is protecting the
+Even in this case, the wrapping (probably controlled) object still is protecting the
 container, because the master of the returned object is the master of the
 renames: it will stick around as long as the renames does.
 
 Moreover, splitting the access from the object usually isn't possible:
 
    declare
-      My_IV : access Integer_Vectors.Vector := NV.Accessor(0).Element; -- Illegal!
+      My_IV : access Integer_Vectors.Vector := NV.Reference(0).Element; -- Illegal!
    begin
 
 This is illegal because the accessibility check fails. The (anonymous) object
-returned here will have the master of the expression, which is shorter than the
-master of the declaration of My_IV. Thus the accessibility check preventing
+returned here will have the master of the expression (as a prefix, the special
+"directly initializing" rule does not apply to this function call), which is shorter
+than the master of the declaration of My_IV. Thus the accessibility check preventing
 shorter lifetimes will fail.
 
 It is OK to rename the access:
 
    declare
-      My_IV : access Integer_Vectors.Vector renames NV.Accessor(0).Element;
+      My_IV : access Integer_Vectors.Vector renames NV.Reference(0).Element;
    begin
 
 as in this case, the anonymous object will continue to exist until the renames
@@ -702,11 +723,11 @@
 This element can be passed as a parameter, as again the wrapping object will
 live as long as the parameter:
 
-    Operate (NV.Accessor(0).Element);
+    Operate (NV.Reference(0).Element);
 
 or
 
-    Munge (NV.Accessor(0).Element.all);
+    Munge (NV.Reference(0).Element.all);
 
 
 !ACATS test

Questions? Ask the ACAA Technical Agent