!standard 10.1.2(12/3) 18-05-07 AI12-0261-1/04 !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 WG9 Approved 16-06-22 !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); -- OK. procedure Parent.Child (A : Foo.Bar) is -- Legal? (Yes.) ... 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 a 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) @drepl A @fa denoting a @fa (or the corresponding declaration for a child of a generic within an instance @emdash see 10.1.1), if it is visible only due to being mentioned in one or more @fas that include the reserved word @b, shall appear only within: @dby A @fa denoting a @fa (or the corresponding declaration for a child of a generic within an instance @emdash see 10.1.1), if it is visible only due to being mentioned in one or more @fas of a unit @i that include the reserved word @b, shall appear only within: !corrigendum 10.1.2(14/2) @drepl @xbullet of a library subprogram body;> @dby @xbullet, but not within the @fa of a body of a subprogram that is a public descendant of @i;> !corrigendum 10.1.2(15/2) @drepl @xbullets appear; or> @dby @xbullet 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. ****************************************************************