CVS difference for 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