Version 1.3 of ais/ai-00106.txt

Unformatted version of ais/ai-00106.txt version 1.3
Other versions for file ais/ai-00106.txt

!standard 13.14 (06)          99-08-31 AI95-00106/06
!standard 13.14 (08)
!standard 13.14 (11)
!standard 13.14 (15)
!class binding interpretation 96-04-04
!status Corrigendum 2000 99-05-25
!status WG9 approved 96-12-07
!status ARG approved 11-0-0 96-10-07
!status work item (letter ballot was 9-3-0) 96-10-03
!status ARG approved 8-0-0 (subject to letter ballot) 96-06-17
!status work item 96-04-17
!status received 96-04-04
!priority High
!difficulty Hard
!qualifier Omission
!subject Freezing Rules
!summary
1. An object name causes freezing where it occurs, unless the name is part of a default_expression, a default_name, or a per-object expression of a component's constraint, in which case, the freezing occurs later as part of another construct.
2. An implicit_dereference freezes entities according to the same rule that applies to a name that is an explicit_dereference.
3. An implicit call, such as an implicit call to Initialize, freezes the called subprogram. This is true even if the implicit call is removed via the Implementation Permissions in 7.6(18-21).
4. If a name or expression is implicitly converted to a type or subtype, then that type or subtype is frozen at the same place where the name or expression causes freezing.
!question
1. Does an object_renaming_declaration cause freezing of the renamed object? (Yes.)
For example, is the following legal? (No.)
package P is type T is private; type Acc is access T; X: Acc; Y: T renames X.all; -- Illegal! private type T is ...; end P;
----------------
2. Now, consider the following example:
package P is type T(D: Integer) is private; type A is access T; Obj: A; I: Integer := Obj.D; -- Does this freeze T? (Yes, -- and it's therefore illegal.) private type T(D: Integer) is ...; end P;
Does the declaration of I freeze the type T? If we replaced "Obj.D" with "Obj.all.D", then it would freeze T, and therefore be illegal.
13.14(11-11.b) says:
11 {freezing [entity caused by a name]} 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; {freezing [nominal subtype caused by a name]} at the place where an object name causes freezing, the nominal subtype associated with the name is frozen.
11.a 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 Implicit_dereferences are covered by expression.
It seems that (11.b) is wrong -- an implicit_dereference is not an expression.
----------------
3. Does an implicit call to Initialize freeze the subprogram? The freezing rules seem to apply to explicit constructs. For example:
type T is new Controlled with record...; procedure Initialize(X: in out T); X: T; -- Implicit call to Initialize. for Initialize'Address use ...; -- Legal? (No.)
If this is legal, it will raise Program_Error, but 13.14(1.o) argues that that's no excuse.
The same question applies to Adjust and Finalize, and also to implicit calls to user-defined storage pool operations.
----------------
4. It seems unclear whether an implicit type conversion freezes. For example:
type Color is (Red, Yellow); subtype S is Color range Red..Red; -- The expression "Red" freezes type Color.
BUT:
type T is range 1..100; subtype S is T range 1..10; -- Freezes type T? (Yes.)
The expressions "1" and "10" are of type universal_integer, so T is not frozen. But it seems like it should be -- the value is implicitly converted to type T, and so it's very much like an expression of type T.
13.14(12) seems to agree that the implicit conversion should freeze.
12 [{freezing [type caused by a range]} 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 ``..''.}
Here's a case not covered by 13.14(12):
type T is range 1..10; function F(X: T) return boolean; X: Boolean := F(10); -- Freezes type T? (Yes.) for T'Size use 4; -- Legal? (No.)
!recommendation
(See summary.)
!wording
1. Add object names to 13.14(8):
A static expression causes freezing where it occurs. [A] {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, or a per-object expression of a component's constraint, in which case, the freezing occurs later as part of another construct.
2. Add implicit_dereferences to 13.14(11), replacing it with:
At the place where a name or implicit dereference causes freezing, the denoted entity is frozen, unless the name is a prefix of an expanded name; at the place where an object name or implicit dereference causes freezing, the associated nominal subtype is frozen.
3. Add a paragraph to cover implicit calls:
An implicit call to one of the subprograms in Ada.Finalization or System.Storage_Pools freezes the same entities that would be frozen by an explicit call. This is true even if the implicit call is removed via the Implementation Permissions in 7.6.
4. Add a paragraph to cover implicit type conversions:
If an expression is explicitly converted to a type or subtype T, then at the place where the expression causes freezing, T is frozen.
!discussion
1. 13.14(8) says that expressions cause freezing. It does not cover names that denote objects, but it should -- the reasons for the existence of 13.14(8) apply equally to object names.
Given the recommendation of this AI, the above example (1) is illegal. The occurrence of "X.all" freezes the type T, but the type is not completely defined at that point, thus violating 13.14(17). Note that the declaration of Y is an object_renaming_declaration, not an object_declaration, so 13.14(6) does not apply.
If the above example (1) were legal, it would necessarily raise Constraint_Error due to dereferencing a null access value. However, 13.14(1.o-1.1.u) explains that we do not wish to rely on run-time checks for this kind of example. Furthermore, it is possible to construct examples that do not necessarily raise an exception.
Object_renaming_declarations are not the only offender. Here's another example:
with System.Storage_Pools; use System.Storage_Pools; package Q is type My_Pool is new Root_Storage_Pool with private; type My_Pool_Ptr is access all My_Pool; Ptr: My_Pool_Ptr;
type Acc is access Integer; for Acc'Storage_Pool use Ptr.all; -- Illegal! private type My_Pool is new Root_Storage_Pool with ...; end Q;
The above is illegal because the name "Ptr.all" freezes type My_Pool before My_Pool is completely defined.
The problem occurs in any case where an object name can occur, and is analogous to the expression case in 13.14(8); hence the recommendation of this AI is worded by analogy with 13.14(8).
----------------
2. Clearly, the same rules should apply to explicit and implicit dereferences -- in the example, "Obj.all.D" and "Obj.D" should freeze the same entities. Therefore, 13.14(11) is extended to cover implicit_dereferences, so that the "Obj" in "Obj.D" freezes the same entities that "Obj.all" would freeze. That is, an implicit_dereference freezes the denoted object and its nominal subtype.
----------------
3 and 4. Clearly implicit calls and implicit conversions should freeze in the same manner as their explicit counterparts. An implicit call should freeze even if it is removed via the Implementation Permissions in 7.6(18-21); otherwise, there would be a portability problem.
!corrigendum 13.14(8)
Replace the paragraph:
A static expression causes freezing where it occurs. A nonstatic expression causes freezing where it occurs, unless the expression is part of a default_expression, a default_name, or a per-object expression of a component's constraint, in which case, the freezing occurs later as part of another construct.
by:
A static expression 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, or a per-object expression of a component's constraint, in which case, the freezing occurs later as part of another construct.
!corrigendum 13.14(11)
Replace the paragraph:
by:
!corrigendum 13.14(15)
Insert after the paragraph:
the new paragraphs:
An implicit call to one of the subprograms in Ada.Finalization or System.Storage_Pools freezes the same entities that would be frozen by an explicit call. This is true even if the implicit call is removed via the Implementation Permissions in 7.6.
If an expression is explicitly converted to a type or subtype T, then at the place where the expression causes freezing, T is frozen.
!ACATS test
A B-Test should be constructed to check each of the examples in this issue.
!appendix

!section 13.14(06)
!subject Does an object renaming cause freezing?
!reference AARM95-13.14(6);6.0
!from Jesper Joergensen 95-10-30
!reference 95-5371.a Jesper Joergensen 95-10-30>>
!discussion

I'm in doubt whether an object renaming causes freezing. The above mentioned
paragraph does not mention object renamings (since the syntactic construct
object_declaration is used). On the other hand, there is an ACVC program
(b74103i) that tests for an object renaming freezing the subtype (but for all
of the cases in this test, elaboration_error would result).

--
+---------------------------------------------------------------------+
|                                                                     |
|           \_\_\_\_   \_\_\_\_    \_\_\_\_       \_                  |
|            \_     \_  \_     \_  \_              \_                 |
|             \_      \_ \_      \_ \_       \_\_\_ \_                |
|              \_     \_  \_     \_  \_              \_               |
|               \_\_\_\_   \_\_\_\_    \_\_\_\_       \_              |
|                                                                     |
|  Jesper Jorgensen                                                   |
|  DDC-I A/S                            Phone:       +45 45 87 11 44  |
|  Lundtoftevej 1 B                     Fax:         +45 45 87 22 17  |
|  DK-2800 Lyngby, Denmark              Email:       jj@ddci.dk       |
+---------------------------------------------------------------------+

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

!section 13.14(06)
!subject Does an object renaming cause freezing?
!reference AARM95-13.14(6);6.0
!from Jesper Joergensen 95-11-29
!reference 95-5399.a Jesper Joergensen 95-11-29>>
!discussion

I'm in doubt whether an object renaming causes freezing. The above mentioned
paragraph does not mention object renamings (since the syntactic construct
object_declaration is used). On the other hand, there is an ACVC program
(b74103i) that tests for an object renaming freezing the subtype (but for all
of the cases in this test, elaboration_error would result). After a discussion
on the ACVC mailing list, it seems that freezing should indeed occur.


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

!section 13.14(06)
!subject Does an object renaming cause freezing?
!reference AARM95-13.14(6);6.0
!reference comment from Jesper Joergensen 95-10-30, re-sent 95-11-29
!reference 95-5403.a Dan Lehman 95-11-30>>
   <<referenced as: 95-5371.a Jesper Joergensen 95-10-30>>
   <<referenced as: 95-5399.a Jesper Joergensen 95-11-29>> [DUPL. OF 95-5371.a]
!discussion

Here are the comments from the ACVC Reviewers (or Fast-Reaction Team,
since in this case the only commenters are both) on this issue.

The AVO's preference is to retain the old test (written for ACVC 1.11/Ada83,
kept for ACVC 2.0/Ada95; which Ada95 validations 001..004 included without
challenge (Intermetrics,GNAT-SGI)), with perhaps a note that it may be ruled
NA on challenge as per the Ada95 standard, but that it's expected that the
ARG will support the test and amend the standard.  (Truly *transitioning*
implementations ought to already include the rule.)

---Dan Lehman
-------------- *

* * * * * * * * *From: Gary Dismukes  Tue Nov 28 21:20:59 1995

[REF. ACVC 2.0 TEST PROGRAM B74103I]
> This test assumes that an object_renaming_declaration causes freezing of the
> type of the renaming. However, RM paragraphs 13.14(5-7) state that only a
> generic_instantiation, object_declaration, or record extension can cause
> freezing. Since the word for the syntactic construct object_declaration is
> used, this does not include an object_renaming_declaration (but maybe that
> was a mistake in the RM !?)

Actually, expressions can also cause freezing of course (13.14(8)), but
you're right that the current rules don't cover object renamings.  This
looks like an oversight to me.  Note that the name given for a generic
actual parameter corresponding to a formal in out object causes
freezing, so it seems reasonable that the object name given in
an object renaming should also cause freezing.  It also seems
that the name given in a subprogram renaming should cause freezing
in some cases (at least for evaluable names).

> Jesper Joergensen,  DDC-I   (jj@ddci.dk)

-- Gary Dismukes


* * * * * * * * *From Robert Dewar Tue Nov 28 21:15:24 1995

how could an object renaming NOT cause freezing of the type, it would
seem very strange to me if this were the case. THe name is an expression
after all.


* * * * * * * * *From Gary Dismukes Tue Nov 28 21:15:26 1995

> how could an object renaming NOT cause freezing of the type, it would
> seem very strange to me if this were the case. THe name is an expression
> after all.

No, the name in an object renaming is not an expression, that's the problem.
But I think it's clear that it should freeze.

-- Gary

* * * * * * * * *From Robert Dewar   Tue Nov 28 20:36:14 1995

the name is not an expression ..

yes, well, it is of course syntactically of the form of an expression. Here
is the same disucssion as occurred in Ada 83 as to wheter 1+23 is a static
expression in A := 1+23;
the expression here is of the form of a static expression, but is not (in
Ada 83) a static expression in the syntactic sense.

* * * * * * * * *From Robert Dewar   Wed Nov 29 08:23:55 1995

I think it definitely is the case that the object renaming must cause
freezing. Consider

  x : integer renames a (j); -- j dynamic

one possible implementation used by more than one compiler (Alsys did it,
and GNAT does it), is to make a pointer to the object and store that as
the value of x. This is certainly a reasonable, and this implementation
would clearly need the name to be frozen.

* * * * * * * * *From Jesper Jorgensen   Wed Nov 29 03:08:15 1995

I seems that the name in an object renaming should cause freezing. The problem
is, though, that the manual says is doesn't.

The conclusion must be that an AI must be made (and that I must implement this
freezing in our compiler).

/Jesper

* * * * * * * * *From Erhard Ploedereder   Wed Nov 29 11:17:35 1995

> This test assumes that an object_renaming_declaration causes freezing of the
> type of the renaming.

I agree that a rule requiring freezing of the renamed object should be in
the ARM. An AI should be produced.

Jesper, if you haven't already, can you submit an offical comment to
ada-comment ?  [WELL, HE HAD & HE DID, HENCE DUPLICATE REFERENCE-AS!]

An observation, though: I can't think of a single example, in which an
object_renaming_decl that renames an unfrozen object would not result in
CONSTRAINT_ERROR or PROGRAM_ERROR by an elaboration check (and the
raising of that exception can be determined statically).

* * * * * * * * *

[... SOME EXAMPLE CODE EXCHANGE BY GARY TO ERHARD, LEADING TO ...]

* * * * * * * * *From Tucker Taft   Wed Nov 29 13:29:32 1995

> > Easy.  How about:
>
> >  X: T;
> >  Y: T renames X;
>
> T already frozen by the first decl. No need to freeze it again.
> Next rock, please :-)

