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

Differences between 1.1 and version 1.2
Log of other versions for file ai05s/ai05-0067-1.txt

--- ai05s/ai05-0067-1.txt	2007/10/23 03:22:55	1.1
+++ ai05s/ai05-0067-1.txt	2008/02/05 04:27:59	1.2
@@ -1,4 +1,4 @@
-!standard 7.5(8.1/2)                                         07-10-22    AI05-0067-1/01
+!standard 7.5(8.1/2)                                         08-02-04    AI05-0067-1/02
 !class binding interpretation 07-10-22
 !status work item 07-10-22
 !status received 07-09-03
@@ -104,24 +104,176 @@
 
 !wording
 
-** TBD **
+7.5(8.1/2) is "Implementation Requirements".  Replace that with
+"Dynamic Semantics", as follows:
+
+When a function call or aggregate is used to initialize an object,
+the result of the function call or aggregate is an anonymous object,
+which is assigned into the newly-created object.
+Under certain circumstances, the anonymous object is
+is "built in place", in which case the assignment need not involve
+any copying. In particular:
+
+    - If the type of the newly-created object has a part that is of a task,
+      protected, or explicitly limited record type, the anonymous object is
+      built in place.
+
+    - In the case of an aggregate, if the type of the newly-created object is
+      controlled, the anonymous object is built in place.
+
+    - In other cases, it is implementation dependent whether
+      the anonymous object is built in place.
+
+[Is it time to define "inherently limited" in the RM?  I'd like to replace the
+first two bullets with, "If the type of the newly-created object is inherently
+limited, or has controlled parts, the anonymous object is built in place."
+That's not quite the same thing -- it requires b-i-p in more cases than the
+current RM.]
+
+Notwithstanding what this International Standard says elsewhere,
+if an object is built in place:
+
+    - Upon successful completion of the return statement or aggregate,
+      the anonymous object becomes the newly-created object.
+      This happens atomically with respect to abort and other tasks.
+
+    - Adjustment is not performed on the newly-created object.
+
+    - All access values that designate parts of the anonymous object now
+      designate the corresponding parts of the newly-created object.
+
+    - All renamings of parts of the anonymous object now denote views of the
+      corresponding parts of the newly-created object.
+
+AARM notes:
+
+  The intended implementation is that the anonymous object is allocated at the
+  same address as the newly-created object. Thus, no run-time action is
+  required to cause all the access values and renamings to point to the right
+  place. They just point to the newly-created object, which is what the return
+  object has magically "become".
+
+  There is no requirement that 'Address of the return object is equal to
+  'Address of the newly-created object, but that will be true in this
+  implementation.
+
+  For a function call, if the size of the newly-created object is known at the
+  call site, the object is allocated there, and the address is implicitly
+  passed to the function; the return object is created at that address.
+  Otherwise, a storage pool is implicitly passed to the function; the size is
+  determined at the point of the return statement, and passed to the Allocate
+  procedure. The address returned by the thunk is returned from the function,
+  and the newly-created object uses that same address. If the return statement
+  is left without returning (via an exception or a goto, for example), then
+  Deallocate is called.
+
+  The Tag of the newly-created object may be different from that of the result
+  object. Likewise, the master and accessibility level may be different.
+
+  An alternative implementation model might allow objects to move around to
+  different addresses. In this case, access values and renamings would need to
+  be modified at run time. It seems that this model requires the full power of
+  tracing garbage collection.
+
+7.6(17.1/2) can be removed, but the AARM annotations are still relevant.
+
+7.6(21/2) becomes partly irrelevant.
+
+3.9.1(8.a):  After first sentence, add "It also makes it easier to implement
+extension aggregates in the case where the type is limited, the object is
+allocated from a user-defined storage pool, and the discriminants are
+inherited from the parent type."
+
+???I still think it is unwise to allow premature access to the tag (via 'Tag,
+or via dispatching). I think should raise Program_Error. (Premature means
+before the return statement is done.) Any sympathy for that?
 
 !discussion
 
-For (1), the model is that (logically) there are two objects at the
-same location, and each has the appropriate tag. (Remember that the semantics
-are determined by the canonical semantics: build-in-place is just a permission.)
-Thus T1'Tag is assigned.
-
-However, dispatching in an extended return statement is dubious. (So is dispatching
-in Initialize, for reasons similar to those given in the question.) One could imagine
-trying to detect such dispatching as an error rather than worrying about the answer
-to this question.
+Consider the following example. We have an allocator with a limited heap
+object initialized with an extension aggregate, where the parent part is given
+by a build-in-place function call to Make_T1. The expected implementation
+strategy is to pass T1_Ref'Storage_Pool as an implicit parameter to Make_T1,
+along with the size and alignment of the extension part as determined by
+Comp2. The size of the parent part is determined at the return statement
+in Make_T1. Make_T1 must calculate the size and alignment to allocate
+based on the two sizes and two alignments, and pass that on to the
+storage pool's Allocate procedure. Make_T1 will return the address of
+returned by Allocate, and that will be used at the call site to calculate the
+address of Comp2.
+
+  package P1 is
+     type T1 (D1 : Integer) is tagged limited private;
+     type T1_Ref is access all T1'Class;
+     for T1_Ref'Storage_Pool use ...;
+
+     package Nested_Pkg is
+        function Make_T1 (D1 : Integer) return T1;
+     end Nested_Pkg;
+  private
+     type T1 (D1 : Integer) is tagged limited
+        record
+           Comp1 : String (1..D1);
+        end record;
+  end P1;
 
