Ada Conformity Assessment Authority      Home Conformity Assessment   Test Suite ARGAda Standard
Annotated Ada Reference ManualLegal Information
Contents   Index   References   Search   Previous   Next 

10.1.1 Compilation Units - Library Units

[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. 
Ramification: Standard is a library unit.


compilation ::= {compilation_unit}
compilation_unit ::= 
    context_clause library_item
  | context_clause subunit
library_item ::= [privatelibrary_unit_declaration
  | library_unit_body
  | [privatelibrary_unit_renaming_declaration
library_unit_declaration ::= 
     subprogram_declaration | package_declaration
   | generic_declaration | generic_instantiation
library_unit_renaming_declaration ::= 
 | generic_renaming_declaration
 | subprogram_renaming_declaration
library_unit_body ::= subprogram_body | package_body
parent_unit_name ::= name
{AI95-00397-01} An overriding_indicator is not allowed in a subprogram_declaration, generic_instantiation, or subprogram_renaming_declaration that declares a library unit.
Reason: All of the listed items syntactically include 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))].
Discussion: In this example: 
with Ada.Text_IO;
package P is
end P;
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.
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.
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.] 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. 
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 declaration.” 
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
Discussion: 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 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.
A subprogram declared by a subprogram_body (as opposed to a subprogram_declaration) is always public, since the syntax rules disallow the reserved word private on a body.
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 package. 
Ramification: 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
        end C;
    end B;
end A;
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.) 
   {AI95-00217-06} 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:
{AI95-00217-06} {AI05-0129-1} {AI05-0262-1} For each package_declaration occurring immediately within the visible part, a declaration of the limited view of that package, with the same defining_program_unit_name.
{AI95-00217-06} {AI95-00326-01} {AI05-0108-1} {AI05-0129-1} {AI05-0262-1} For each type_declaration occurring immediately within the visible part that is not an incomplete_type_declaration, an incomplete view of the type with no discriminant_part; if the type_declaration is tagged, then the view is a tagged incomplete view. 
Reason: {AI05-0108-1} 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_clauses) would be necessary to determine the types of the discriminants.
{AI05-0129-1} 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. 
Discussion: {AI95-00217-06} 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 of units. 
Ramification: The limited view does not include package instances and their contents. Semantic analysis of a unit (and dependence on its with_clauses) 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.
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.

Legality Rules

The 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.
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. 
 {AI95-00217-06} 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 prefixes, 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. 
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. 
Reason: Instances 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. 
 {AI05-0004-1} 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.
 {AI95-00331-01} 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.]
Implementation Note: 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. 
Ramification: 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 subprogram. 
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. 

Static Semantics

A 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 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 (see 10.2) determine the order of elaboration of library_items.]
Discussion: Don't confuse these kinds of dependences with the run-time dependences among tasks and masters defined in 9.3, “Task Dependence - Termination of Tasks”. 
 {AI95-00217-06} 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.
Discussion: 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 of Ada.Exceptions.
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 unit. 
Discussion: For example, a compilation unit containing X'Address depends semantically upon the declaration of package System.
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_clauses, 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.
Note that no special rule is needed for an attribute_definition_clause, since an expression after use will require semantic dependence upon the compilation unit containing the type_declaration of interest.
{AI95-00217-06} Unlike a full view of a package, a limited view does not depend semantically on units mentioned in with_clauses 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

   {AI95-00217-06} The elaboration of the declaration of the limited view of a package has no effect. 
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 of pragmas.
Ramification: Such pragmas cannot have any arguments that are names, 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 ramifications: 
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 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 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)). 
Note that “declaration of a library unit” is different from “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_declarations.
The visibility rules generally imply that the renamed view of a library_unit_renaming_declaration has to be mentioned in a with_clause of the library_unit_renaming_declaration.
To be honest: The real rule is that the renamed library unit has to be visible in the library_unit_renaming_declaration.
Reason: 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.Q renames P;” is legal with no with_clauses (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. 
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_declarations 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 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;
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
end Rational_Numbers;
with Rational_Numbers.IO; use Rational_Numbers;
with Ada.Text_io;               -- see A.10
procedure Main is               -- a root library procedure
   R : Rational;
   R := 5/3;                    -- construct a rational number, see 7.1
   Ada.Text_IO.Put("The answer is: ");
end Main;
with Rational_Numbers.IO;
package Rational_IO renames Rational_Numbers.IO;
                                -- a library unit renaming declaration
Each of the above library_items can be submitted to the compiler separately. 
Discussion: 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 ...;
end Generic_Bags;
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);
end Generic_Bags.Generic_Iterators;
A package that instantiates the above generic units: 
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;
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: 
with Generic_Bags.Generic_Iterators;
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) := ',';
         end if;
         Buffer(Last+1 .. Last+Im'Length) := Im;
         Last := Last + Im'Length;
      end Append_Image;
      procedure Append_All is new Iters.Iterate(Append_Image);
      return Buffer(1..Last);
   end Bag_Image;
end Generic_Bags;

Extensions to Ada 83

The syntax rule for library_item is modified to allow the reserved word private before a library_unit_declaration.
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

{AI95-00217-06} The concept of a limited view is new. Combined with limited_with_clauses (see 10.1.2), they facilitate construction of mutually recursive types in multiple packages. 

Wording Changes from Ada 95

{AI95-00331-01} Clarified the wording so that a grandchild generic unit will work as expected. 

Wording Changes from Ada 2005

{AI05-0108-1} {AI05-0129-1} Correction: Clarified the wording so that it is clear that limited views of types never have discriminants and never are of incomplete types.

Contents   Index   References   Search   Previous   Next 
Ada-Europe Ada 2005 and 2012 Editions sponsored in part by Ada-Europe