!standard 3.10.2(19.3/4) 20-03-09 AI12-0372-1/01 !standard 6.4.1(6.4/3) !class binding interpretation 20-03-09 !status work item 20-03-09 !status received 20-03-09 !priority Low !difficulty Easy !qualifier Omission !subject Static accessibility of "master of the call" !summary Inside of a function body, the contents of the function are statically deeper than the master of the call. Otherwise, the other rules defining the "master of the call" are applied until we have a result for which the statically deeper relationship is defined. !question Consider: procedure Test1 is type Discriminated (D : access Integer) is null record; function Make (Param : aliased in out Integer) return Discriminated is begin return (D => Param'Access); end; function Func return Discriminated is Y : aliased Integer := 0; begin return Make (Y); -- (1) end; Result : Discriminated := Func; begin null; end Test; The call at (1) invokes 6.4.1(6.4/3). We would want this to be illegal, as the master of the call of Func is used as the master of the call of Make, and Y is clearly more nested than any possible call of Func. But how do we determine that? 3.10.2(19.3/4) only applies to anonynous access types in a return statement for an access result. But there's no access result here. No other "statically deeper" rule comes close. Is there a rule missing here? (Yes.) !recommendation (See Summary.) !wording Replace 3.10.2(19.3/4) with: Inside of the body of a function or generic function F, other than for a call of F, the accessibility level of the master representing the execution of the body F is statically deeper than that of the master of the function call invoking F. Otherwise, the master of the function call invoking F is interpreted by the other rules of this subclause, until one of the rules defining the statically deeper relationship applies. AARM To Be Honest: Generic functions are not "executed" per-se (instances are), but since this is true for every possible instance, we can enforce the rule in generic function bodies. The "master of the call" for a recursive call is treated like the otherwise case here; it is treated like a different function from the enclosing function (as it is dynamically). End To Be Honest. !discussion The second sentence of the revised rule is describing how statically deeper checks outside of a function body F are processed. For instance, the 6.4.1(6.4/3) rule applies to function calls at the call-site. In such cases, we want to apply the (dynamic) rules until we reach an answer. But since those rules are recursive, we want to stop when we reach something for which "statically deeper" has a rule; in particular, we want to stop when we reach a "master of the call" for an enclosing function body. [Note: We don't say that we go until the "statically deeper relationship is defined", since 3.10.2(19-19.1/3) specifically don't define such a relationship - but we still want to stop if either are triggered. Not sure if that is actually possible, but I want to be safe rather than sorry here - Editor.] Consider: procedure Test2 is type Discriminated (D : access Integer) is null record; function Make (Param : aliased in out Integer) return Discriminated is begin return (D => Param'Access); end; function Func return Discriminated is Y : aliased Integer := 0; C : Discriminated := Make (Y); -- (1) begin if True then return Make (Y); -- (2) else return C; -- (3) end if; end; Result : Discriminated := Func; begin null; end Test2; 6.4.1(6.4/3) applies to each of the calls of Make. For each of these cases, we have to check whether Y is statically deeper than the master of the call of Make. Since these are calls, we can't use the revised 3.10.2(19.3) rule. Instead, we have to determine the actual master of the call of Make. For the call at (1), 3.10.2(10.2/3) says that the "master of the call" is that of the object C. We then check the level of Y against the level of C, which is the same so this call is legal. For the call at (2), however, 3.10.2(10.5/5) says that the "master of the call" is that of the enclosing function. The rule says to recursively apply the rule, but since we're inside of the body of the enclosing function, the second sentence of the revised 3.10.2(19.3) tells us to stop and apply the first sentence of the revised 3.10.2(19.3) rule, which clearly fails. Thus, this call is illegal. For the return of (3), "master of the call" is not involved with the static check 6.5(5.9/5); 3.10.2(12.5/3) says that the level of C is compared to the level of declaration of Func; that clearly fails so returning C is illegal. With this revised "statically deeper" rule, 6.5(5.9/5) could instead say "master of the call", the answer would be the same. But it's not necessary to change the rule, so we didn't do so. (That makes the discriminant case more different from the other cases - in particular the anonymous access case - but that seems harmless.) !ASIS No ASIS effect. !ACATS test An ACATS B-Test should be constructed to verify that the example is illegal. !appendix From: Steve Baird [part of private mail] procedure Test1 is type Discriminated (D : access Integer) is null record; function Make (Param : aliased in out Integer) return Discriminated is begin return (D => Param'Access); end; function Func return Discriminated is Y : aliased Integer := 0; begin return Make (Y); -- Legal? end; Result : Discriminated := Func; begin null; end; === We've got the 6.4.1 rule In a function call, the accessibility level of the actual object for each explicitly aliased parameter shall not be statically deeper than the accessibility level of the master of the call (see 3.10.2). and it is clear what the accessibility of Y is. The question is whether the level of Y is statically deeper than the accessibility level of the master of the call. Using common sense, the answer is obviously yes. But we are looking for RM wording. In 3.10.2 we've got this rule For determining whether a level is statically deeper than the level of the anonymous access type of an access result of a function or generic function F, when within a return statement that applies to F or the return expression of expression function F the function, the level of the master of the call is presumed to be the same as that of the level of the master that elaborated the function body of F. which would give us just what we want if it applied in this case, but it doesn't. Note that there are no anonymous access types in this example. I think this may be root of the problem - perhaps we want to amend this rule so that it applies in this case. I think we want a general rule that implies, one way or another, that the level of the locals declared immediately within a function is statically deeper than that of the master of the call to that function (although that might not be the right wording to express this idea). ****************************************************************