T is already frozen, true.  But X is not.  The question is
can you follow these two declarations with:

   for X'Address use Blah;

or

   for X'Size use foo;

-Tuck

* * * * * * * * *From Robert Dewar   Wed Nov 29 13:37:40 1995

As tuck says,

   T is already frozen, true.  But X is not.  The question is
   can you follow these two declarations with:

      for X'Address use Blah;
   or
      for X'Size use foo

and the answer should please be NO, because otherwise it is an implemenjtation
pain for very little gain!

* * * * * * * * *From Erhard Ploedereder   Wed Nov 29 20:00:15 1995

> T is already frozen, true.  But X is not.  The question is
> can you follow these two declarations with:
>    for X'Address use Blah;
> or
>    for X'Size use foo;

Right. I was focusing only on the freezing of types, even if I wrote
differently. (And Gary gave me an example where my guess was wrong for
types, too:
  DC: constant T;
  RC: T renames DC;
)

Erhard

=============================================================================

!section 13.14(11)
!subject Freezing of incomplete types
!reference RM95-13.14(11)
!from Bob Duff
!reference 96-5476.a Robert A Duff 96-4-12>>
!discussion

Consider the following example:

    package P is
        type T is private;
    private
        type R(D: Boolean); -- Completed in body
        type T is access all R;
        Obj: T;
    end P;

    package body P is
        B1: Boolean := Obj.D; -- Legal?
        procedure Q is separate; -- Legal?

        type R(D: Boolean) is null record;
    begin
        Q;
    end P;

