7.6 Assignment and Finalization
Three kinds 
of actions are fundamental to the manipulation of objects: initialization, 
finalization, and assignment. Every object is initialized, either explicitly 
or by default, after being created (for example, by an 
object_declaration 
or 
allocator). 
Every object is finalized before being destroyed (for example, by leaving 
a 
subprogram_body 
containing an 
object_declaration, 
or by a call to an instance of Unchecked_Deallocation). An assignment 
operation is used as part of 
assignment_statements, 
explicit initialization, parameter passing, and other operations. 
 
Default definitions for these three fundamental operations 
are provided by the language, but 
a 
controlled 
type gives the user additional control over parts of these operations. 
In particular, 
the user can define, for a controlled type, an Initialize procedure which 
is invoked immediately after the normal default initialization of a controlled 
object, a Finalize procedure which is invoked immediately before finalization 
of any of the components of a controlled object, and an Adjust procedure 
which is invoked as the last step of an assignment to a (nonlimited) 
controlled object. 
 
Static Semantics
The following language-defined 
library package exists: 
package Ada.Finalization 
is
    pragma Pure(Finalization);
 
    type Controlled 
is abstract tagged private;
    
pragma Preelaborable_Initialization(Controlled);
 
    procedure Initialize (Object : 
in out Controlled) 
is null;
    
procedure Adjust     (Object : 
in out Controlled) 
is null;
    
procedure Finalize   (Object : 
in out Controlled) 
is null;
 
    type Limited_Controlled 
is abstract tagged limited private;
    
pragma Preelaborable_Initialization(Limited_Controlled);
 
    procedure Initialize (Object : 
in out Limited_Controlled) 
is null;
    
procedure Finalize   (Object : 
in out Limited_Controlled) 
is null;
private
    ... -- 
not specified by the language
end Ada.Finalization;
 
A controlled type is a descendant 
of Controlled or Limited_Controlled. The predefined "=" operator 
of type Controlled always returns True, since this operator is incorporated 
into the implementation of the predefined equality operator of types 
derived from Controlled, as explained in 
4.5.2. 
The type Limited_Controlled is like Controlled, except that it is limited 
and it lacks the primitive subprogram Adjust. 
 
  A type is said to 
need finalization if:
 
it is a controlled type, a task type or a protected 
type; or
it has a component whose type  needs finalization; 
or
it is a class-wide type; or
it is a partial view whose full view needs finalization; 
or
it is one of a number of language-defined types 
that are explicitly defined to need finalization.
Dynamic Semantics
 During the elaboration or evaluation of a construct 
that causes an object to be initialized by default, for every controlled 
subcomponent of the object that is not assigned an initial value (as 
defined in 
3.3.1), Initialize is called on 
that subcomponent. Similarly, if the object that is initialized by default 
as a whole is controlled, Initialize is called on the object.
 
Initialize and other initialization operations are 
done in an arbitrary order, except as follows.
 Initialize 
is applied to an object after initialization of its subcomponents, if 
any (including both implicit initialization and Initialize calls). If 
an object has a component with an access discriminant constrained by 
a per-object expression, Initialize is applied to this component after 
any components that do not have such discriminants. For an object with 
several components with such a discriminant, Initialize is applied to 
them in order of their 
component_declarations. 
For an 
allocator, 
any task activations follow all calls on Initialize. 
 
When 
a target object with any controlled parts is assigned a value, either 
when created or in a subsequent 
assignment_statement, 
the 
assignment operation proceeds as follows: 
 
The value of the target becomes the assigned value.
The value 
of the target is 
adjusted.  
 To adjust 
the value of a composite object, the values of the components of the 
object are first adjusted in an arbitrary order, and then, if the object 
is nonlimited controlled, Adjust is called.
 Adjusting 
the value of an elementary object has no effect, nor does adjusting the 
value of a composite object with no controlled parts. 
 
For an 
assignment_statement, 
 after the 
name 
and 
expression 
have been evaluated, and any conversion (including constraint checking) 
has been done, an anonymous object is created, and the value is assigned 
into it; that is, the assignment operation is applied. (Assignment includes 
value adjustment.) The target of the 
assignment_statement 
is then finalized. The value of the anonymous object is then assigned 
into the target of the 
assignment_statement. 
Finally, the anonymous object is finalized. As explained below, the implementation 
may eliminate the intermediate anonymous object, so this description 
subsumes the one given in 
5.2, “
Assignment 
Statements”. 
 
   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. 
For such an assignment, the anonymous object might be 
built in place,
 
in which case the assignment does not involve any copying. Under certain 
circumstances, the anonymous object is required to be built in place. 
In particular:
 
If the full type of any part of the object is immutably 
limited, the anonymous object is built in place.
In the case of an 
aggregate, 
if the full type of any part of the newly-created object is controlled, 
the anonymous object is built in place.
 
In other cases, it is unspecified whether the anonymous 
object is built in place.
 
   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 
mutates into the newly-created object; that 
is, the anonymous object ceases to exist, and the newly-created object 
appears in its place.
 
Finalization is not performed on the anonymous 
object.
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.
Coextensions of the anonymous object become coextensions 
of the newly-created object. 
Implementation Permissions
 An implementation is allowed to relax the above 
rules for 
assignment_statements 
in the following ways: 
 
If an object is assigned the value of that same 
object, the implementation need not do anything. 
For assignment of a noncontrolled type, the implementation 
may finalize and assign each component of the variable separately (rather 
than finalizing the entire variable and assigning the entire new value) 
unless a discriminant of the variable is changed by the assignment. 
The implementation need not create an anonymous 
object if the value being assigned is the result of evaluating a 
name 
denoting an object (the source object) whose storage cannot overlap with 
the target. If the source object might overlap with the target object, 
then the implementation can avoid the need for an intermediary anonymous 
object by exercising one of the above permissions and perform the assignment 
one component at a time (for an overlapping array assignment), or not 
at all (for an assignment where the target and the source of the assignment 
are the same object). 
 
 Furthermore, an implementation 
is permitted to omit implicit Initialize, Adjust, and Finalize calls 
and associated assignment operations on an object of a nonlimited controlled 
type provided that:
any omitted Initialize call is not a call on a 
user-defined Initialize procedure, and 
any usage of the value of the object after the 
implicit Initialize or Adjust call and before any subsequent Finalize 
call on the object does not change the external effect of the program, 
and
after the omission of such calls and operations, 
any execution of the program that executes an Initialize or Adjust call 
on an object or initializes an object by an 
aggregate 
will also later execute a Finalize call on the object and will always 
do so prior to assigning a new value to the object, and
 
the assignment operations associated with omitted 
Adjust calls are also omitted. 
 This permission applies to Adjust and Finalize calls 
even if the implicit calls have additional external effects. 
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe