!standard 10.1.2(12/3) 18-02-28 AI12-0261-1/01 !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 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) need 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? ... 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(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}; !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. !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. ****************************************************************