First question, pointed out to me by Gary Dismukes:
Does the declaration of B1 freeze the type R?  If we replaced "Obj.D"
with "Obj.all.D", then it would freeze R, and therefore be illegal.
Clearly, the same rules should apply to "Obj.all.D" and "Obj.D".

13.14(11-11.b) says:

     11  {freezing [entity caused by a name]} 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; {freezing [nominal
         subtype caused by a name]} at the place where an object name
         causes freezing, the nominal subtype associated with the name is
         frozen.
   11.a   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   Implicit_dereferences are covered by expression.

It seems that (11.b) is wrong -- an implicit_dereference is *not* an
expression.  13.14(11) should be extended to cover
implicit_dereferences, so that the "Obj" in "Obj.D" freezes the same
entities that "Obj.all" would freeze.  That is, an implicit_dereference
should freeze the denoted object and its nominal subtype.

Second question: Does the procedure body Q freeze R?  It certainly
should, for all the reasons given in 13.14(3.d) -- in particular, Q
might contain something that would need to freeze R, but we can't tell
at compile time of the body of P.

13.14(3) says:

 A noninstance body causes freezing of each entity declared before it
 within the same declarative_part.

It not cover this case, because R is not declared in the same
declarative_part as the body Q.  Therefore, "declarative_part" should be
changed to "declarative region", so Q freezes R, and is thus illegal.

