Version 1.3 of ai12s/ai12-0372-1.txt
!standard 3.10.2(19.3/4) 20-06-10 AI12-0372-1/03
!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
Within a function body, the accessibility level of entities declared in the
function are statically deeper than the master of the call.
!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); --
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
Modify 3.10.2(10.5/5):
If the call itself defines the result of a function {F} [to which one
of the above rules applies], or has an accessibility level that is tied
to the result of such a function {F}, [these rules are applied
recursively] {then the master of the call is that of the master of the
call invoking F}.
Delete 3.10.2(19.3/4):
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 level of the master of
the call is presumed to be the same as that of the level of the master
that elaborated the body of F.
and replace it with:
When within a function body or the return expression of an expression
function, the accessibility level of the master representing an
execution of the function is statically deeper than that of the master
of the function call invoking that execution[Redundant:, independent
of how the master of the function call is determined (see above)].
!discussion
When combined with other rules, such as 6.4.1(6.4/3):
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 given the proposed revised rule given above for 3.10.2(10.5/5), we
will correctly conclude that the call on Make(Y) in the return statement in
the example given in the !problem will be disallowed, because Y is statically
deeper than the level of the master of the call.
The new rule also covers the case from the deleted paragraph, because it will
also make the level of anything declared within a function F statically deeper
than the master that elaborated the body of F, which is the primary intent of
this prior rule.
Here is a somewhat more complex example:
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); --
begin
if True then
return Make (Y); --
else
return C; --
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.
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 Func. By the new rule, we know that
the level of Y is statically deeper than the master of the call of Func,
making the call at (2) illegal.
For the return of C at (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.D is that of
C, and C is clearly statically deeper than the master that elaborated the body
of F, so 6.5(5.9/5) clearly fails.
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.)
---
It can be necessarily to apply 3.10.2(10.1-6/3) more than once before it is
possible to apply the new rule to determine the result. Consider:
procedure Test3 is
type Discriminated (D : access Integer) is tagged null record;
Glob : aliased Integer := 1;
function Make (Param : aliased in out Integer)
return Discriminated is
begin
return (D => Param'access);
end Make;
function Copy (Obj : aliased in Discriminated;
Selector : in Natural) return Discriminated is
begin
if Selector = 0 then
return Make (Glob); --
else
return Obj; --
end if;
end Copy;
function Func return Discriminated is
Y : aliased Integer := 0;
begin
return Copy (Make (Y), 0); --
end Func;
Result : Discriminated := Func;
begin
null;
end Test3;
(1) is OK as Glob is library-level, which surely is not deeper than anything.
(2) is OK directly by 3.10.2(21.1/5).
For (3), 6.4.1(6.4/3) again applies to the call of Make (as well as the call
of Copy). We again have to check whether Y is statically deeper than the
master of the call of Make.
Copy's parameter has the same accessibility as is the master of the
call of Copy (by 3.10.2(7/5)). Therefore the accessibility of the parameter of
Copy is tied to the master of the call of Copy. We know by applying the
second part of 3.10.2(10.5/5) that the master of the call of Make is therefore
the master of the call of Copy. By applying the first part of 3.10.2(10.5/5),
the master of the call of Copy is that of Func. Now we can apply 3.10.2(10/5)
again then know by the new rule that that the level of Y is statically deeper
than the master of the call of Func, making the call at (3) illegal.
!ASIS
No ASIS effect.
!ACATS test
An ACATS B-Test should be constructed to verify that the examples are
appropriately 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).
****************************************************************
From: Justin Squirek
Sent: Thursday, June 11, 2020 12:33 AM
I was going through AI12-0372 and found the example "Test3" under the
discussion section has some errors:
procedure Test3 is
type Discriminated (D : access Integer) is null record;
Glob : aliased Integer := 1;
function Make (Param : aliased in out Integer)
return Discriminated is
begin
return (D => Param'Access);
end Make;
function Copy (Obj : aliased in out Discriminated;
Selector : in Natural) is -- No return here
begin
if Selector = 0 then
return Make (Glob);
else
return Obj;
end if;
end Copy;
function Func return Discriminated is
Y : aliased Integer := 0;
begin
return Copy (Make (Y)); -- Missing Selector, and a function call is used
-- as an actual for an aliased in out formal
end Func;
Result : Discriminated := Func;
begin
null;
end Test3;
****************************************************************
From: Randy Brukardt
Sent: Thursday, June 11, 2020 12:33 AM
The parameter to Copy needs to be mode "in", and type Discriminated needs to
be tagged. Then with the other missing text this should work and illustrate
the issue. Sigh.
procedure Test3 is
type Discriminated (D : access Integer) is tagged null record;
Glob : aliased Integer := 1;
function Make (Param : aliased in out Integer)
return Discriminated is
begin
return (D => Param'Access);
end Make;
function Copy (Obj : aliased in Discriminated;
Selector : in Natural) return Discriminated is
begin
if Selector = 0 then
return Make (Glob);
else
return Obj;
end if;
end Copy;
function Func return Discriminated is
Y : aliased Integer := 0;
begin
return Copy (Make (Y), 0);
end Func;
Result : Discriminated := Func;
begin
null;
end Test3;
****************************************************************
Questions? Ask the ACAA Technical Agent