!standard 13.14(5/3) 14-11-13 AI12-0132-1/02 !class binding interpretation 14-10-09 !status Corrigendum 2015 14-11-13 !status WG9 Approved 15-06-26 !status ARG Approved 7-0-0 14-10-18 !status work item 14-10-09 !status received 14-07-30 !priority Medium !difficulty Medium !qualifier Omission !subject Freezing of renames-as-body !summary A renames-as-body freezes the expression of any expression function that it renames. !question AI12-0103-1 appeals to an analogy with renames-as-body in order to determine how freezing for expression functions should work. Unfortunately, an example using renames-as-body has a similar problem as the one described in AI12-0103-1 for expression functions: package Pack is type Flub is range 0 .. 100; function Foo (A : in Natural) return Natural; function Bar (A : in Natural) return Natural is (A + Flub'Size); -- (A) type Fum is access function Foo (A : in Natural) return Natural; P : Fum := Foo'Access; -- (B) function Foo (A : in Natural) return Natural renames Bar; -- (C) Val : Natural := P.all(5); -- (D) end Pack; (A) doesn't freeze anything. (B) does not trigger 13.14(10.1/3), since Foo is not an expression function. (C) doesn't appear to freeze anything. Finally, the call at (D) is legal and passes elaboration checks, but the value of the result depends on a representation aspect of the unfrozen type Flub. This hole needs to be plugged somehow, right? (Yes.) !recommendation (See Summary.) !wording Add after 13.14(5/3): At the occurrence of a renames-as-body whose callable_entity_name denotes an expression function, the expression of the expression function causes freezing. !discussion There isn't any rule in Ada 2012 that causes the freezing of the name of a renamed entity. We didn't worry about freezing these in Ada 95 and Ada 2005 because any problems would be detected by a failed elaboration check. For instance, an Ada 95 example like the above could have been: package Pack2 is type Flub is range 0 .. 100; function Foo (A : in Natural) return Natural; function Bar (A : in Natural) return Natural; -- (A) type Fum is access function Foo (A : in Natural) return Natural; P : Fum := Foo'Access; -- (B) function Foo (A : in Natural) return Natural renames Bar; -- (C) Val : Natural := P.all(5); -- (D) end Pack2; In this case, nothing freezes Bar, but the call at (D) will raise Program_Error, so there will not be any possibility of evaluating something unfrozen (like Flub). If Bar had been an instance, it would have frozen everything before it. Thus, it appears that this bug is also related to the introduction of expression functions (for which neither the elaboration check nor freezing work). --- The proposed solution applies only to expression functions, as any other solution would potentially be incompatible. In the example in the question, the proposed rule means that (C) causes the expression of (A) to freeze. Then the call at (D) is safe because Flub has been frozen. !corrigendum 13.14(5/3) @dinsa @xbullet causes freezing, except that a @fa 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 @fa or @fa for that parameter causes freezing.> @dinst @xbullet@fa denotes an expression function, the @fa of the expression function causes freezing.> !ASIS No ASIS effect. !ACATS test Create an ACATS B-test to check that the case in the question causes a freezing error. !appendix From: Randy Brukardt Sent: Wednesday, July 30, 2014 8:58 PM I've just finished doing homework update to AI12-0103-1. But I'm a bit dubious about the (near) equivalence between renames-as-body and expression-function-as-completion because I can't quite figure out how renames-as-body is supposed to work. The problematical example (thanks, Steve!) for expression-function-as-completion was: package Pack is type Flub is range 0 .. 100; function Foo (A : in Natural) return Natural; type Bar is access function Foo (A : in Natural) return Natural; P : Bar := Foo'Access; -- (A) function Foo (A : in Natural) return Natural is (A + Flub'Size); -- (B) Val : Natural := P.all(5); -- (C) end Pack; This is fixed by making (B) freezing of the expression of the expression function. This appears to be essentially the same as a renames-as-body, as the renamed entity ought to be frozen at that point. Except that I can't find any rule in 13.14 that would have that effect. "Renames" is never mentioned anywhere except in 13.14(3/3) [which says it doesn't freeze]. The "name" freezing rule of 13.14(11) would do the trick, except that it requires something to freeze the "name" first -- which is what I can't find. If a renames-as-body *doesn't* freeze the renamed "name", we have the same problem as shown above: package Pack is type Flub is range 0 .. 100; function Foo (A : in Natural) return Natural; function Bar (A : in Natural) return Natural is (A + Flub'Size); -- (A) type Fum is access function Foo (A : in Natural) return Natural; P : Fum := Foo'Access; -- (B) function Foo (A : in Natural) return Natural renames Bar; -- (C) Val : Natural := P.all(5); -- (D) end Pack; The call at (D) is legal and passes elaboration checks, but the value of the result depends on a representation aspect of the unfrozen type Flub. The rules we introduced in AI12-0103-1 don't fix this hole, nor does 13.14(10.1-3/3). If (C) froze Bar, then one would expect the expression to be frozen, too (but unfortunately, that doesn't happen with the current rules - only prefixes of 'Access and calls and uses in generic instances cause that expression to freeze, and this is none of those.) Perhaps this is a new problem introduced by the addition of expression functions (any Ada 95 case would seem to raise Program_Error or already have been frozen), but even that seems weird (we don't want freezing rules to depend on the compiler's knowledge that an elaboration check will necessarily fail). If (A) is just a normal specification (with a completion in a body somewhere), I don't see any rule that would freeze it or the renames-as-body for the call (D). So, have I missed something or is there a hole here? And is the hole old (just wider now) or new? Is there any important value to not freezing the subprogram involved in a renames-as-body? P.S. Gosh, I hate freezing rules. It doesn't get the animosity it deserves since we have accessibility and coextensions to take the heat instead. (And admittedly, those are a lot worse.) ****************************************************************