- Bob


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

!section 13.14(11)
!subject Freezing of incomplete types
!reference RM95-13.14(11)
!reference as: 96-5476.a Robert A Duff 96-4-12
!reference 96-5489.a Robert I. Eachus 96-4-15>>
!discussion
!from Robert I Eachus 96-4-15

   Bob Duff says:

  > It seems that (11.b) is wrong -- an implicit_dereference is *not*
  > an expression.  13.14(11) should be extended to cover
  > implicit_dereferences, so that the "Obj" in "Obj.D" freezes the
  > same things that "Obj.all" would freeze.  That is, an
  > implicit_dereference should freeze the denoted object and its
  > nominal subtype.

  Agreed.

  > Second question: Does the procedure body Q freeze R?  It certainly
  > should, for all the reasons given in 13.14(3.d) -- in particular,
  > Q might contain something that would need to freeze R, but we
  > can't tell at compile time of the body of P.

    Don't agree here, without a (pathological) example.  The freezing
of R must occur in the body of P, and must occur before the body of Q
can be compiled.  Nothing in Q can affect the representation of R
anyway, so I don't see anything here sufficiently broken to require a
check.

    (However, this would have implications for the GNAT approach to
inlining, so I am prepared to be convinced if Robert Dewar finds a
significant problem.)


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