-For (2), of course R.F2 points to R. But surely that should be said somehow.
+  with P1; use P1;
+  package P2 is
+     type T2 is new T1 with private;
+     function Make return T1_Ref;
+     N : Integer := 7;
+  private
+     type T2 is new T1 with
+        record
+           Comp2 : String (1..N);
+        end record;
+  end P2;
 
-** TBD **
+  package body P1 is
+     package body Nested_Pkg is
+        function Make_T1 (D1 : Integer) return T1 is
+        begin
+           return Result : T1 (D1) do
+              Result.Comp1 := (others => 'x');
+           end return;
+        end Make_T1;
+     end Nested_Pkg;
+  end P1;
+
+  package body P2 is
+     function Make return T1_Ref is
+     begin
+        return Result : T1_Ref := new T2'
+          (Nested_Pkg.Make_T1 (D1 => 5) with Comp2 => "ABCDEFG") do
+           null;
+        end return;
+     end Make;
+  end P2;
+
+  with P1; use P1;
+  with P2; use P2;
+  procedure Main is
+     Ptr : T1_Ref := Make;
+  begin
+     null;
+  end Main;
+
+Note that the size of Comp2 (based on N) need not be known at compile time, but
+it cannot depend on the discriminant. This is fortunate -- otherwise we would
+need to pass a size-calculating thunk to Make_T1.
+
+On the other hand, if T2 had a discriminant part (for example,
+"type T2 (D1, D2 : Integer) is new T1 (D1) with...") then we can calculate the
+size to allocate at the call site. In that case, we would pass the address of
+the parent part to Make_T1, instead of the storage pool and the size/alignment
+information.
+
+The Tag of the return object in Make_T1 is T1'Tag.  The Tag of the return
+object in Make is T2'Tag.  Semantically, we have two separate objects, but in
+implementation terms, this means the Tag will be overwritten in Make, since the
+two objects' Tags are at the same address.
 
+
 --!corrigendum 7.6.1(17.1/1)
 
 !ACATS Test
@@ -795,4 +947,94 @@
 Prim (T2)
 Class_Wide (T0'Class) done
 
+****************************************************************
+
+From: Robert A. Duff
+Sent: Monday, January 4, 2008  1:11 PM
+
+Here's wording for AI05-67. [This is version /02 of the AI - ED.]
+
+[Wording omitted.]
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, January 4, 2008  1:31 PM
+
+I think we use the term "unspecified" rather than
+"implementation dependent" in the RM.
+
+You start talking about a "thunk" in the AARM note
+somewhat out of the blue.  Is there really a need
+for a thunk?  If so, I think you need to explain
+what it does.  I suspect that some implementations
+might prefer to create "pseudo" storage pools
+rather than thunks, though that is hopefully not
+semantically significant.
+
+Overall, the solution you propose seems reasonable.
+It will probably require some rewording in AI-66
+(which I sent around last night).
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Monday, January 4, 2008  6:25 PM
+
+> I think we use the term "unspecified" rather than
+> "implementation dependent" in the RM.
+
+OK.
+
+> You start talking about a "thunk" in the AARM note
+> somewhat out of the blue.  Is there really a need
+> for a thunk?  If so, I think you need to explain
+> what it does.  I suspect that some implementations
+> might prefer to create "pseudo" storage pools
+> rather than thunks, though that is hopefully not
+> semantically significant.
+
+That "thunk" is an editing mistake.  I think I thunk about the GNAT
+implementation details too much ;-), and then eliminated those details, but
+missed that one.  The basic idea is that a storage pool is passed in.  One
+common "storage pool" is the "allocate-on-secondary-stack" storage pool.
+I think this is optimized in the GNAT case by passing various flags that bypass
+the actual pool -- e.g. a flag might say "allocate on secondary stack".
+I don't remember the details of the GNAT implementation, but anyway, the AARM
+doesn't need to talk too much about those optimization details.  Maybe just
+mention the possibility.
+
+There's one more occurrence of the term "thunk", which I really mean.
+
+> Overall, the solution you propose seems reasonable.
+> It will probably require some rewording in AI-66
+> (which I sent around last night).
+
+Right, I noticed that, but didn't say anything.
+
+I'm glad you say "reasonable".  I'm thinking there are two objects, the return
+object and the newly-created object that it turns into.  In my AI writeup, I
+said "becomes", but I wish there were a more evocative word -- "morphs into"
+or "magically transforms itself" or (from the minutes) "poofs"?
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Monday, January 4, 2008  1:11 PM
+****************************************************************
+
+From: Robert A. Duff
+Sent: Monday, January 4, 2008  1:11 PM
+****************************************************************
+
+From: Robert A. Duff
+Sent: Monday, January 4, 2008  1:11 PM
+****************************************************************
+
+From: Robert A. Duff
+Sent: Monday, January 4, 2008  1:11 PM
+****************************************************************
+
+From: Robert A. Duff
+Sent: Monday, January 4, 2008  1:11 PM
 ****************************************************************

Questions? Ask the ACAA Technical Agent