10.1 Separate Compilation
This Reference Manual output has not been verified, and may contain omissions or errors. Report any problems on the tracking issue
[ A program unit is either a package, a task unit, a protected unit, a protected entry, a generic unit, or an explicitly declared subprogram other than an enumeration literal. Certain kinds of program units can be separately compiled. Alternatively, they can appear physically nested within other program units. Version=[5],Kind=(AddedNormal),Group=[C],Term=[program unit], Def=[a language construct that is a package, a task unit, a protected unit, a protected entry, a generic unit, or an explicitly declared subprogram other than an enumeration literal], Note1=[Certain kinds of program units can be separately compiled. Alternatively, they can appear physically nested within other program units.]
The text of a program can be submitted to the compiler in one or more compilation
s. Each compilation
is a succession of compilation_unit
s. A compilation_unit
contains either the declaration, the body, or a renaming of a program unit.] Version=[5],Kind=(AddedNormal),Group=[C],Term=[compilation unit], Def=[a program unit that is separately compiled], Note1=[A compilation_unit
contains either the declaration, the body, or a renaming of a program unit.] The representation for a compilation
is implementation-defined.
compilation
.compilation
be a source (text) file. Others might allow multiple source files to be automatically concatenated to form a single compilation
. Others still may represent the source in a nontextual form such as a parse tree. Note that the RM95 does not even define the concept of a source file.A library unit is a separately compiled program unit, and is a package, subprogram, or generic unit. Library units may have other (logically nested) library units as children, and may have other program units physically nested within them. A root library unit, together with its children and grandchildren and so on, form a subsystem. Version=[5],Kind=(AddedNormal),Group=[C],Term=[library unit], Def=[a separately compiled program unit, which is a package, a subprogram, or a generic unit], Note1=[Library units can have other (logically nested) library units as children, and can have other program units physically nested within them. A root library unit, together with its children and grandchildren and so on, form a subsystem.]
Implementation Permissions
4An implementation may impose implementation-defined restrictions on compilation
s that contain multiple compilation_unit
s.
compilation
that contains two versions of the same compilation unit, or that contains the declarations for library packages P1 and P2, where P1 precedes P2 in the compilation
but P1 has a with_clause
that mentions P2. Wording Changes from Ada 83
10.1.1 Compilation Units - Library Units
1[A library_item
is a compilation unit that is the declaration, body, or renaming of a library unit. Each library unit (except Standard) has a parent unit, which is a library package or generic library package.] A library unit is a child of its parent unit. The root library units are the children of the predefined library package Standard.
Syntax
2compilation
::=
{compilation_unit
}
3compilation_unit
::=
context_clause
library_item
| context_clause
subunit
4library_item
::=
[private] library_unit_declaration
| library_unit_body
| [private] library_unit_renaming_declaration
5library_unit_declaration
::=
subprogram_declaration
| package_declaration
| generic_declaration
| generic_instantiation
6library_unit_renaming_declaration
::=
package_renaming_declaration
| generic_renaming_declaration
| subprogram_renaming_declaration
7library_unit_body
::=
subprogram_body
| package_body
8parent_unit_name
::=
name
8.1/2An overriding_indicator
is not allowed in a subprogram_declaration
, generic_instantiation
, or subprogram_renaming_declaration
that declares a library unit.
overriding_indicator
, but a library unit can never override anything. A majority of the ARG thought that allowing not overriding in that case would be confusing instead of helpful. A library unit is a program unit that is declared by a library_item
. When a program unit is a library unit, the prefix “library” is used to refer to it (or “generic library” if generic), as well as to its declaration and body, as in “library procedure”, “library package_body
”, or “generic library package”. The term compilation unit is used to refer to a compilation_unit
. When the meaning is clear from context, the term is also used to refer to the library_item
of a compilation_unit
or to the proper_body
of a subunit
[(that is, the compilation_unit
without the context_clause
and the separate (parent_unit_name
))].
with Ada.Text_IO;
package P is
...
end P;
declarative_item
). The terms “compilation_unit
”, “compilation unit”, and “subunit
” are exceptions to this rule. We considered changing “compilation_unit
”, “compilation unit” to “compilation_item
”, “compilation item”, respectively, but we decided not to. The parent declaration of a library_item
(and of the library unit) is the declaration denoted by the parent_unit_name
, if any, of the defining_program_unit_name
of the library_item
. If there is no parent_unit_name
, the parent declaration is the declaration of Standard, the library_item
is a root library_item
, and the library unit (renaming) is a root library unit (renaming). The declaration and body of Standard itself have no parent declaration. The parent unit of a library_item
or library unit is the library unit declared by its parent declaration.
[The children of a library unit occur immediately within the declarative region of the declaration of the library unit.] The ancestors of a library unit are itself, its parent, its parent's parent, and so on. [(Standard is an ancestor of every library unit.)] The descendant relation is the inverse of the ancestor relation.
A library_unit_declaration
or a library_unit_renaming_declaration
is private if the declaration is immediately preceded by the reserved word private; it is otherwise public. A library unit is private or public according to its declaration. The public descendants of a library unit are the library unit itself, and the public descendants of its public children. Its other descendants are private descendants.
library_item
is either public or private (not in relation to anything else — it's just a property of the library unit). The second concept is that a library_item
is a public descendant or private descendant of a given ancestor. A given library_item
can be a public descendant of one of its ancestors, but a private descendant of some other ancestor.subprogram_body
(as opposed to a subprogram_declaration
) is always public, since the syntax rules disallow the reserved word private on a body.package A is
private
package B is
package C is
end C;
private
end B;
end A;
For each library package_declaration
in the environment, there is an implicit declaration of a limited view of that library package. The limited view of a package contains:
- For each
package_declaration
occurring immediately within the visible part, a declaration of the limited view of that package, with the samedefining_program_unit_name
. 12.3/3 - For each
type_declaration
occurring immediately within the visible part that is not anincomplete_type_declaration
, an incomplete view of the type with nodiscriminant_part
; if thetype_declaration
is tagged, then the view is a tagged incomplete view.
type_declaration
does have one. This is necessary because semantic analysis (and the associated dependence on with_clause
s) would be necessary to determine the types of the discriminants.with_clause
s) would be needed to determine the contents of an instance. The limited view of a library package_declaration
is private if that library package_declaration
is immediately preceded by the reserved word private.
[There is no syntax for declaring limited views of packages, because they are always implicit.] The implicit declaration of a limited view of a library package [is not the declaration of a library unit (the library package_declaration
is); nonetheless, it] is a library_item
. The implicit declaration of the limited view of a library package forms an (implicit) compilation unit whose context_clause
is empty.
A library package_declaration
is the completion of the declaration of its limited view.
Legality Rules
13The parent unit of a library_item
shall be a [library] package or generic [library] package.
If a defining_program_unit_name
of a given declaration or body has a parent_unit_name
, then the given declaration or body shall be a library_item
. The body of a program unit shall be a library_item
if and only if the declaration of the program unit is a library_item
. In a library_unit_renaming_declaration
, the [(old)] name
shall denote a library_item
.
A parent_unit_name
[(which can be used within a defining_program_unit_name
of a library_item
and in the separate clause of a subunit
)], and each of its prefix
es, shall not denote a renaming_declaration
. [On the other hand, a name that denotes a library_unit_renaming_declaration
is allowed in a nonlimited_with_clause
and other places where the name of a library unit is allowed.]
If a library package is an instance of a generic package, then every child of the library package shall either be itself an instance or be a renaming of a library unit.
a)
- We want all source code that can depend on information from the private part of a library unit to be inside the "subsystem" rooted at the library unit. If an instance of a generic unit were allowed to have a noninstance as a child, the source code of that child might depend on information from the private part of the generic unit, even though it is outside the subsystem rooted at the generic unit.
b)- Disallowing noninstance children simplifies the description of the semantics of children of generic packages.
A child of a generic library package shall either be itself a generic unit or be a renaming of some other child of the same generic unit.
A child of a parent generic package shall be instantiated or renamed only within the declarative region of the parent generic.
For each child C of some parent generic package P, there is a corresponding declaration C nested immediately within each instance of P. For the purposes of this rule, if a child C itself has a child D, each corresponding declaration for C has a corresponding child D. [The corresponding declaration for a child within an instance is visible only within the scope of a with_clause
that mentions the (original) child generic unit.]
generic_formal_part
of the child, as it does for a generic child of a nongeneric unit. with_clause
. Conceptually, an instance I of P is a package that has a nested generic unit called I.C. Mentioning P.C in a with_clause
allows I.C to be instantiated. I need not be a library unit, and the instantiation of I.C need not be a library unit. If I is a library unit, and an instance of I.C is a child of I, then this instance has to be called something other than C.A library subprogram shall not override a primitive subprogram.
The defining name of a function that is a compilation unit shall not be an operator_symbol
.
Static Semantics
22A subprogram_renaming_declaration
that is a library_unit_renaming_declaration
is a renaming-as-declaration, not a renaming-as-body.
[There are two kinds of dependences among compilation units:]
- [The semantic dependences (see below) are the ones necessary to check the compile-time rules across compilation unit boundaries; a compilation unit depends semantically on the other compilation units necessary to determine its legality. The visibility rules are based on the semantic dependences.
- The elaboration dependences (see 10.2) determine the order of elaboration of
library_item
s.]
A library_item
depends semantically upon its parent declaration. A subunit depends semantically upon its parent body. A library_unit_body
depends semantically upon the corresponding library_unit_declaration
, if any. The declaration of the limited view of a library package depends semantically upon the declaration of the limited view of its parent. The declaration of a library package depends semantically upon the declaration of its limited view. A compilation unit depends semantically upon each library_item
mentioned in a with_clause
of the compilation unit. In addition, if a given compilation unit contains an attribute_reference
of a type defined in another compilation unit, then the given compilation unit depends semantically upon the other compilation unit. The semantic dependence relationship is transitive.
subprogram_declaration
. choice_parameter_specification
, then the given compilation unit depends semantically upon the declaration of Ada.Exceptions.pragma
with an argument of a type defined in another compilation unit, then the given compilation unit depends semantically upon the other compilation unit. with_clause
s, even without this rule. Hence, the rule has very little effect on programmers.with_clause
; in order to denote a declaration in one of those packages, a with_clause
will generally be needed.attribute_definition_clause
, since an expression after use will require semantic dependence upon the compilation unit containing the type_declaration
of interest.with_clause
s of the compilation_unit
that defines the package. Formally, this is achieved by saying that the limited view has an empty context_clause
. This is necessary so that they can be useful for their intended purpose: allowing mutual dependences between packages. The lack of semantic dependence limits the contents of a limited view to the items that can be determined solely from the syntax of the source of the package, without any semantic analysis. That allows it to be created without the semantic dependences of a full package. Dynamic Semantics
26.1/2The elaboration of the declaration of the limited view of a package has no effect.
compilation
can have no compilation units; for example, its text can consist of pragma
s. pragma
s cannot have any arguments that are name
s, by a previous rule of this subclause. A compilation
can even be entirely empty, which is probably not useful.- The restrictions on “early” use of a private type (RM83-7.4.1(4)) or a deferred constant (RM83-7.4.3(2)) do not apply to uses in child units, because they follow the full declaration.
- A library subprogram is never primitive, even if its profile includes a type declared immediately within the parent's
package_specification
, because the child is not declared immediately within the samepackage_specification
as the type (so it doesn't declare a new primitive subprogram), and because the child is forbidden from overriding an old primitive subprogram. It is immediately within the same declarative region, but not the samepackage_specification
. Thus, for a tagged type, it is not possible to call a child subprogram in a dispatching manner. (This is also forbidden by the freezing rules.) Similarly, it is not possible for the user to declare primitive subprograms of the types declared in the declaration of Standard, such as Integer (even if the rules were changed to allow a library unit whose name is an operator symbol). 27.f - When the parent unit is “used” the simple names of the with'd child units are directly visible (see 8.4, “Use Clauses”).
- When a parent body with's its own child, the defining name of the child is directly visible, and the parent body is not allowed to include a declaration of a homograph of the child unit immediately within the
declarative_part
of the body (RM83-8.3(17)).
library_unit_declaration
” — the former includes subprogram_body
. Also, we sometimes really mean “declaration of a view of a library unit”, which includes library_unit_renaming_declaration
s.library_unit_renaming_declaration
has to be mentioned in a with_clause
of the library_unit_renaming_declaration
. library_unit_renaming_declaration
. with_clause
. However, it is possible in obscure cases to avoid the need for a with_clause
; in particular, a compilation unit such as “package P.Q renames P;” is legal with no with_clause
s (though not particularly interesting). ASCII is physically nested in Standard, and so is not a library unit, and cannot be renamed as a library unit. designator
of a library function cannot be an operator_symbol
, but a nonlibrary renaming_declaration
is allowed to rename a library function as an operator. Within a partition, two library subprograms are required to have distinct names and hence cannot overload each other. However, renaming_declaration
s are allowed to define overloaded names for such subprograms, and a locally declared subprogram is allowed to overload a library subprogram. The expanded name Standard.L can be used to denote a root library unit L (unless the declaration of Standard is hidden) since root library unit declarations occur immediately within the declarative region of package Standard. Examples
29Examples of library units:
package Rational_Numbers.IO is -- public child of Rational_Numbers, see 7.1
procedure Put(R : in Rational);
procedure Get(R : out Rational);
end Rational_Numbers.IO;
31private procedure Rational_Numbers.Reduce(R : in out Rational);
-- private child of Rational_Numbers
32with Rational_Numbers.Reduce; -- refer to a private child
package body Rational_Numbers is
...
end Rational_Numbers;
33with Rational_Numbers.IO; use Rational_Numbers;
with Ada.Text_io; -- see A.10
procedure Main is -- a root library procedure
R : Rational;
begin
R := 5/3; -- construct a rational number, see 7.1
Ada.Text_IO.Put("The answer is: ");
IO.Put(R);
Ada.Text_IO.New_Line;
end Main;
34with Rational_Numbers.IO;
package Rational_IO renames Rational_Numbers.IO;
-- a library unit renaming declaration
35Each of the above library_item
s can be submitted to the compiler separately.
generic
type Element is private;
with function Image(E : Element) return String;
package Generic_Bags is
type Bag is limited private; -- A bag of Elements.
procedure Add(B : in out Bag; E : Element);
function Bag_Image(B : Bag) return String;
private
type Bag is ...;
end Generic_Bags;
35.cgeneric
package Generic_Bags.Generic_Iterators is
... -- various additional operations on Bags.
35.dgeneric
with procedure Use_Element(E : in Element);
-- Called once per bag element.
procedure Iterate(B : in Bag);
end Generic_Bags.Generic_Iterators;
with Generic_Bags;
with Generic_Bags.Generic_Iterators;
package My_Abstraction is
type My_Type is ...;
function Image(X : My_Type) return String;
package Bags_Of_My_Type is new Generic_Bags(My_Type, Image);
package Iterators_Of_Bags_Of_My_Type is new Bags_Of_My_Type.Generic_Iterators;
end My_Abstraction;
with_clause
makes that nested unit visible.with Generic_Bags.Generic_Iterators;
package body Generic_Bags is
procedure Add(B : in out Bag; E : Element) is ... end Add;
35.jpackage Iters is new Generic_Iterators;
35.kfunction Bag_Image(B : Bag) return String is
Buffer : String(1..10_000);
Last : Integer := 0;
35.lprocedure Append_Image(E : in Element) is
Im : constant String := Image(E);
begin
if Last /= 0 then -- Insert a comma.
Last := Last + 1;
Buffer(Last) := ',';
end if;
Buffer(Last+1 .. Last+Im'Length) := Im;
Last := Last + Im'Length;
end Append_Image;
35.mprocedure Append_All is new Iters.Iterate(Append_Image);
begin
Append_All(B);
return Buffer(1..Last);
end Bag_Image;
end Generic_Bags;
Extensions to Ada 83
library_item
is modified to allow the reserved word private before a library_unit_declaration
.Wording Changes from Ada 83
Extensions to Ada 95
limited_with_clause
s (see 10.1.2), they facilitate construction of mutually recursive types in multiple packages. Wording Changes from Ada 95
Wording Changes from Ada 2005
10.1.2 Context Clauses - With Clauses
1[A context_clause
is used to specify the library_item
s whose names are needed within a compilation unit.]
Language Design Principles
context_clause
without looking ahead. Similarly, when compiling a context_clause
, the compiler should not have to look ahead at subsequent context_item
s, nor at the compilation unit to which the context_clause
is attached. (We have not completely achieved this.)with_clause
on some compilation unit on which the unit depends, directly or indirectly. We try to avoid ripple effects because they make understanding and maintenance more difficult. However, ripple effects can occur because of direct visibility (as in child units); this seems impossible to eliminate. The ripple effect for with_clause
s is somewhat similar to the Beaujolais effect (see 8.4) for use_clause
s, which we also try to avoid. Syntax
2context_clause
::=
{context_item
}
3context_item
::=
with_clause
| use_clause
4/2with_clause
::=
limited_with_clause
| nonlimited_with_clause
4.1/2limited_with_clause
::=
limited [private] with library_unit_name
{, library_unit_name
};
4.2/2nonlimited_with_clause
::=
[private] with library_unit_name
{, library_unit_name
};
with_clause
containing the reserved word private is called a private with_clause. It can be thought of as making items visible only in the private part, although it really makes items visible everywhere except the visible part. It can be used both for documentation purposes (to say that a unit is not used in the visible part), and to allow access to private units that otherwise would be prohibited. Name Resolution Rules
5The 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].
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
.with_clause
also affects visibility within subsequent use_clause
s and pragma
s of the same context_clause
, even though those are not in the scope of the with_clause
. A library_item
(and the corresponding library unit) is named in a with_clause
if it is denoted by a library_unit_name
in the with_clause
. A library_item
(and the corresponding library unit) is mentioned in a with_clause
if it is named in the with_clause
or if it is denoted by a prefix
in the with_clause
.
With_clause
s 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 nonroot library unit makes its declaration visible. See Clause 8 for details.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. (This is not exactly equivalent because the latter with_clause
names A and A.B, while the previous one does not. Whether a unit is “named” does not have any effect on visibility, however, so it is equivalent for visibility purposes.)[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
8/2If a with_clause
of a given compilation_unit
mentions a private child of some library unit, then the given compilation_unit
shall be one of:
- the declaration, body, or subunit of a private descendant of that library unit;
- 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); or
- the declaration of a public descendant of that library unit, in which case the
with_clause
shall include the reserved word private.
with_clause
. context_clause
s 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;
11.epackage A.B is
end A.B;
11.fprivate package A.B.C is
end A.B.C;
11.gpackage A.B.C.D is
end A.B.C.D;
11.hwith A.B.C; -- (1)
private package A.B.X is
end A.B.X;
11.ipackage A.B.Y is
end A.B.Y;
11.jwith A.B.C; -- (2)
package body A.B.Y is
end A.B.Y;
11.j.1/2private with A.B.C; -- (3)
package A.B.Z is
end A.B.Z;
with_clause
. 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;”. 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_clause
s of a 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; 15/5 - a private descendant of U or its body ; or
- a pragma within a context clause.
with_clause
s that mention the name include the reserved word private. They do not apply if the name is mentioned in any with_clause
that does not include private. library_item
visible anywhere that is not visible outside the subsystem rooted at the compilation_unit
having the private with_clause
, including private parts of packages nested in the visible part, private parts of child packages, the visible part of private children, and context clause pragmas like Elaborate_All.with_clause
not include the visible part. However, that rule would mean that moving a declaration between the visible part and the private part could change its meaning from one legal interpretation to a different legal interpretation. For example: package A is
function B return Integer;
end A;
16.e/2function B return Integer;
16.f/2with A;
private with B;
package C is
use A;
V1 : Integer := B; -- (1)
private
V2 : Integer := B; -- (2)
end C;
[A library_item
mentioned in a limited_with_clause
shall be the implicit declaration of the limited view of a library package, not the declaration of a subprogram, generic unit, generic instance, or a renaming.]
limited_with_clause
. See 10.1.6. A limited_with_clause
shall not appear on a library_unit_body
, subunit
, or library_unit_renaming_declaration
.
limited_with_clause
on a library_unit_renaming_declaration
because it would be useless and therefore probably is a mistake. A renaming cannot appear in a limited_with_clause
(by the rule prior to this one), and a renaming of a limited view cannot appear in a nonlimited_with_clause
(because the name would not be within the scope of a with_clause
denoting the package, see 8.5.3). Nor could it be the parent of another unit. That doesn't leave anywhere that the name of such a renaming could appear, so we simply make writing it illegal. A limited_with_clause
that names a library package shall not appear:
- in the
context_clause
for the explicit declaration of the named library package or any of its descendants;
limited with P;
package P is ...
limited private with P.Child;
package P is ...
limited with P;
package P.Child is ...
- within a
context_clause
for alibrary_item
that is within the scope of anonlimited_with_clause
that mentions the same library package; or
nonlimited_with_clause
s found in the same context_clause
, as well as nonlimited_with_clause
s found on parent units. limited_with_clause
could have no effect, and would be confusing. If a nonlimited_with_clause
for the same package is inherited from a parent unit or given in the context_clause
, the full view is available, which strictly provides more information than the limited view. - within a
context_clause
for alibrary_item
that is within the scope of ause_clause
that names an entity declared within the declarative region of the library package.
use_clause
s found in the same context_clause
, as well as use_clause
s found in (or on) parent units. limited_with_clause
cannot be useful, as we must have the full view available in the parent in order for the use_clause
to be legal. library_item
mentioned in a nonlimited_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_clause
s 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 nonlimited_with_clause
, then the corresponding declaration nested within each visible instance is visible within the compilation unit. Similarly, a library_item
mentioned in a limited_with_clause
of a compilation unit is visible within the compilation unit and thus can be used to form expanded names.with_clause
s 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_clause
s, or even within a given with_clause
.with_clause
mentions a library_unit_renaming_declaration
, it only “mentions” the prefix
es 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. Examples
24/5Examples of use of with clauses, limited with clauses, and private with clauses:
package Office is
end Office;
26/2with Ada.Strings.Unbounded;
package Office.Locations is
type Location is new Ada.Strings.Unbounded.Unbounded_String;
end Office.Locations;
27/2limited with Office.Departments; -- types are incomplete
private with Office.Locations; -- only visible in private part
package Office.Employees is
type Employee is private;
28/2function Dept_Of(Emp : Employee) return access Departments.Department;
procedure Assign_Dept(Emp : in out Employee;
Dept : access Departments.Department);
29/2...
private
type Employee is
record
Dept : access Departments.Department;
Loc : Locations.Location;
...
end record;
end Office.Employees;
30/5limited with Office.Employees;
package Office.Departments is
type Department is ... ;
31/2function Manager_Of(Dept : Department) return access Employees.Employee;
procedure Assign_Manager(Dept : in out Department;
Mgr : access Employees.Employee);
...
end Office.Departments;
32/5The limited_with_clause
can be used to support mutually dependent abstractions that are split across multiple packages. In this case, an employee is assigned to a department, and a department has a manager who is an employee. If a with_clause
with the reserved word private appears on one library unit and mentions a second library unit, it provides visibility to the second library unit, but restricts that visibility to the private part and body of the first unit. The compiler checks that no use is made of the second unit in the visible part of the first unit.
Extensions to Ada 83
with_clause
is modified to allow expanded name notation.Wording Changes from Ada 83
context_clause
is modified to more closely reflect the semantics. The Ada 83 syntax rule implies that the use_clause
s 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.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.use_clause
s. Their semantics are fully covered by the “scope (of a use_clause
)” definition in 8.4. Incompatibilities With Ada 95
Extensions to Ada 95
limited_with_clause
s are new. They make a limited view of a package visible, where all of the types in the package are incomplete. They facilitate construction of mutually recursive types in multiple packages.with_clause
are modified to allow the reserved word private. Private with_clause
s do not allow the use of their library_item
in the visible part of their compilation_unit
. They also allow using private units in more locations than in Ada 95. Incompatibilities With Ada 2005
Wording Changes from Ada 2005
context_clause
is “within the scope of” something, as context_clause
s are never included in anything's scope. The intended meaning is unchanged, however.Wording Changes from Ada 2012
10.1.3 Subunits of Compilation Units
1[Subunits are like child units, with these (important) differences: subunits support the separate compilation of bodies only (not declarations); the parent contains a body_stub
to indicate the existence and place of each of its subunits; declarations appearing in the parent's body can be visible within the subunits.]
Syntax
2body_stub
::=
subprogram_body_stub
| package_body_stub
| task_body_stub
| protected_body_stub
3/3subprogram_body_stub
::=
[overriding_indicator
]
subprogram_specification
is separate
[aspect_specification
];
parent_unit_name
, that is disallowed by 10.1.1, “Compilation Units - Library Units”. package_body_stub
::=
package body defining_identifier
is separate
[aspect_specification
];
5/3task_body_stub
::=
task body defining_identifier
is separate
[aspect_specification
];
6/3protected_body_stub
::=
protected body defining_identifier
is separate
[aspect_specification
];
7subunit
::=
separate (parent_unit_name
) proper_body
Legality Rules
8/2The parent body of a subunit is the body of the program unit denoted by its parent_unit_name
. The term subunit is used to refer to a subunit
and also to the proper_body
of a subunit
. The subunits of a program unit include any subunit that names that program unit as its parent, as well as any subunit that names such a subunit as its parent (recursively).
The parent body of a subunit shall be present in the current environment, and shall contain a corresponding body_stub
with the same defining_identifier
as the subunit.
A package_body_stub
shall be the completion of a package_declaration
or generic_package_declaration
; a task_body_stub
shall be the completion of a task declaration; a protected_body_stub
shall be the completion of a protected declaration.
In contrast, a subprogram_body_stub
can be defined without it being the completion of a previous declaration, [in which case the _stub
declares the subprogram]. If the _stub
is a completion, it shall be the completion of a subprogram_declaration
or generic_subprogram_declaration
. The profile of a subprogram_body_stub
that completes a declaration shall conform fully to that of the declaration.
subprogram_body_stub
s echoes the corresponding rule for subprogram_bodies
in 6.3, “Subprogram Bodies”. A subunit that corresponds to a body_stub
shall be of the same kind (package_
, subprogram_
, task_
, or protected_
) as the body_stub
. The profile of a subprogram_body
subunit shall be fully conformant to that of the corresponding body_stub
.
A body_stub
shall appear immediately within the declarative_part
of a compilation unit body. This rule does not apply within an instance of a generic unit.
The defining_identifier
s of all body_stub
s that appear immediately within a particular declarative_part
shall be distinct.
Post-Compilation Rules
16For each body_stub
, there shall be a subunit containing the corresponding proper_body
.
body_stub
is equivalent to the corresponding proper_body
. This implies: - Visibility within a subunit is the visibility that would be obtained at the place of the corresponding
body_stub
(within the parent body) if thecontext_clause
of the subunit were appended to that of the parent body.
library_item
that is mentioned in a with_clause
of a subunit can be hidden (from direct visibility) by a declaration (with the same identifier
) given in the subunit. Moreover, such a library_item
can even be hidden by a declaration given within the parent body since a library unit is declared in its parent's declarative region; this however does not affect the interpretation of the with_clause
s themselves, since only library_item
s are visible or directly visible in with_clause
s.Examples
20/5Example that defines package Parent without subunits:
package Parent is
procedure Inner;
end Parent;
22with Ada.Text_IO;
package body Parent is
Variable : String := "Hello, there.";
procedure Inner is
begin
Ada.Text_IO.Put_Line(Variable);
end Inner;
end Parent;
23/5Example showing how the body of procedure Inner can be turned into a subunit by rewriting the package body as follows (with the declaration of Parent remaining the same):
package body Parent is
Variable : String := "Hello, there.";
procedure Inner is separate;
end Parent;
25with Ada.Text_IO;
separate(Parent)
procedure Inner is
begin
Ada.Text_IO.Put_Line(Variable);
end Inner;
Extensions to Ada 83
Extensions to Ada 95
Wording Changes from Ada 95
Extensions to Ada 2005
10.1.4 The Compilation Process
1Each compilation unit submitted to the compiler is compiled in the context of an environment declarative_part
(or simply, an environment), which is a conceptual declarative_part
that forms the outermost declarative region of the context of any compilation
. At run time, an environment forms the declarative_part
of the body of the environment task of a partition (see 10.2, “Program Execution”).
declarative_part
, since there might, for example, be bodies that do not yet exist. The declarative_item
s of the environment are library_item
s appearing in an order such that there are no forward semantic dependences. Each included subunit occurs in place of the corresponding stub. The visibility rules apply as if the environment were the outermost declarative region, except that with_clause
s are necessary to make declarations of library units visible (see 10.1.2).
The mechanisms for creating an environment and for adding and replacing compilation units within an environment are implementation defined. The mechanisms for adding a compilation unit mentioned in a limited_with_clause
to an environment are implementation defined.
limited_with_clause
to an environment.Name Resolution Rules
4/3{8652/0032} If a library_unit_body
that is a subprogram_body
is submitted to the compiler, it is interpreted only as a completion if a library_unit_declaration
with the same defining_program_unit_name
already exists in the environment for a subprogram other than an instance of a generic subprogram or for a generic subprogram (even if the profile of the body is not type conformant with that of the declaration); otherwise, the subprogram_body
is interpreted as both the declaration and body of a library subprogram.
subprogram_body
should be interpreted as only a completion if and only if it “might” be legal as the completion of some preexisting declaration, where “might” is defined in a way that does not require overload resolution to determine.subprogram_declaration
or generic_subprogram_declaration
, we treat the new subprogram_body
as its completion, because it “might” be legal. If it turns out that the profiles don't fully conform, it's an error. In all other cases (the preexisting declaration is a package or a generic package, or an instance of a generic subprogram, or a renaming, or a “spec-less” subprogram, or in the case where there is no preexisting thing), the subprogram_body
declares a new subprogram.Legality Rules
5When a compilation unit is compiled, all compilation units upon which it depends semantically shall already exist in the environment; the set of these compilation units shall be consistent in the sense that the new compilation unit shall not semantically depend (directly or indirectly) on two different versions of the same compilation unit, nor on an earlier version of itself.
Implementation Permissions
6/2The implementation may require that a compilation unit be legal before it can be mentioned in a limited_with_clause
or it can be inserted into the environment.
When a compilation unit that declares or renames a library unit is added to the environment, the implementation may remove from the environment any preexisting library_item
or subunit
with the same full expanded name. When a compilation unit that is a subunit or the body of a library unit is added to the environment, the implementation may remove from the environment any preexisting version of the same compilation unit. When a compilation unit that contains a body_stub
is added to the environment, the implementation may remove any preexisting library_item
or subunit
with the same full expanded name as the body_stub
. When a given compilation unit is removed from the environment, the implementation may also remove any compilation unit that depends semantically upon the given one. If the given compilation unit contains the body of a subprogram for which aspect Inline is True, the implementation may also remove any compilation unit containing a call to that subprogram.
with_clause
s are attached to the new compilation unit that triggered all this.compilation
and compilation unit boundaries, just as they are enforced within a single compilation unit. library_item
s. If multiple libraries are supported, the implementation can document how a single environment is constructed when a compilation unit is submitted to the compiler. Naming conflicts between different libraries can, for example, be resolved by treating each library as the root of a hierarchy of child library units. Extensions to Ada 83
Wording Changes from Ada 95
subprogram_body
is not considered a completion of an instance of a generic subprogram.limited_with_clause
were added to several rules; limited views have the same presence in the environment as the corresponding full views. 10.1.5 Pragmas and Program Units
1/5[This subclause discusses pragmas related to compilation
s.]
Name Resolution Rules
2/5
Legality Rules
3/5
- {8652/0033}
Paragraphs 2 through 7 were moved to Annex J, “Obsolescent Features”.
Static Semantics
7.1/5{8652/0034}
Post-Compilation Rules
8Certain pragma
s are defined to be configuration pragmas; they shall appear before the first compilation_unit
of a compilation
. [They are generally used to select a partition-wide or system-wide option.] The pragma
applies to all compilation_unit
s appearing in the compilation
, unless there are none, in which case it applies to all future compilation_unit
s compiled into the same environment.
Implementation Permissions
9/2An implementation may require that configuration pragmas that select partition-wide or system-wide options be compiled when the environment contains no library_item
s other than those of the predefined environment. In this case, the implementation shall still accept configuration pragmas in individual compilations that confirm the initially selected partition-wide or system-wide options.
Implementation Advice
10/5{8652/0034}
Paragraph 10 was moved to Annex J, “Obsolescent Features”.
Wording Changes from Ada 95
Wording Changes from Ada 2005
Wording Changes from Ada 2012
pragma
s that use these terms are now in that annex. 10.1.6 Environment-Level Visibility Rules
1[The normal visibility rules do not apply within a parent_unit_name
or a context_clause
, nor within a pragma
that appears at the place of a compilation unit. The special visibility rules for those contexts are given here.]
Static Semantics
2/2Within the parent_unit_name
at the beginning of an explicit library_item
, and within a nonlimited_with_clause
, the only declarations that are visible are those that are explicit library_item
s of the environment, and the only declarations that are directly visible are those that are explicit root library_item
s of the environment. Within a limited_with_clause
, the only declarations that are visible are those that are the implicit declaration of the limited view of a library package of the environment, and the only declarations that are directly visible are those that are the implicit declaration of the limited view of a root library package.
limited_with_clause
, while only compilation units defining full views (that is, the explicit declarations) can be mentioned in a nonlimited_with_clause
. This resolves the conflict inherent in having two compilation units with the same defining name. Within a use_clause
or pragma
that is within a context_clause
, each library_item
mentioned in a previous with_clause
of the same context_clause
is visible, and each root library_item
so mentioned is directly visible. In addition, within such a use_clause
, if a given declaration is visible or directly visible, each declaration that occurs immediately within the given declaration's visible part is also visible. No other declarations are visible or directly visible.
with_clause
on a declaration mentions X, this does not make X visible in use_clause
s and pragma
s that are on the body. The reason for this rule is the one-pass context_clause
s Language Design Principle.Within the parent_unit_name
of a subunit, library_item
s are visible as they are in the parent_unit_name
of a library_item
; in addition, the declaration corresponding to each body_stub
in the environment is also visible.
subprogram_declaration
, the body_stub
itself is the declaration. Within a pragma
that appears at the place of a compilation unit, the immediately preceding library_item
and each of its ancestors is visible. The ancestor root library_item
is directly visible.
Notwithstanding the rules of 4.1.3, an expanded name in a with_clause
, a pragma
in a context_clause
, or a pragma
that appears at the place of a compilation unit may consist of a prefix
that denotes a generic package and a selector_name
that denotes a child of that generic package. [(The child is necessarily a generic unit; see 10.1.1.)]
Wording Changes from Ada 83
parent_unit_name
or a context_clause
, and within a pragma
that appears at the place of a compilation_unit
are clarified.context_clause
is not part of any declarative region.parent_unit_name
s and context_clause
s follow from the context of compilation. However, this attempt failed for various reasons. For example, it would require use_clause
s in context_clause
s to be within the declarative region of Standard, which sounds suspiciously like a kludge. And we would still need a special rule to prevent seeing things (in our own context_clause
) that were with-ed by our parent, etc. Wording Changes from Ada 95
limited_with_clause
s; the existing rules apply only to nonlimited_with_clause
s.