Skip to main content

13.14 Freezing Rules

danger

This Reference Manual output has not been verified, and may contain omissions or errors. Report any problems on the tracking issue

1/3

[This subclause 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

Similar issues arise for incomplete types. However, we do not use freezing to prevent premature access; 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, 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

However, if the construct is not evaluated where it appears, let it cause freezing later, when it is evaluated. This is the case for default_expressions and default_names. (Formal parameters, generic formal parameters, and components can have default_expressions or default_names.)

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

This subclause 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/5

{8652/0014} 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, as well as the entity itself in the case of the declaration of a library unit. A noninstance proper_body, body_stub, or entry_body causes freezing of each entity and profile declared before it within the same declarative_part.

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/5

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.

3.c/3
ramification

The part about bodies does not say immediately within. A renaming-as-body does not have this property. Nor does an imported body

3.d/5
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/4

Note that null_procedure_declarations and expression_function_declarations (even when those are used as completions), as well as generic_instantiations and renames-as-bodies do not necessarily cause freezing; each have their own specific rules.

3.g/5
ramification

Note that the rule about proper bodies causing freezing only applies in declarative_parts. All of the kinds of bodies (see 3.11.1 – keep in mind the difference from bodys) that are allowed in a package specification have their own freezing rules, so they don't need to be covered by the above rule.

4/1

{8652/0046} 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[, 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
  • 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 a parameter of the instantiation is defaulted, the default_expression or default_name for that parameter causes freezing.
5.a/3
ramification

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.

5.1/4
5.b/4
reason

This rule prevents calls through access values to an expression that might have unfrozen parts. Typically, elaboration checks and other freezing rules prevent this, but in this case the completion is elaborated and since this is not a body it does not by itself freeze anything that precedes it.

5.2/4
  • At the occurrence of a renames-as-body whose callable_entity_name denotes an expression function, the return expression of the expression function causes freezing.
  • 6
  • The occurrence of an object_declaration that has no corresponding completion causes freezing.
6.a
ramification

Note that this does not include a formal_object_declaration.

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

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
  • 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/5
  • At the freezing point of the entity associated with an aspect_specification, any static expressions within the aspect_specification cause freezing, as do expressions or names in aspect_definitions for representation aspects, or operational aspects that have a corresponding operational attribute. Similarly, if an aspect_definition for an operational aspect, other than an assertion aspect, can affect the Name Resolution, Static Semantics, or Legality Rules of a subsequent construct, then any expressions or names within the aspect_definition cause freezing at the freezing point of the associated entity. Any static expressions within an aspect_specification also cause freezing at the end of the immediately enclosing declaration list. For the purposes of this rule, if there is no declared entity associated with an aspect_specification, the freezing point is considered to occur immediately following the aspect_specification.
8/4

{8652/0046} A static expression (other than within an aspect_specification) causes freezing where it occurs. An object name or nonstatic expression causes freezing where it occurs, unless the name or expression is part of a default_expression, a default_name, the return expression of an expression function, an aspect_specification, or a per-object expression of a component's constraint, in which case, the freezing occurs later as part of another construct or at the freezing point of an associated entity.

8.1/3

{8652/0046} 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} 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/5
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.a.1/5

We exclude uses of enumeration literals that are used in part for setting the representation of the type (aspect Default_Value is defined to be a representation aspect) so we don't freeze the type while determining 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/4
  • 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 return expression of the expression function causes freezing.
10.e/3
reason

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/4
ramification

Freezing of the return 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 bodys; the end of a declarative_part or library package freezes everything in it, and a body freezes everything declared before it.

10.2/4
  • At the place where a generic_instantiation causes freezing of a callable entity, the profile of that entity is frozen unless the formal subprogram corresponding to the callable entity has a parameter or result of a formal untagged incomplete type; if the callable entity is an expression function, the return expression of the expression function causes freezing.
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/4
  • At the place where a use of the Access or Unchecked_Access attribute whose prefix denotes an expression function causes freezing, the return 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/4

type Bar is access function (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

This only matters in the presence of deferred constants or access types; an object_declaration other than a deferred constant declaration causes freezing of the nominal subtype, plus all component junk.

11.b/1
This paragraph was deleted.{8652/0046}
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
  • At the place where a profile is frozen, each subtype of the profile is frozen. If the corresponding callable entity is a member of an entry family, the index subtype of the family is frozen.
14.a/3
This paragraph was deleted.
15/5
  • 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, other than those that occur within an access_type_definition or an access_definition; 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
  • At the place where a specific tagged type is frozen, the primitive subprograms of the type are frozen. At the place where a type is frozen, any subprogram named in an attribute_definition_clause for the type is frozen.
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

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.

15.2/5
  • At the place where a construct causes freezing, if the construct includes a check associated with some assertion aspect [(independent of whether the check is enabled)], or depends on the definition of some operational aspect as part of its Dynamic Semantics, any names or expressions in the aspect_definition for the aspect cause freezing.
15.f/5
ramification

Aspects such as Constant_Indexing cause freezing when they are used — the name in a Constant_Indexing would cause freezing when a generalized_indexing that makes use of it causes freezing.

15.3/5

Notwithstanding the rest of this subclause, freezing an incomplete view has no effect.

15.g/5
ramification

In particular, freezing an incomplete view does not freeze the completion of the view. For an incomplete type, once the completion of the incomplete type is seen, any further references to the type will be of the complete type, which will be frozen in the normal way. Legality Rules prevent all problems for incomplete types themselves.

15.h/5

In contrast, freezing a partial view does have an effect (the completion of the view is frozen and the program is illegal if it hasn't occurred yet).

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: 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/5
This paragraph was deleted.
19/1

{8652/0009} [An operational or representation item that directly specifies an aspect of an entity shall appear before the entity is frozen (see 13.1).]

19.a/1
discussion

{8652/0009} From RM83-13.1(7). The wording here forbids freezing within the aspect_clause itself, which was not true of the Ada 83 wording. The wording of this rule is carefully written to work properly for type-related representation items. For example, an enumeration_representation_clause is illegal after the type is frozen, even though the _clause refers to the first subtype.

19.a.1/5
This paragraph was deleted.
19.b/5
proof

The above Legality Rules are stated “officially” in the referenced subclauses.

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 Clause 10), the freezing rules actually have no effect beyond compilation unit boundaries.

19.g
reason

That is important, because Clause 10 allows some implementation definedness in the order of things, and we don't want the freezing rules to be implementation defined.

19.h
ramification

These rules also have no effect in statements — they only apply within a single declarative_part, package_specification, task_definition, protected_definition, or protected_body.

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/3

2.8 overrides the freezing rules in the case of unrecognized pragmas; similarly 13.1.1 overrides the freezing rules in the case of a specification of an unrecognized aspect.

19.l/1

{8652/0009} An aspect_clause for an entity should most certainly not be a freezing point for the entity.

Dynamic Semantics

20/2

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

In Ada 95, generic_formal_parameter_declarations do not normally freeze the entities from which they are defined. For example:

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
  • Ada 83 had a case where an aspect_clause had a strong effect on the semantics of the program — 'Small. This caused certain semantic anomalies. There are more cases in Ada 95, because the attribute_definition_clause has been generalized.

Incompatibilities With Ada 95

20.p/2
correction

{8652/0046} 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 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} Corrigendum: Added wording to specify that both operational and representation attributes must be specified before the type is frozen.

20.r/2

Added wording that declaring a specific descendant of an interface type freezes the interface type.

20.s/2

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
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
correction

Reworded so that incomplete types with a deferred completion aren't prematurely frozen.

20.v/3

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

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

Added freezing rules for formal incomplete types; the corresponding actual is not frozen.

Wording Changes from Ada 2012

20.y/4

Corrigendum: Clarified when and what an expression_function_declaration that is a completion or that is the target of a renames-as-body freezes. This is formally an incompatibility, but as all known implementations freeze expression functions more aggressively than allowed by either the old or new wording, practically this will be an extension.

20.z/5
correction

Clarified that the implicit body created by an instance doesn't have any freezing effect. This was an unintentional change caused by the Technical Corrigendum 1 oversimplifying wording.

20.aa/5
correction

Clarified that incomplete types do not freeze in any case. The one known case where incomplete freezing was necessary has been plugged with a new Legality Rules (see 3.10.1). This matches the original intent (see Language Design Principles above) and eliminates whack-a-mole trying to allow such freezing without it having (almost) any effects.

20.bb/5
correction

Clarified that the subtype names in an access type are not frozen at the point of the type declaration. This has always been true (there is an Ada 95-era AARM note that says so) but it didn't follow from the actual wording. Since the ACATS requires the AARM note to be true, no compiler could actually get this wrong, so no incompatibility is possible.

20.cc/5
correction

Added a freezing exclusion for enumeration literals in the expression of a Default_Value aspect; otherwise, one could not set a default value for an enumeration type.

20.dd/5

Added missing definition of freezing of library units.

20.ee/5
correction

Improved and clarified the freezing rules for aspect_specifications; these now depend on the kind of aspect.