Version 1.2 of ai12s/ai12-0261-1.txt
!standard 10.1.2(12/3) 18-03-06 AI12-0261-1/02
!standard 10.1.2(13/2)
!standard 10.1.2(14/2)
!standard 10.1.2(15/2)
!standard 10.1.2(16/2)
!class binding interpretation 15-06-04
!status Amendment 1-2012 18-03-05
!status ARG Approved 7-0-5 18-03-05
!status work item 15-06-04
!status received 15-04-28
!priority Low
!difficulty Easy
!qualifier Clarification
!subject Conflict in "private with" rules
!summary
Only one of the bullets 10.1.2(13-16/2) needs to be true for a name to be
legal.
!question
The Legality Rules for references to names mentioned in a private with are:
[12] A name denoting a library_item (or the corresponding declaration for a
child of a generic within an instance - see 10.1.1), if it is visible
only due to being mentioned in one or more with_clauses that include the
reserved word private, shall appear only within:
[13] * a private part;
[14] * a body, but not within the subprogram_specification of a library
subprogram body;
[15] * a private descendant of the unit on which one of these with_clauses
appear; or
[16] * a pragma within a context clause.
Consider the case of the body of a private library subprogram:
package Foo is
type Bar is ...
end Foo;
private with Foo;
package Parent is
...
end Parent;
private procedure Parent.Child (A : Foo.Bar); --
procedure Parent.Child (A : Foo.Bar) is --
...
Bullet [14] says clearly that this is illegal, but that is nonsense:
there would be no legal way to complete this specification.
10.1.1(12) describes "private descendant" in terms of the unit declarations;
it appears that body units aren't covered by this term. (Note that the
paragraph never mentions "library_unit_body"). Thus bullet [15] doesn't
apply (and even if it did, it would be confusing).
Should this be fixed? (Yes.)
!recommendation
(See Summary.)
!wording
Modify 10.1.2(12/3):
A name denoting a library_item (or the corresponding declaration for a child
of a generic within an instance - see 10.1.1), if it is visible only due to
being mentioned in one or more with_clauses {of unit U} that include the
reserved word private, shall appear only within:
Modify 10.1.2(14/2):
* a body{ of a public descendant of U}, but not within the
subprogram_specification of a [library subprogram] body {of a subprogram
that is a public descendant of U};
Modify 10.1.2(15/2):
* a private descendant of [the unit on which one of these with_clauses
appear]{U or its body}; or
!discussion
Note that a private body as posed in the original question (see the !appendix)
is illegal: "private" cannot be used on a body. That changes the question, but
makes a fix more important, as a body is not a private descendant of
anything.
!corrigendum 10.1.2(12/3)
Replace the paragraph:
A name denoting a library_item (or the corresponding declaration
for a child of a generic within an instance — see 10.1.1), if it
is visible only due to being mentioned in one or more with_clauses
that include the reserved word private, shall appear only within:
by:
A name denoting a library_item (or the corresponding declaration
for a child of a generic within an instance — see 10.1.1), if it
is visible only due to being mentioned in one or more with_clauses
of unit U that include the reserved word private, shall appear
only within:
!corrigendum 10.1.2(14/2)
Replace the paragraph:
- a body, but not within the subprogram_specification of a
library subprogram body;
by:
- a body of a public descendant of U, but not within the
subprogram_specification of a body of a subprogram that is a public
descendant of U;
!corrigendum 10.1.2(15/2)
Replace the paragraph:
- a private descendant of the unit on which one of these
with_clauses appear; or
by:
- a private descendant of U or its body; or
!ASIS
No ASIS effect.
!ACATS test
Add an ACATS test for this case, based on BA120013, BA120014, or BA120015.
!appendix
From: Randy Brukardt
Sent: Thursday, February 15, 2018 7:26 PM
I was looking at the Legality Rules for "private with", and noticed a conflict.
The rules are:
[12] A name denoting a library_item (or the corresponding declaration for a
child of a generic within an instance - see 10.1.1), if it is visible
only due to being mentioned in one or more with_clauses that include the
reserved word private, shall appear only within:
[13] * a private part;
[14] * a body, but not within the subprogram_specification of a library
subprogram body;
[15] * a private descendant of the unit on which one of these with_clauses
appear; or
[16] * a pragma within a context clause.
Of course, using what Steve calls "heat vision", I started to wonder what
happens for a private library subprogram body:
package Foo is
type Bar is ...
end Foo;
private with Foo;
package Parent is
...
end Parent;
private procedure Parent.Child (A : Foo.Bar) is -- Legal?
So is this parameter legal?
[15] says that it is OK to refer to Foo in a private descendant. Great, so
it's legal.
[14] says that is not OK to refer to Foo in the subprogram specification of
a library subprogram body. Parent.Child surely is a library subprogram body.
Darn, it is not legal.
That's two different answers. Apparently the answer depends on which bullet
the compiler implementer tests first. Not good.
The ACATS test in question doesn't try this case (apparently neither Pascal
Leroy [who wrote the test] or I [who vetted it] thought of this case). The
ACATS test objectives are written such that it appears that it is legal (there
are tests for all of the illegal cases, but this case is not among them -- the
objective specifically says "public descendant").
Having written this, I note that bullet [15] ends with "or". That implies that
it is only necessary for one of these bullets to be true (as opposed to having
only one apply); in that case, the answer is that it is legal.
That's not obvious enough that probably there should be an AARM note discussing
this case. Something like:
AARM Ramification: Only one of these bullets need to be true for the name
to be legal. In particular, a use of a name mentioned in a private with is
allowed in the subprogram specification of a private subprogram body
descendant of the unit with the private with, despite the "not within"
wording of the second bullet.
Thoughts??
****************************************************************
From: Tucker Taft
Sent: Thursday, February 15, 2018 8:51 PM
> Having written this, I note that bullet [15] ends with "or". That
> implies that it is only necessary for one of these bullets to be true
> (as opposed to having only one apply); in that case, the answer is that it
> is legal.
I suppose, but when it says "not within" that seems like it might overrule the
"or". I would suggest we invert the order so that the rule about private
descendant (now [15]) comes before the rule about "body" (now [14]), and then
we can preface the body rule by "the body of a public descendant, but not
within the subprogram_specification of the body of a subprogram that is a
public descendant." Note that the public descendants of a library unit
includes the library unit itself.
****************************************************************
From: Randy Brukardt
Sent: Wednesday, February 28, 2018 9:18 PM
...
> > Having written this, I note that bullet [15] ends with "or". That
> > implies that it is only necessary for one of these bullets to be
> > true (as opposed to having only one apply); in that case, the answer
> > is that it is legal.
>
> I suppose, but when it says "not within" that seems like it might
> overrule the "or". I would suggest we invert the order so that the
> rule about private descendant (now [15]) comes before the rule about
> "body" (now [14]), and then we can preface the body rule by "the body
> of a public descendant, but not within the subprogram_specification of
> the body of a subprogram that is a public descendant." Note that the
> public descendants of a library unit includes the library unit itself.
This rewrite doesn't work, because you can't just say "public descendant"
without saying of what!
You also missed something more important: my original example is illegal for
other reasons. It was:
package Foo is
type Bar is ...
end Foo;
private with Foo;
package Parent is
...
end Parent;
private procedure Parent.Child (A : Foo.Bar) is -- Legal?
...
However, you can't have "private" on a body (it's not allowed syntactically).
You can however write this as a completion:
private procedure Parent.Child (A : Foo.Bar); --OK
procedure Parent.Child (A : Foo.Bar) is -- Legal?
...
...and since a body is never a descendant (public or private) -- the
definition only applies to library units, not library bodies -- [15] doesn't
apply and the completion is clearly illegal. Which is clearly nonsense, so
we have to fix something here (an AARM note is not enough).
I just suggested the rather lengthy wording:
Modify 10.1.2(14):
* a body, but not within the subprogram_specification of a library subprogram
body {unless that body is the completion of a private descendant of the unit
on which one of these with_clauses appear};
This is clearly correct, but it's rather long! Better ideas welcome.
****************************************************************
From: Tucker Taft
Sent: Friday, March 2, 2018 6:25 AM
Below is what I proposed earlier, but now with a more explicit indication of
what is the ancestor of these "descendants." This seems a bit clearer and
simpler than what you proposed.
------------
A name denoting a library_item (or the corresponding declaration for a child
of a generic within an instance - see 10.1.1), if it is visible only due to
being mentioned in one or more with_clauses of unit U that include the
reserved word private, shall appear only within:
* a private part;
* a private descendant of U;
* a body of a public descendant of U, but not within the
subprogram_specification of a body of a subprogram that is a public
descendant of U; or
* a pragma within a context clause.
****************************************************************
From: Randy Brukardt
Sent: Friday, March 2, 2018 5:30 PM
> Below is what I proposed earlier, but now with a more explicit
> indication of what is the ancestor of these "descendants." This seems
> a bit clearer and simpler than what you proposed.
This is better. Pragmatically, though, I don't like reordering the bullets if
we can avoid it, as compiler error messages probably depend on these
paragraphs (I know ours do). I'm not sure there's really any need for the
reordering anyway, the two middle bullets are disjoint with this rewording.
> ------------
>
> A name denoting a library_item (or the corresponding declaration for a
> child of a generic within an instance - see 10.1.1), if it is visible
> only due to being mentioned in one or more with_clauses of unit U that
> include the reserved word private, shall appear only within:
>
> * a private part;
>
> * a private descendant of U;
>
> * a body of a public descendant of U, but not within the
> subprogram_specification of a body of a subprogram that is a public
> descendant of U; or
>
> * a pragma within a context clause.
The problem with this is that a body is not a descendant of U at all. So you
have lost the bodies of private descendants of U altogether. This requires
fixing up the "private" bullet. So I'd suggest (reverting to the original
order):
A name denoting a library_item (or the corresponding declaration for a child
of a generic within an instance - see 10.1.1), if it is visible only due to
being mentioned in one or more with_clauses of unit U that include the
reserved word private, shall appear only within:
* a private part;
* a body of a public descendant of U, but not within the
subprogram_specification of a body of a subprogram that is a public
descendant of U;
* a private descendant of U or its body; or
* a pragma within a context clause.
****************************************************************
From: Tucker Taft
Sent: Friday, March 2, 2018 6:42 PM
Works for me.
****************************************************************
Questions? Ask the ACAA Technical Agent