10.1.1 Compilation Units - Library Units
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.]
library unit is a child
of its parent unit. The root
units are the children of the predefined library package Standard.
Ramification: Standard is a library unit.
parent_unit_name ::= name
All of the listed items syntactically
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.
In this example:
package P is
the term “compilation unit” can
refer to this text: “with Ada.Text_IO; package P
is ... end P;” or to this text: “package
P is ... end P;”. We use this shorthand because it
corresponds to common usage.
We like to use the word “unit” for
declaration-plus-body things, and “item” for declaration
or body separately (as in 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.
Discussion: The declaration and body
of Standard are presumed to exist from the beginning of time, as it were.
There is no way to actually write them, since there is no syntactic way
to indicate lack of a parent. An attempt to compile a package Standard
would result in Standard.Standard.
Reason: Library units (other than Standard)
have “parent declarations” and “parent units”.
Subunits have “parent bodies”. We didn't bother to define
the other possibilities: parent body of a library unit, parent declaration
of a subunit, parent unit of a subunit. These are not needed, and might
get in the way of a correct definition of “child.”
[The children of a library unit occur immediately
within the declarative region of the declaration of the library unit.]
of a library unit are itself,
its parent, its parent's parent, and so on. [(Standard is an ancestor
of every library unit.)]
is the inverse of the ancestor relation.
Reason: These definitions are worded
carefully to avoid defining subunits as children. Only library units
can be children.
We use the unadorned term “ancestors”
here to concisely define both “ancestor unit” and “ancestor
or a library_unit_renaming_declaration
if the declaration is immediately preceded by the reserved
; it is otherwise public
. A library unit is
private or public according to its declaration.
of a library unit are the library unit itself,
and the public descendants of its public children.
other descendants are private descendants
The first concept defined
here is that a 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
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.
Note that a private library unit is a public
descendant of itself, but a private descendant of its parent.
This is because it is visible outside itself — its privateness
means that it is not visible outside its parent.
Private children of Standard are legal, and
follow the normal rules. It is intended that implementations might have
some method for taking an existing environment, and treating it as a
package to be “imported” into another environment, treating
children of Standard in the imported environment as children of the imported
Suppose we have a public library unit A, a private library unit A.B,
and a public library unit A.B.C. A.B.C is a public descendant of itself
and of A.B, but a private descendant of A; since A.B is private to A,
we don't allow A.B.C to escape outside A either. This is similar to the
situation that would occur with physical nesting, like this:
package A is
package B is
package C is
Here, A.B.C is visible outside itself and outside
A.B, but not outside A. (Note that this example is intended to illustrate
the visibility of program units from the outside; the visibility within
child units is not quite identical to that of physically nested units,
since child units are nested after their parent's declaration.)
For each library package_declaration
in the environment, there is an implicit declaration of a limited
of that library package.
The limited view
of a package contains:
The incomplete view of a type does not have a discriminant_part even
if the type_declaration
does have one. This is necessary because semantic analysis (and the associated
dependence on with_clause
would be necessary to determine the types of the discriminants.
No incomplete views of incomplete types are included in the limited view.
The rules of 3.10.1
ensure that the completion
of any visible incomplete type is declared in the same visible part,
so such an incomplete view would simply be redundant.
The implementation model of a limited view is that it can be determined
solely from the syntax of the source of the unit, without any semantic
analysis. That allows it to be created without the semantic dependences
of a full unit, which is necessary for it to break mutual dependences
The limited view does not
include package instances and their contents. Semantic analysis of a
unit (and dependence on its with_clause
would be needed to determine the contents of an instance.
[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
To be honest:
This is notwithstanding
the rule in 3.11.1
that says that implicit
declarations don't have completions.
Reason: This rule explains where to find
the completions of the incomplete views defined by the limited view.
The parent unit of a library_item
shall be a [library] package or generic [library] package.
Discussion: We could have allowed nested
program units to be children of other program units; their semantics
would make sense. We disallow them to keep things simpler and because
they wouldn't be particularly useful.
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.
Discussion: A child of an instance of
a given generic unit will often be an instance of a (generic) child of
the given generic unit. This is not required, however.
are forbidden from having noninstance children for two reasons:
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.
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
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.]
Within the child,
like anything nested in a generic unit, one can make up-level references
to the current instance of its parent, and thereby gain access to the
formal parameters of the parent, to the types declared in the parent,
etc. This “nesting” model applies even within the generic_formal_part
of the child, as it does for a generic child of a nongeneric unit.
Suppose P is a generic
library package, and P.C is a generic child of P. P.C can be instantiated
inside the declarative region of P. Outside P, P.C can be mentioned only
in a 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
Reason: This prevents certain obscure
anomalies. For example, if a library subprogram were to override a subprogram
declared in its parent package, then in a compilation unit that depends
indirectly on the library subprogram, the library subprogram could
hide the overridden operation from all visibility, but the library subprogram
itself would not be visible.
Note that even without this rule, such subprograms
would be illegal for tagged types, because of the freezing rules.
The defining name of a function that is a compilation
unit shall not be an operator_symbol
Reason: Since overloading is not permitted
among compilation units, it seems unlikely that it would be useful to
define one as an operator. Note that a subunit could be renamed within
its parent to be an operator.
[There are two kinds
of dependences among compilation units:]
[The semantic dependences (see below) are
the ones needed to check the compile-time rules across compilation unit
boundaries; a compilation unit depends semantically on the other compilation
units needed to determine its legality. The visibility rules are based
on the semantic dependences.
The elaboration dependences
determine the order of elaboration of 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
mentioned in a with_clause
of the compilation unit. In addition, if a given compilation unit contains
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.
The “if any”
in the third sentence is necessary because library subprograms are not
required to have a subprogram_declaration
To be honest:
If a given compilation
unit contains a choice_parameter_specification
then the given compilation unit depends semantically upon the declaration
If a given compilation unit contains a pragma
with an argument of a type defined in another compilation unit, then
the given compilation unit depends semantically upon the other compilation
Discussion: For example, a compilation
unit containing X'Address depends semantically upon the declaration of
For the Address attribute, this fixes a hole
in Ada 83. Note that in almost all cases, the dependence will need to
exist due to with_clause
even without this rule. Hence, the rule has very little effect on programmers.
Note that the semantic dependence does not have
the same effect as a with_clause
in order to denote a declaration in one of those packages, a with_clause
will generally be needed.
Unlike a full view of a package, a limited view does not depend semantically
on units mentioned in with_clause
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.
The elaboration of the declaration of the limited view of a package has
1 A simple program may consist of a single
compilation unit. A compilation
need not have any compilation units; for example, its text can consist
cannot have any arguments that are name
by a previous rule of this subclause. A compilation
can even be entirely empty, which is probably not useful.
Some interesting properties of the three kinds
of dependence: The elaboration dependences also include the semantic
dependences, except that subunits are taken together with their parents.
The semantic dependences partly determine the order in which the compilation
units appear in the environment at compile time. At run time, the order
is partly determined by the elaboration dependences.
The model whereby
a child is inside its parent's declarative region, after the parent's
declaration, as explained in 8.1
, has the following
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
because the child is not declared immediately within the same package_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 same package_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).
When the parent unit is “used”
the simple names of the with'd child units are directly visible (see
, “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)).
In most cases, “has to
be visible” means there has to be a 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;” is legal with no with_clause
(though not particularly interesting). ASCII is physically nested in
Standard, and so is not a library unit, and cannot be renamed as a library
2 The 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
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
Examples of library
-- public child of Rational_Numbers, see 7.1
Put(R : in
Get(R : out
private procedure Rational_Numbers.Reduce(R : in out Rational);
-- private child of Rational_Numbers
with Rational_Numbers.Reduce; -- refer to a private child
package body Rational_Numbers is
Ada.Text_io; -- see A.10
-- a root library procedure
R : Rational;
R := 5/3; -- construct a rational number, see 7.1
Ada.Text_IO.Put("The answer is: ");
package Rational_IO renames Rational_Numbers.IO;
-- a library unit renaming declaration
Each of the above library_item
can be submitted to the compiler separately.
Example of a generic package with children:
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;
type Bag is ...;
package Generic_Bags.Generic_Iterators is
... -- various additional operations on Bags.
with procedure Use_Element(E : in Element);
-- Called once per bag element.
procedure Iterate(B : in Bag);
that instantiates the above generic units:
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;
In the above example, Bags_Of_My_Type has a
nested generic unit called Generic_Iterators. The second with_clause
makes that nested unit visible.
Here we show how
the generic body could depend on one of its own children:
package body Generic_Bags is
procedure Add(B : in out Bag; E : Element) is ... end Add;
package Iters is new Generic_Iterators;
function Bag_Image(B : Bag) return String is
Buffer : String(1..10_000);
Last : Integer := 0;
procedure Append_Image(E : in Element) is
Im : constant String := Image(E);
if Last /= 0 then -- Insert a comma.
Last := Last + 1;
Buffer(Last) := ',';
Buffer(Last+1 .. Last+Im'Length) := Im;
Last := Last + Im'Length;
procedure Append_All is new Iters.Iterate(Append_Image);
Extensions to Ada 83
Children (other than children of Standard) are
new in Ada 95.
Library unit renaming is new in Ada 95.
Wording Changes from Ada 83
Standard is considered a library unit in Ada
95. This simplifies the descriptions, since it implies that the parent
of each library unit is a library unit. (Standard itself has no parent,
of course.) As in Ada 83, the language does not define any way to recompile
Standard, since the name given in the declaration of a library unit is
always interpreted in relation to Standard. That is, an attempt to compile
a package Standard would result in Standard.Standard.
Extensions to Ada 95
Wording Changes from Ada 95
Clarified the wording so that a grandchild generic unit will work as
Wording Changes from Ada 2005
Clarified the wording so that it is clear that limited
views of types never have discriminants and never are of incomplete types.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe