Contents   Index   Search   Previous   Next

10.1.2 Context Clauses - With Clauses

   [A context_clause is used to specify the library_items whose names are needed within a compilation unit.]

Language Design Principles

{one-pass context_clauses} The reader should be able to understand a context_clause without looking ahead. Similarly, when compiling a context_clause, the compiler should not have to look ahead at subsequent context_items, nor at the compilation unit to which the context_clause is attached. (We have not completely achieved this.)


context_clause ::= {context_item}
context_item ::= with_clause | use_clause
with_clause ::= with library_unit_name {, library_unit_name};

Name Resolution Rules

   {scope (of a with_clause)} The scope of a with_clause that appears on a library_unit_declaration or library_unit_renaming_declaration consists of the entire declarative region of the declaration[, which includes all children and subunits]. The scope of a with_clause that appears on a body consists of the body[, which includes all subunits].
Discussion: Suppose a with_clause of a public library unit mentions one of its private siblings. (This is only allowed on the body of the public library unit.) We considered making the scope of that with_clause not include the visible part of the public library unit. (This would only matter for a subprogram_body, since those are the only kinds of body that have a visible part, and only if the subprogram_body completes a subprogram_declaration, since otherwise the with_clause would be illegal.) We did not put in such a rule for two reasons: (1) It would complicate the wording of the rules, because we would have to split each with_clause into pieces, in order to correctly handle ``with P, Q;'' where P is public and Q is private. (2) The conformance rules prevent any problems. It doesn't matter if a type name in the spec of the body denotes the completion of a private_type_declaration.
A with_clause also affects visibility within subsequent use_clauses and pragmas of the same context_clause, even though those are not in the scope of the with_clause.
   {mentioned in a with_clause} {with_clause (mentioned in)} A library_item is mentioned in a with_clause if it is denoted by a library_unit_name or a prefix in the with_clause.
Discussion: With_clauses control the visibility of declarations or renamings of library units. Mentioning a root library unit in a with_clause makes its declaration directly visible. Mentioning a non-root library unit makes its declaration visible. See Section 8 for details.
Note that this rule implies that ``with A.B.C;'' is equivalent to ``with A, A.B, A.B.C;'' The reason for making a with_clause apply to all the ancestor units is to avoid ``visibility holes'' -- situations in which an inner program unit is visible while an outer one is not. Visibility holes would cause semantic complexity and implementation difficulty.
   [Outside its own declarative region, the declaration or renaming of a library unit can be visible only within the scope of a with_clause that mentions it. The visibility of the declaration or renaming of a library unit otherwise follows from its placement in the environment.]

Legality Rules

   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.
Reason: The purpose of this rule is to prevent a private child from being visible (or even semantically depended-on) from outside the subsystem rooted at its parent.
Discussion: This rule violates the one-pass context_clauses Language Design Principle. We rationalize this by saying that at least that Language Design Principle works for legal compilation units.
package A is
end A;
package A.B is
end A.B;
private package A.B.C is
end A.B.C;
package A.B.C.D is
end A.B.C.D;
with A.B.C; -- (1)
private package A.B.X is
end A.B.X;
package A.B.Y is
end A.B.Y;
with A.B.C; -- (2)
package body A.B.Y is
end A.B.Y;
(1) is OK because it's a private child of A.B -- it would be illegal if we made A.B.X a public child of A.B. (2) is OK because it's the body of a child of A.B. It would be illegal to say ``with A.B.C;'' on any library_item whose name does not start with ``A.B''. Note that mentioning A.B.C.D in a with_clause automatically mentions A.B.C as well, so ``with A.B.C.D;'' is illegal in the same places as ``with A.B.C;''.
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.
3  A library_item mentioned in a with_clause of a compilation unit is visible within the compilation unit and hence acts just like an ordinary declaration. Thus, within a compilation unit that mentions its declaration, the name of a library package can be given in use_clauses and can be used to form expanded names, a library subprogram can be called, and instances of a generic library unit can be declared. If a child of a parent generic package is mentioned in a with_clause, then the corresponding declaration nested within each visible instance is visible within the compilation unit.
Ramification: The rules given for with_clauses are such that the same effect is obtained whether the name of a library unit is mentioned once or more than once by the applicable with_clauses, or even within a given with_clause.
If a with_clause mentions a library_unit_renaming_declaration, it only ``mentions'' the prefixes appearing explicitly in the with_clause (and the renamed view itself); the with_clause is not defined to mention the ancestors of the renamed entity. Thus, if X renames Y.Z, then ``with X;'' does not make the declarations of Y or Z visible. Note that this does not cause the dreaded visibility holes mentioned above.

Extensions to Ada 83

{extensions to Ada 83} The syntax rule for with_clause is modified to allow expanded name notation.
A use_clause in a context_clause may be for a package (or type) nested in a library package.

Wording Changes from Ada 83

The syntax rule for context_clause is modified to more closely reflect the semantics. The Ada 83 syntax rule implies that the use_clauses that appear immediately after a particular with_clause are somehow attached to that with_clause, which is not true. The new syntax allows a use_clause to appear first, but that is prevented by a textual rule that already exists in Ada 83.
The concept of ``scope of a with_clause'' (which is a region of text) replaces RM83's notion of ``apply to'' (a with_clause applies to a library_item) The visibility rules are interested in a region of text, not in a set of compilation units.
No need to define ``apply to'' for use_clauses. Their semantics are fully covered by the ``scope (of a use_clause)'' definition in 8.4.

Contents   Index   Search   Previous   Next   Legal