!standard 13.14 (06) 00-04-11 AI95-00106/09 !standard 13.14 (08) !standard 13.14 (11) !standard 13.14 (04) !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: 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. 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. Implicit_dereferences are covered by expression. It seems that AARM 13.14(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 AARM 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. [At the place where a range causes freezing, the type of the range is frozen.] 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 a new bullet for implicit_dereferences following 13.14(11): At the place where an implicit_dereference causes freezing, the nominal subtype associated with the implicit_dereference is frozen. Add implicit_dereference to 13.14(4): ...expression, {implicit_dereference}, or... 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, AARM 13.14(1.o-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, a new bullet after 13.14(11) is added 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. Since an implicit_dereference is not an expression and is not be a name ( although it may be part of a name), it is added to 13.14(4). ---------------- 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(4) @drepl 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 @fa, expression, or @fa within the construct causes freezing: @dby 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 @fa, @fa, @fa, or @fa within the construct causes freezing: !corrigendum 13.14(8) @drepl A static expression causes freezing where it occurs. A nonstatic expression causes freezing where it occurs, unless the expression is part of a @fa, a @fa, or a per-object expression of a component's @fa, in which case, the freezing occurs later as part of another construct. @dby 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 @fa, a @fa, or a per-object expression of a component's @fa, in which case, the freezing occurs later as part of another construct. An implicit call freezes the same entities that would be frozen by an explicit call. This is true even if the implicit call is removed via implementation permissions. If an expression is implicitly converted to a type or subtype @i, then at the place where the expression causes freezing, @i is frozen. !corrigendum 13.14(11) @dinsa @xbullet causes freezing, the entity denoted by the @fa is frozen, unless the @fa is a @fa of an expanded name; at the place where an object @fa causes freezing, the nominal subtype associated with the @fa is frozen.> @dinst @xbullet causes freezing, the nominal subtype associated with the @fa 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>> <> <> [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 ****************************************************************