13.14 Freezing Rules
1
[This clause defines a place in the program text
where each declared entity becomes “frozen.” A use of an
entity, such as a reference to it by name, or (for a type) an expression
of the type, causes freezing of the entity in some contexts, as described
below. The Legality Rules forbid certain kinds of uses of an entity in
the region of text where it is frozen.]
1.a
Reason: This concept has two purposes:
a compile-time one and a run-time one.
1.b
The compile-time purpose of the freezing rules
comes from the fact that the evaluation of static expressions depends
on overload resolution, and overload resolution sometimes depends on
the value of a static expression. (The dependence of static evaluation
upon overload resolution is obvious. The dependence in the other direction
is more subtle. There are three rules that require static expressions
in contexts that can appear in declarative places: The expression in
an
attribute_designator
shall be static. In a record aggregate, variant-controlling discriminants
shall be static. In an array aggregate with more than one named association,
the choices shall be static. The compiler needs to know the value of
these expressions in order to perform overload resolution and legality
checking.) We wish to allow a compiler to evaluate static expressions
when it sees them in a single pass over the
compilation_unit.
The freezing rules ensure that.
1.c
The run-time purpose of the freezing rules is
called the “linear elaboration model.” This means that declarations
are elaborated in the order in which they appear in the program text,
and later elaborations can depend on the results of earlier ones. The
elaboration of the declarations of certain entities requires run-time
information about the implementation details of other entities. The freezing
rules ensure that this information has been calculated by the time it
is used. For example, suppose the initial value of a constant is the
result of a function call that takes a parameter of type T. In
order to pass that parameter, the size of type T has to be known.
If T is composite, that size might be known only at run time.
1.d
(Note that in these discussions, words like
“before” and “after” generally refer to places
in the program text, as opposed to times at run time.)
1.e
Discussion:
The “implementation details” we're talking about above
are:
1.f
For a tagged type, the implementations of
all the primitive subprograms of the type — that is (in the canonical
implementation model), the contents of the type descriptor, which contains
pointers to the code for each primitive subprogram.
1.g
For a type, the full type declaration of any
parts (including the type itself) that are private.
1.h
For a deferred constant, the full constant
declaration, which gives the constant's value. (Since this information
necessarily comes after the constant's type and subtype are fully known,
there's no need to worry about its type or subtype.)
1.i
For any entity, representation information
specified by the user via representation items. Most representation items
are for types or subtypes; however, various other kinds of entities,
such as objects and subprograms, are possible.
1.j/3
{
AI05-0005-1}
Similar issues arise for incomplete types. However, we do not use freezing
to prevent premature access there;
incomplete types have different, more severe, restrictions. Similar issues
also arise for subprograms, protected operations, tasks and generic units.
However, we do not use freezing
to prevent premature
access for those, there either;
3.11
prevents problems with run-time Elaboration_Checks.
Even so, freezing is used for these entities to prevent giving representation
items too late (that is, after uses that require representation information,
such as calls).
Language Design Principles
1.k
An evaluable construct should freeze anything
that's needed to evaluate it.
1.l
1.m
The compiler should be allowed to evaluate static
expressions without knowledge of their context. (I.e. there should not
be any special rules for static expressions that happen to occur in a
context that requires a static expression.)
1.n
Compilers should be allowed to evaluate static
expressions (and record the results) using the run-time representation
of the type. For example, suppose Color'Pos(Red) = 1, but the internal
code for Red is 37. If the value of a static expression is Red, some
compilers might store 1 in their symbol table, and other compilers might
store 37. Either compiler design should be feasible.
1.o
Compilers should never be required to detect
erroneousness or exceptions at compile time (although it's very nice
if they do). This implies that we should not require code-generation
for a nonstatic expression of type T too early, even if we can
prove that that expression will be erroneous, or will raise an exception.
1.p
Here's an example
(modified from AI83-00039, Example 3):
1.q
type T is
record
...
end record;
function F return T;
function G(X : T) return Boolean;
Y : Boolean := G(F); -- doesn't force T in Ada 83
for T use
record
...
end record;
1.r
AI83-00039 says
this is legal. Of course, it raises Program_Error because the function
bodies aren't elaborated yet. A one-pass compiler has to generate code
for an expression of type T before it knows the representation of T.
Here's a similar example, which AI83-00039 also says is legal:
1.s
package P is
type T is private;
function F return T;
function G(X : T) return Boolean;
Y : Boolean := G(F); -- doesn't force T in Ada 83
private
type T is
record
...
end record;
end P;
1.t
If T's size were dynamic, that size would be
stored in some compiler-generated dope; this dope would be initialized
at the place of the full type declaration. However, the generated code
for the function calls would most likely allocate a temp of the size
specified by the dope before checking for Program_Error. That
dope would contain uninitialized junk, resulting in disaster. To avoid
doing that, the compiler would have to determine, at compile time, that
the expression will raise Program_Error.
1.u
This is silly. If we're going to require compilers
to detect the exception at compile time, we might as well formulate the
rule as a legality rule.
1.v
Compilers should not be required to generate
code to load the value of a variable before the address of the variable
has been determined.
1.w
After an entity has been frozen, no further
requirements may be placed on its representation (such as by a representation
item or a
full_type_declaration).
2
The
freezing
of an entity occurs at one or more places (
freezing points) in
the program text where the representation for the entity has to be fully
determined. Each entity is frozen from its first freezing point to the
end of the program text (given the ordering of compilation units defined
in
10.1.4).
2.a
Ramification: The “representation”
for a subprogram includes its calling convention and means for referencing
the subprogram body, either a “link-name” or specified address.
It does not include the code for the subprogram body itself, nor its
address if a link-name is used to reference the body.
2.1/3
{
AI05-0019-1}
This clause also defines a
place in the program text where the profile of each declared callable
entity becomes frozen. A use of a callable entity causes freezing
of its profile in some contexts, as described below. At the place where
the profile of a callable entity becomes frozen, the entity itself becomes
frozen.
3/3
{
8652/0014}
{
AI05-0017-1}
{
AI05-0019-1}
The end of a
declarative_part,
protected_body,
or a declaration of a library package or generic library package, causes
freezing of each entity
and profile declared
within it, except for incomplete types.
A noninstance
body
other than a renames-as-body causes
freezing of each entity
and profile declared
before it within the same
declarative_part that is not an incomplete type; it only causes freezing of an incomplete
type if the body is within the immediate scope of the incomplete type.
3.a
Discussion: This is worded carefully
to handle nested packages and private types. Entities declared in a nested
package_specification
will be frozen by some containing construct.
3.b/3
{
AI05-0017-1}
An incomplete type declared in the private part of a library
package_specification
can be completed in the body.
For other incomplete
types (and in the bodies of library packages), the completion of the
type will be frozen at the end of the package or declarative_part,
and that will freeze the incomplete view as well.
3.b.1/3
{
AI05-0017-1}
The reason we have to worry about freezing of incomplete
types is to prevent premature uses of the types in dispatching calls.
Such uses may need access to the tag of the type, and the type has to
be frozen to know where the tag is stored.
3.c/3
Ramification: {
AI05-0229-1}
The part about bodies does not say
immediately within. A renaming-as-body
does not have this property. Nor does
an imported
body a pragma
Import.
3.d
Reason: The reason bodies cause freezing
is because we want
proper_bodies and
body_stubs
to be interchangeable — one should be able to move a
proper_body
to a
subunit,
and vice-versa, without changing the semantics. Clearly, anything that
should cause freezing should do so even if it's inside a
proper_body.
However, if we make it a
body_stub,
then the compiler can't see that thing that should cause freezing. So
we make
body_stubs
cause freezing, just in case they contain something that should cause
freezing. But that means we need to do the same for
proper_bodies.
3.e
Another reason for bodies to cause freezing,
there could be an added implementation burden if an entity declared in
an enclosing
declarative_part
is frozen within a nested body, since some compilers look at bodies after
looking at the containing
declarative_part.
3.f/3
4/1
{
8652/0046}
{
AI95-00106-01}
A construct that (explicitly or implicitly) references
an entity can cause the
freezing of the entity, as defined by
subsequent paragraphs.
At the place where a construct
causes freezing, each
name,
expression,
implicit_dereference expression[,
or
range]
within the construct causes freezing:
4.a
Ramification: Note that in the sense
of this paragraph, a
subtype_mark
“references” the denoted subtype, but not the type.
5/3
{
AI05-0213-1}
The occurrence of a
generic_instantiation
causes freezing
, except that a name
which is a generic actual parameter whose corresponding generic formal
parameter is a formal incomplete type (see 12.5.1)
does not cause freezing. In addition, if;
also, if a parameter of the instantiation is defaulted, the
default_expression
or
default_name
for that parameter causes freezing.
5.a/3
Ramification: {
AI05-0213-1}
Thus, an actual parameter corresponding to a formal
incomplete type parameter may denote an incomplete or private type which
is not completely defined at the point of the generic_instantiation.
6
The occurrence of an
object_declaration
that has no corresponding completion causes freezing.
6.a
7
The declaration of a record
extension causes freezing of the parent subtype.
7.a
Ramification: This combined with another
rule specifying that primitive subprogram declarations shall precede
freezing ensures that all descendants of a tagged type implement all
of its dispatching operations.
7.b/2
{
AI95-00251-01}
The declaration of a private extension does not cause freezing. The freezing
is deferred until the full type declaration, which will necessarily be
for a record extension
, task, or protected type
(the latter only for a limited private extension derived from an interface).
7.1/2
{
AI95-00251-01}
The declaration of a record extension, interface
type, task unit, or protected unit causes freezing of any progenitor
types specified in the declaration.
7.b.1/2
Reason: This rule
has the same purpose as the one above: ensuring that all descendants
of an interface tagged type implement all of its dispatching operations.
As with the previous rule, a private extension does not freeze its progenitors;
the full type declaration (which must have the same progenitors) will
do that.
7.b.2/2
Ramification: An
interface type can be a parent as well as a progenitor; these rules are
similar so that the location of an interface in a record extension does
not have an effect on the freezing of the interface type.
7.2/3
8/3
8.1/3
{
8652/0046}
{
AI95-00106-01}
{
AI05-0019-1}
An implicit call freezes the
same entities and profiles that
would be frozen by an explicit call. This is true even if the implicit
call is removed via implementation permissions.
8.2/1
{
8652/0046}
{
AI95-00106-01}
If an expression is implicitly
converted to a type or subtype T, then at the place where the
expression causes freezing, T is frozen.
9
The following rules
define which entities are frozen at the place where a construct causes
freezing:
10
10.a
Reason: We considered making enumeration
literals never cause freezing, which would be more upward compatible,
but examples like the variant record aggregate (Discrim => Red, ...)
caused us to change our mind. Furthermore, an enumeration literal is
a static expression, so the implementation should be allowed to represent
it using its representation.
10.b
Ramification:
The following pathological example was legal in Ada 83, but is illegal
in Ada 95:
10.c
package P1 is
type T is private;
package P2 is
type Composite(D : Boolean) is
record
case D is
when False => Cf : Integer;
when True => Ct : T;
end case;
end record;
end P2;
X : Boolean := P2."="( (False,1), (False,1) );
private
type T is array(1..Func_Call) of Integer;
end;
10.d
In Ada 95, the declaration of X freezes Composite
(because it contains an expression of that type), which in turn freezes
T (even though Ct does not exist in this particular case). But type T
is not completely defined at that point, violating the rule that a type
shall be completely defined before it is frozen. In Ada 83, on the other
hand, there is no occurrence of the name T, hence no forcing occurrence
of T.
10.1/3
{
AI05-0019-1}
{
AI05-0177-1}
At the
place where a function call causes freezing, the profile of the function
is frozen. Furthermore, if a parameter of the call is defaulted, the
default_expression
for that parameter causes freezing. If the function call is to an expression
function, the expression
of the expression function causes freezing.
10.e/3
Reason: {
AI05-0019-1}
This is the important rule for profile freezing:
a call freezes the profile. That's because generating the call will need
to know how the parameters are passed, and that will require knowing
details of the types. Other uses of subprograms do not need to know about
the parameters, and thus only freeze the subprogram, and not the profile.
10.f/3
Note that we don't need
to consider procedure or entry calls, since a body freezes everything
that precedes it, and the end of a declarative part freezes everything
in the declarative part.
10.g/3
Ramification: {
AI05-0177-1}
Freezing of the expression
of an expression function only needs to be considered when the expression
function is in the same compilation unit and there are no intervening
bodies; the end of a declarative_part or library package freezes everything
in it, and a body freezes everything declared before it.
10.2/3
10.h/3
Reason: Elaboration
of the generic might call the actual for one of its formal subprograms,
so we need to know the profile and (for an expression function) expression.
10.3/3
{
AI05-0177-1}
At the place where a use of
the Access or Unchecked_Access attribute whose prefix
denotes an expression function causes freezing, the expression
of the expression function causes freezing.
10.i/3
Reason:
This is needed to avoid calls to unfrozen expressions. Consider:
10.j/3
package Pack is
10.k/3
type Flub is range 0 .. 100;
10.l/3
function Foo (A : in Natural) return Natural is
(A + Flub'Size); -- The expression is not frozen here.
10.m/3
type Bar is access function Foo (A : in Natural) return Natural;
10.n/3
P : Bar := Foo'Access; -- (A)
10.o/3
Val : Natural := P.all(5); -- (B)
10.p/3
end Pack;
10.q/3
If point (A) did not freeze
the expression of Foo (which freezes Flub), then the call at point (B)
would be depending on the aspects of the unfrozen type Flub. That would
be bad.
11
At
the place where a
name
causes freezing, the entity denoted by the
name
is frozen, unless the
name
is a
prefix
of an expanded name;
at the place where an object
name causes
freezing, the nominal subtype associated with the
name
is frozen.
11.a/2
Ramification: {
AI95-00114-01}
This only matters in the presence of deferred constants or access types;
an
object_declaration
other than a
deferred constant declaration deferred_constant_declaration
causes freezing of the nominal subtype, plus all component junk.
11.b/1
11.1/1
11.c/2
Discussion: This
rule ensures that X.D freezes the same entities that X.all.D does.
Note that an implicit_dereference
is neither a name
nor expression
by itself, so it isn't covered by other rules.
12
[
At the place where a
range
causes freezing, the type of the
range
is frozen.]
12.a
Proof: This is consequence of the facts
that expressions freeze their type, and the Range attribute is defined
to be equivalent to a pair of expressions separated by “..”.}
13
At
the place where an
allocator
causes freezing, the designated subtype of its type is frozen. If the
type of the
allocator
is a derived type, then all ancestor types are also frozen.
13.a
Ramification: Allocators
also freeze the named subtype, as a consequence of other rules.
13.b
The ancestor types
are frozen to prevent things like this:
13.c
type Pool_Ptr is access System.Storage_Pools.Root_Storage_Pool'Class;
function F return Pool_Ptr;
13.d
package P is
type A1 is access Boolean;
type A2 is new A1;
type A3 is new A2;
X : A3 := new Boolean; -- Don't know what pool yet!
for A1'Storage_Pool use F.all;
end P;
13.e
This is necessary because derived access types
share their parent's pool.
14/3
{
AI05-0019-1}
At the place where a
profile callable
entity is frozen, each subtype of
the its
profile is frozen. If the
corresponding callable
entity is a member of an entry family, the index subtype of the family
is frozen.
At the place where
a function call causes freezing, if a parameter of the call is defaulted,
the default_expression
for that parameter causes freezing.
14.a/3
This paragraph
was deleted.Discussion: We don't
worry about freezing for procedure calls or entry calls, since a body
freezes everything that precedes it, and the end of a declarative part
freezes everything in the declarative part.
15
At
the place where a subtype is frozen, its type is frozen.
At
the place where a type is frozen, any expressions or
names
within the full type definition cause freezing; the first subtype, and
any component subtypes, index subtypes, and parent subtype of the type
are frozen as well.
For a specific
tagged type, the corresponding class-wide type is frozen as well. For
a class-wide type, the corresponding specific type is frozen as well.
15.a
Ramification: Freezing a type needs to
freeze its first subtype in order to preserve the property that the subtype-specific
aspects of statically matching subtypes are the same.
15.b
Freezing an access type does not freeze its
designated subtype.
15.1/3
15.c/2
Reason: We have
a language design principle that all of the details of a specific tagged
type are known at its freezing point. But that is only true if the primitive
subprograms are frozen at this point as well. Late changes of Import
and address clauses violate the principle.
15.d/2
Implementation Note:
This rule means that no implicit call to Initialize or Adjust can
freeze a subprogram (the type and thus subprograms would have been frozen
at worst at the same point).
15.e/3
Discussion: {
AI05-0019-1}
The second sentence is the rule that makes it possible
to check that only subprograms with convention Ada are specified in attribute_definition_clauses
without jumping through hoops.
Legality Rules
16
[The explicit declaration
of a primitive subprogram of a tagged type shall occur before the type
is frozen (see
3.9.2).]
16.a
Reason: This rule is needed because (1)
we don't want people dispatching to things that haven't been declared
yet, and (2) we want to allow tagged type descriptors to be static (allocated
statically, and initialized to link-time-known symbols). Suppose T2 inherits
primitive P from T1, and then overrides P. Suppose P is called before
the declaration of the overriding P. What should it dispatch to? If the
answer is the new P, we've violated the first principle above. If the
answer is the old P, we've violated the second principle. (A call to
the new one necessarily raises Program_Error, but that's beside the point.)
16.b
Note that a call upon a dispatching operation
of type T will freeze T.
16.c
We considered applying this rule to all derived
types, for uniformity. However, that would be upward incompatible, so
we rejected the idea. As in Ada 83, for an untagged type, the above call
upon P will call the old P (which is arguably confusing).
16.d/3
To be honest: {
AI05-0222-1}
This rule only applies to "original"
declarations and not to the completion of a primitive subprogram, even
though a completion is technically an explicit declaration, and it may
declare a primitive subprogram.
17
[A type shall be completely
defined before it is frozen (see
3.11.1
and
7.3).]
18
[The completion of
a deferred constant declaration shall occur before the constant is frozen
(see
7.4).]
18.a/2
Proof: {
AI95-00114-01}
The above Legality Rules are stated “officially”
in the referenced clauses.
19/1
{
8652/0009}
{
AI95-00137-01}
An operational or A
representation item that directly specifies an aspect of an entity shall
appear before the entity is frozen (see
13.1).
19.a/1
19.a.1/2
{
AI95-00114-01}
The above Legality Rule is stated for types and
subtypes in 13.1, but the rule here covers
all other entities as well.
19.b/2
This paragraph
was deleted.Proof: {
AI95-00114-01}
The above Legality Rules are stated “officially”
in the referenced clauses.
19.c
Discussion:
Here's an example that illustrates when freezing occurs in the presence
of defaults:
19.d
type T is ...;
function F return T;
type R is
record
C : T := F;
D : Boolean := F = F;
end record;
X : R;
19.e
Since the elaboration of R's declaration does
not allocate component C, there is no need to freeze C's subtype at that
place. Similarly, since the elaboration of R does not evaluate the
default_expression
“F = F”, there is no need to freeze the types involved at
that point. However, the declaration of X
does need to freeze
these things. Note that even if component C did not exist, the elaboration
of the declaration of X would still need information about T —
even though D is not of type T, its
default_expression
requires that information.
19.f
Ramification: Although we define freezing
in terms of the program text as a whole (i.e. after applying the rules
of Section 10), the freezing rules actually have no effect beyond compilation
unit boundaries.
19.g
Reason: That is important, because Section
10 allows some implementation definedness in the order of things, and
we don't want the freezing rules to be implementation defined.
19.h
19.i
Implementation Note: An implementation
may choose to generate code for
default_expressions
and
default_names
in line at the place of use.
Alternatively, an implementation
may choose to generate thunks (subprograms implicitly generated by the
compiler) for evaluation of defaults. Thunk generation cannot, in general,
be done at the place of the declaration that includes the default. Instead,
they can be generated at the first freezing point of the type(s) involved.
(It is impossible to write a purely one-pass Ada compiler, for various
reasons. This is one of them — the compiler needs to store a representation
of defaults in its symbol table, and then walk that representation later,
no earlier than the first freezing point.)
19.j
In implementation terms, the linear elaboration
model can be thought of as preventing uninitialized dope. For example,
the implementation might generate dope to contain the size of a private
type. This dope is initialized at the place where the type becomes completely
defined. It cannot be initialized earlier, because of the order-of-elaboration
rules. The freezing rules prevent elaboration of earlier declarations
from accessing the size dope for a private type before it is initialized.
19.k
2.8 overrides the
freezing rules in the case of unrecognized
pragmas.
19.l/1
Dynamic Semantics
20/2
{
AI95-00279-01}
The tag (see 3.9) of
a tagged type T is created at the point where T is frozen.
Incompatibilities With Ada 83
20.a
RM83 defines a forcing occurrence
of a type as follows: “A forcing occurrence is any occurrence [of
the name of the type, subtypes of the type, or types or subtypes with
subcomponents of the type] other than in a type or subtype declaration,
a subprogram specification, an entry declaration, a deferred constant
declaration, a
pragma,
or a
representation_clause for the type itself.
In any case, an occurrence within an expression is always forcing.”
20.b
It seems like
the wording allows things like this:
20.c
type A is array(Integer range 1..10) of Boolean;
subtype S is Integer range A'Range;
-- not forcing for A
20.d
Occurrences within
pragmas
can cause freezing in Ada 95. (Since such
pragmas
are ignored in Ada 83, this will probably fix more bugs than it causes.)
Extensions to Ada 83
20.e
20.f
package Outer is
type T is tagged limited private;
generic
type T2 is
new T with private; -- Does not freeze T
-- in Ada 95.
package Inner is
...
end Inner;
private
type T is ...;
end Outer;
20.g
This is important for the usability of generics.
The above example uses the Ada 95 feature of formal derived types. Examples
using the kinds of formal parameters already allowed in Ada 83 are well
known. See, for example, comments 83-00627 and 83-00688. The extensive
use expected for formal derived types makes this issue even more compelling
than described by those comments. Unfortunately, we are unable to solve
the problem that
explicit_generic_actual_parameters
cause freezing, even though a package equivalent to the instance would
not cause freezing. This is primarily because such an equivalent package
would have its body in the body of the containing program unit, whereas
an instance has its body right there.
Wording Changes from Ada 83
20.h
The concept of freezing is based on Ada 83's
concept of “forcing occurrences.” The first freezing point
of an entity corresponds roughly to the place of the first forcing occurrence,
in Ada 83 terms. The reason for changing the terminology is that the
new rules do not refer to any particular “occurrence” of
a name of an entity. Instead, we refer to “uses” of an entity,
which are sometimes implicit.
20.i
In Ada 83, forcing occurrences were used only
in rules about representation_clauses. We
have expanded the concept to cover private types, because the rules stated
in RM83-7.4.1(4) are almost identical to the forcing occurrence rules.
20.j
The Ada 83 rules
are changed in Ada 95 for the following reasons:
20.k
The Ada 83 rules do not work right for subtype-specific
aspects. In an earlier version of Ada 9X, we considered allowing representation
items to apply to subtypes other than the first subtype. This was part
of the reason for changing the Ada 83 rules. However, now that we have
dropped that functionality, we still need the rules to be different from
the Ada 83 rules.
20.l
The Ada 83 rules do not achieve the intended
effect. In Ada 83, either with or without the AIs, it is possible to
force the compiler to generate code that references uninitialized dope,
or force it to detect erroneousness and exception raising at compile
time.
20.m
It was a goal of Ada 83 to avoid uninitialized
access values. However, in the case of deferred constants, this goal
was not achieved.
20.n
The Ada 83 rules are not only too weak —
they are also too strong. They allow loopholes (as described above),
but they also prevent certain kinds of
default_expressions
that are harmless, and certain kinds of
generic_declarations
that are both harmless and very useful.
20.o/2
Incompatibilities With Ada 95
20.p/2
{
8652/0046}
{
AI95-00106-01}
{
AI95-00341-01}
Corrigendum: Various
freezing rules were added to fix holes in the rules. Most importantly,
implicit calls are now freezing, which make some representation clauses
illegal in Ada 2005 that were legal (but dubious) in Ada 95. Amendment
Correction: Similarly, the primitive subprograms of a specific tagged
type are frozen when the type is frozen, preventing dubious convention
changes (and address clauses) after the freezing point. In both cases,
the code is dubious and the workaround is easy.
Wording Changes from Ada 95
20.q/2
{
8652/0009}
{
AI95-00137-01}
Corrigendum: Added wording to specify that
both operational and representation attributes must be specified before
the type is frozen.
20.r/2
{
AI95-00251-01}
Added wording that declaring a specific descendant
of an interface type freezes the interface type.
20.s/2
{
AI95-00279-01}
Added wording that defines when a tag is created
for a type (at the freezing point of the type). This is used to specify
checking for uncreated tags (see 3.9).
Incompatibilities With Ada 2005
20.t/3
{
AI05-0019-1}
Correction: Separated
the freezing of the profile from the rest of a subprogram, in order to
reduce the impact of the Ada 95 incompatibility noted above. (The effects
were much more limiting than expected.)
Wording Changes from Ada 2005
20.u/3
{
AI05-0017-1}
Correction: Reworded so that incomplete
types with a deferred completion aren't prematurely frozen.
20.v/3
{
AI05-0177-1}
Added freezing rules for expression functions;
these are frozen at the point of call, not the point of declaration,
like default expressions.
20.w/3
{
AI05-0183-1}
Added freezing rules for aspect_specifications;
these are frozen at the freezing point of the associated entity, not
the point of declaration.
20.x/3
{
AI05-0213-1}
Added freezing rules for formal incomplete types;
the corresponding actual is not frozen.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe