Version 1.5 of ais/ai-00083.txt

Unformatted version of ais/ai-00083.txt version 1.5
Other versions for file ais/ai-00083.txt

!standard 07.06 (21)          99-10-07 AI95-00083/04
!standard 07.06.01 (20)
!class binding interpretation 95-07-27
!status Corrigendum 2000 99-07-28
!status WG9 approved 95-06-14
!status work item (letter ballot was 10-1-0) 96-06-05
!status ARG approved (subject to letter ballot) 7-0-3 95-11-01
!status received 95-07-27
!qualifier Clarification
!subject Aggregates of a controlled type
!summary
When an object of a controlled type is created and explicitly initialized with an aggregate, the aggregate is built "in place"; Finalize and Adjust are not called on the object as a whole.
!question
If an object of a controlled type is declared in the same package as the type, and initialized with an aggregate, is Program_Error raised? (No.)
!recommendation
When an object of a controlled type is created and explicitly initialized with an aggregate, the implementation must not create a separate anonymous object for the aggregate; it must create the value of the aggregate directly in the newly-created object. Thus, there is no assignment from the anonymous object to the newly-created object, so the Finalize and Adjust that would be done for that assignment are not done.
!wording
(See corrigendum.)
!discussion
Consider the following controlled type:
type Dyn_String is private; Null_String : constant Dyn_String;
... private
type Dyn_String is new Ada.Finalization.Controlled with record ... end record; procedure Finalize(X : in out Dyn_String); procedure Adjust(X : in out Dyn_String);
Null_String : constant Dyn_String := (Ada.Finalization.Controlled with ...);
Clearly, at the time when the full constant declaration for Null_String is elaborated, the bodies for Finalize and Adjust have not yet been elaborated. RM 7.6(21) gives the permission to build the aggregate directly in the target object, thereby eliminating the need for the assignment (and the associated calls on Adjust/Finalize):
21 For an aggregate or function call whose value is assigned into a
target object, the implementation need not create a separate anonymous object if it can safely create the value of the aggregate or function call directly in the target object.
However, it seems important to require this behavior, so that this kind of programming is portable (that is, it will portably work without raising Program_Error due to an access-before-elaboration from calling Adjust or Finalize before their bodies are elaborated).
In other words, the first sentence of 7.6(21) should be an Implementation Requirement in the case where a new object is being created.
Note that no Adjust ever takes place on an aggregate as a whole, since there is no assignment to the aggregate as a whole (AARM 4.3(5,5b)). AARM 7.6(21a) talks about this case, and says that "only one value adjustment is necessary". This is misleading. It should say that only one adjustment of each controlled subcomponent (if any) is necessary in this case. No adjustments of the object as a whole are necessary (and as suggested above, such adjustments should be disallowed).
Note that this interpretation applies to all object creations, not just to object_declarations. Thus, continuing the above example, if we have:
type Dyn_String_Ptr is access all Dyn_String; Null_String_Ptr: Dyn_String_Ptr := new Dyn_String'(Ada.Finalization.Controlled with ...);
The aggregate must be built directly in the newly-created heap object.
!corrigendum 7.06.01(20)
Insert after the paragraph:
the new paragraph:
Implementation Requirements

For an aggregate of a controlled type whose value is assigned, other than assignment_statement or return_statement, the implementation shall not create a separate anonymous object for the aggregate. The aggregate value shall be constructed directly in the target of the assignment operation, and Adjust is not called on the target object.
!ACATS test
ACATS test C761010 was constructed to test this rule. The annex H ACATS test CXH3002 also requires these semantics.
!appendix

!section 7.6(21)
!subject Aggregates of a controlled type
!reference RM95-7.6(21)
!reference AARM-7.6(21.a);6.0
!from Tucker Taft 95-07-25
!reference as: 95-5234.a Tucker Taft 95-7-25>>
!discussion

Consider the following controlled type:

    type Dyn_String is private;
    Null_String : constant Dyn_String;
 ...
 private
    type Dyn_String is new Ada.Finalization.Controlled
      with record
        ...
      end record;
    procedure Finalize(X : in out Dyn_String);
    procedure Adjust(X : in out Dyn_String);

    Null_String : constant Dyn_String :=
      (Ada.Finalization.Controlled with ...);

Clearly, at the time when the full constant declaration for
Null_String is elaborated, the bodies for Finalize and Adjust have
not yet been elaborated.  RM 7.6(21) gives the permission to
build the aggregate directly in the target object, thereby
eliminating the need for the assignment (and the associated calls on
Adjust/Finalize).   However, it seems important to *require*
this behavior, so that this kind of programming is portable
(that is, it will portably work without raising Program_Error due
to an access-before-elaboration from calling Adjust or Finalize
before their bodies are elaborated).

In other words, at least parts of 7.6(21) should be moved to
an Implementation Requirement (or the Dynamic Semantics).
In particular, when a constant is initialized from an aggregate
of a controlled type, the aggregate should be built in place,
and no Adjust or Finalize on the constant object as a whole
should take place.  Note that no Adjust ever takes place
on an aggregate as a whole, since there is no assignment
to the aggregate as a whole (AARM 4.3(5,5b)).

Note that AARM 7.6(21a) talks about this case, and says that
"only one value adjustment is necessary".  This is misleading.
It should say that only one adjustment of each controlled *subcomponent*
(if any) is necessary in this case.  *No* adjustments of the object as
a whole are necessary (and as suggested above, such adjustments
should be disallowed).

-Tuck

****************************************************************

From: Randy Brukardt
Sent: October 7, 1999

At the recent ARG meeting, discussion centered around insuring that all
places where an extension aggregate can be used are explicitly covered
by the wording for this AI. (This discussion subsumes AI-00197, which now
will be deleted and merged into this one).

The meeting enumerated the places where an extension aggregate can be used:

Assignment, return statement, generic IN parameter, formal parameter,
allocator, initial expression, and subaggregate.

The meeting then discussed for each place whether or not this rule should
apply. Eventually, it was decided it should apply to all cases except
assignment and return statements. While return statements probably could be
implemented without a temporary for the aggregate, there did not seem to
be any compelling reason to burden implementations with such a requirement.

New wording was crafted to insure that all of the cases are covered.
Note that all aggregates of a controlled type are extension aggregates:
Controlled itself is private, so it is not possible to create a normal
aggregate for such a type.

****************************************************************

Questions? Ask the ACAA Technical Agent