!section 13.14(11)
!subject Freezing of incomplete types
!reference RM95-13.14(11)
!reference 96-5476.a Robert A Duff 96-4-12
!reference 96-5489.a Robert I Eachus 96-4-15
!from Bob Duff
!reference 96-5492.a Robert A Duff 96-4-16>>
!discussion

I wrote the following, which is wrong.  I had forgotten that incomplete
types are special -- the freezing rules don't need to cover them,
because there are other rules specific to incomplete types, which are
much more strict than the freezing rules.  Thanks to Robert Eachus for
reminding me.

> Consider the following example:
>
>     package P is
>         type T is private;
>     private
>         type R(D: Boolean); -- Completed in body
>         type T is access all R;
>         Obj: T;
>     end P;
>
>     package body P is
>         B1: Boolean := Obj.D; -- Legal?

Illegal.

>         procedure Q is separate; -- Legal?

Legal.

>         type R(D: Boolean) is null record;
>     begin
>         Q;
>     end P;
>
> First question, pointed out to me by Gary Dismukes:
> Does the declaration of B1 freeze the type R?  If we replaced "Obj.D"
> with "Obj.all.D", then it would freeze R, and therefore be illegal.
> Clearly, the same rules should apply to "Obj.all.D" and "Obj.D".

Nonsense.  3.10.1(10) already covers this case:

  10   A dereference (whether implicit or explicit -- see 4.1) shall not be of
  an incomplete type.

> 13.14(11-11.b) says:
>
>      11  {freezing [entity caused by a name]} 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; {freezing [nominal
>        subtype caused by a name]} at the place where an object name
>        causes freezing, the nominal subtype associated with the name is
>        frozen.
>    11.a   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   Implicit_dereferences are covered by expression.
>
> It seems that (11.b) is wrong -- an implicit_dereference is *not* an
> expression.  13.14(11) should be extended to cover
> implicit_dereferences, so that the "Obj" in "Obj.D" freezes the same
> things that "Obj.all" would freeze.  That is, an implicit_dereference
> should freeze the denoted object and its nominal subtype.

I still think that (11.b) is wrong.  Here's a different example, which I
think illustrates the problem here:

    package P is
        type T(D: Integer) is private;
        type A is access T;
        Obj: A;
        I: Integer := Obj.D; -- Does this freeze T?
    private
        type T(D: Integer) is ...;
    end P;

The declaration of I would clearly be illegal if we had written
Obj.all.D.  It should be illegal as written, too.

> Second question: Does the procedure body Q freeze R?  It certainly
> should, for all the reasons given in 13.14(3.d) -- in particular, Q
> might contain something that would need to freeze R, but we can't tell
> at compile time of the body of P.
>
> 13.14(3) says:
>
>  A noninstance body causes freezing of each entity declared before it
>  within the same declarative_part.
>
> It not cover this case, because R is not declared in the same
> declarative_part as the body Q.  Therefore, "declarative_part" should be
> changed to "declarative region", so Q freezes R, and is thus illegal.

Nonsense again.  If the body of Q contains anything nasty, the rules for
incomplete types will make it illegal.  There is no need to make the
freezing rules cover this case.

- Bob

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

!section 13.14(00)
!subject A couple of freezing issues
!reference RM95-13.14(00)
!from Bob Duff
!reference 96-5493.a Robert A Duff 96-4-16>>
!discussion

Does an implicit call to Initialize freeze the subprogram?  The freezing
rules seem to apply to explicit constructs.  For example:

    type T is new Controlled with record...;
    procedure Initialize(X: in out T);
    X: T; -- Implicit call to Initialize.
    for Initialize'Address use ...; -- Legal?

If this is legal, it will raise P_E, but 13.14(1.o) argues that that's
no excuse.

The same question applies to Adjust and Finalize.

It also seems unclear whether an implicit type conversion freezes.
E.g.:

    type Color is (Red, Yellow);
    subtype S is Color range Red..Red; -- The expression "Red" freezes type Color.

BUT:

    type T is range 1..100;
    subtype S is T range 1..10; -- Freezes type T?

The expressions "1" and "10" are of type universal_integer, so T is not
frozen.  But it seems like it should be -- the value is implicitly
converted to type T, and so it's very much like an expression of type T.

13.14(12) seems to agree that the implicit conversion should freeze.

   12  [{freezing [type caused by a range]} 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 ``..''.}

Here's a case not covered by 13.14(12):

    type T is range 1..10;
    function F(X: T) return boolean;
    X: Boolean := F(10); -- Freezes type T?
    for T'Size use 4; -- Legal?  (I hope not.)

It seems to me the recent (draft) AI on freezing rules should cover
these two cases as well.

- Bob

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

Questions? Ask the ACAA Technical Agent