Version 1.5 of ais/ai-00220.txt
!standard 10.1.2 (8) 02-11-27 AI95-00220/03
!class binding interpretation 99-05-27
!status Amendment 200Y 02-10-24
!status ARG Approved 10-0-0 02-10-12
!status work item 99-05-27
!status received 99-05-27
!priority High
!difficulty Easy
!qualifier Error
!subject Subprograms withing private compilation units
!summary
A subprogram body without a distinct subprogram declaration is considered a
declaration (and not a body) for the purposes of checking 10.1.2(8).
!question
Consider the following compilation units:
package A is ...
private package A.B is ...
package A.B.C is ...
with A.B.C; --
procedure A.Fred is ...
Is the with of A.B.C legal? (No.)
!recommendation
(See summary.)
!wording
Replace 10.1.2(8) by:
If a with_clause of a given compilation_unit mentions a private
child of some library unit, then the given compilation_unit shall be either
* the declaration, body, or subunit of a private descendant of that
library unit; or
* the body or subunit of a public descendant of that library unit,
but not a subprogram body acting as a subprogram declaration, see 10.1.4.
!discussion
A subprogram body which acts as a declaration by 10.1.4(4/1) clearly must be
treated as public. If this was not so, an example like:
with A.B.C;
procedure A.Fred(X: in A.B.C.Bar := A.B.C.Foobar) is ... end A.Fred;
would be legal, "exporting" a type declared in a private unit. A public
declaration should never depend semantically on a private unit.
This clearly was intended by the designers of Ada 95. For instance, AARM
10.1.2(8.l) says
To be honest: For the purposes of this rule, if a subprogram_
body has no preceding subprogram_declaration, the subprogram_body
should be considered a declaration and not a body. Thus, it is
illegal for such a subprogram_body to mention one of its siblings in
a with_clause if the sibling is a private library unit.
This AI corrects the wording to match the intent.
!corrigendum 10.01.02(8)
Replace the paragraph:
If a with_clause of a given compilation_unit mentions a private
child of some library unit, then the given compilation_unit shall be either
the declaration of a private descendant of that library unit or the body
or a subunit of a (public or private) descendant of that library unit.
by:
If a with_clause of a given compilation_unit mentions a private
child of some library unit, then the given compilation_unit shall be either
- the declaration, body, or subunit of a private descendant of that
library unit; or
- the body or subunit of a public descendant of that library unit,
but not a subprogram body acting as a subprogram declaration, see 10.1.4.
!ACATS test
A B-Test should be constructed to test the example given in the question
and similar cases.
!appendix
From: Robert I. Eachus
Sent: Monday, May 24, 1999 2:16 PM
dennison@telepath.com wrote:
>
> I have a situation where Gnat and ObjectAda are giving me conflicting
> results.
>
> The situation is basicly this
>
> package A is ....
>
> private package A.B is ...
>
> package A.B.C is ...
>
> with A.B.C;
>
> procedure A.Fred is ...
>
> This compiled fine for one developer using ObjectAda. But with Gnat, I
> get:
> current unit must also be private descendant of "JPATS_Aircraft_Body"
> on the with statement.
Tucker replied:
>The relevant RM paragraph is RM95 10.1.2(8):
> If a with_clause of a given compilation_unit mentions a private child
> of some library unit, then the given compilation unit shall be either
> the declaration of a private descendant of that library unit or the body
> or subunit of a (public or private) descendant of that library unit.
>
>The only possible source of confusion here is whether "procedure A.Fred is"
>is a declaration or a body. You might try creating a separate explicit
>procedure "spec" for A.Fred and see whether GNAT likes it any better.
>However, as you can see from the above RM wording, that shouldn't be
>necessary, because even if there is no separate spec for A.Fred, it
>is still a body (even if also a declaration), and so the second half of
>the rule applies, meaning the with_clause is legal.
I disagree with the analysis in the last sentence. If the body of the
procedure acts as the (visible) declaration of A.Fred, the the declaration
can contain references to types and objects declared in the private package.
There are cases where this would be a "useful" hole in the language, but I
can't imagine that it is intended:
with A.B.C;
procedure A.Fred(X: in A.B.C.Bar := A.B.C.Foobar) is ... end A.Fred;
(The "useful hole" mentioned above is that you could have functions in
the private package that are used as defaults, but can't be otherwise
called outside the package hierarchy. To modify the example above:
with A.B.C;
procedure A.Fred(X: in A.Bar := A.B.C.Foobar) is ... end A.Fred;
Of course, the equivalent can be done by having two procedures, one
with a default and one without. Of course, if they are library items, they
must have distinct names.)
*************************************************************
From: Tucker Taft
Sent: Tuesday, May 25, 1999 1:32 PM
I guess I agree with Robert on this one. If a library
subprogram does not have a separate spec, then it should not be
allowed to "with" the private descendants of its ancestor units.
One of the fundamental rules of private units is that no unit
outside the "subsystem" rooted at their parent may become
semantically dependent on the unit (10.1.2(8.a)). If a specless subprogram
were allowed to "with" a private unit, then anything that
"with"ed the specless subprogram would violate this rule.
Sounds like an "AI" is needed to clarify 10.1.2(8) to say that
the last part of the sentence does not apply to specless subprogram
bodies.
*************************************************************
From: Gary Dismukes
Sent: Tuesday, May 25, 1999 4:32 PM
I also agree that (public) library subprograms without separate specs
should not be allowed to with private siblings (or cousins or whatever).
There's actually already a "to be honest" paragraph in the AARM that
addresses this:
8.l To be honest: For the purposes of this rule, if a subprogram_
body has no preceding subprogram_declaration, the subprogram_body
should be considered a declaration and not a body. Thus, it is
illegal for such a subprogram_body to mention one of its siblings in
a with_clause if the sibling is a private library unit.
-- Gary
*************************************************************
From: Randy Brukardt
Sent: Tuesday, May 25, 1999 4:12 PM
I'll be happy to open an AI this topic, but I think I would like to see some
concurrence that it is needed. (*I* think it is needed. It is clear to me
that ObjectAda implemented the rules as written, and GNAT implemented the
rules as they are intended -- and since those implementations were
different, we have a problem.)
Randy.
*************************************************************
From: Gary Dismukes
Sent: Tuesday, May 25, 1999 5:39 PM
I think we should definitely have an AI (the rules clearly say the
wrong thing, and the AARM "to-be-honest" expresses the intent but
isn't normative).
-- Gary
*************************************************************
Questions? Ask the ACAA Technical Agent