The visibility rules
given below, determine which declarations are visible and directly visible
at each place within a program. The visibility rules apply to both explicit
and implicit declarations.]
declaration is defined to be directly visible
at places where
of only an identifier
is sufficient to denote the declaration; that is, no selected_component
notation or special context (such as preceding => in a named association)
is necessary to denote the declaration.
is defined to be visible
wherever it is directly visible, as well
as at other places where some name
(such as a selected_component
can denote the declaration.
The syntactic category direct_name
is used to indicate contexts where direct visibility is required. The
syntactic category selector_name
is used to indicate contexts where visibility, but not direct visibility,
two kinds of direct visibility: immediate visibility
A declaration is immediately visible at a place if
it is directly visible because the place is within its immediate scope.
A declaration is use-visible if it is directly visible
because of a use_clause
). Both conditions can apply.
A declaration can be hidden
either from direct visibility, or from all visibility, within certain
parts of its scope.
Where hidden from all visibility
it is not visible at all (neither using a direct_name
nor a selector_name
Where hidden from direct visibility
direct visibility is lost; visibility using a selector_name
is still possible.
Two or more declarations are
if they all have the same defining name and there is
a place where they are all directly visible.]
Note that a name
can have more than one possible interpretation even if it denotes a nonoverloadable
entity. For example, if there are two functions F that return records,
both containing a component called C, then the name F.C has two possible
interpretations, even though component declarations are not overloadable.
The declarations of callable
entities [(including enumeration literals)] are overloadable
meaning that overloading is allowed for them].
is not overloadable within its own generic_formal_part
This follows from the rules about when a name
denotes a current instance. See AI83-00286. This implies that within
outer declarations with the same defining name are hidden from direct
visibility. It also implies that if a generic formal parameter has the
same defining name as the generic itself, the formal parameter hides
the generic from direct visibility.
Two declarations are homographs
if they have the same defining name, and, if both are overloadable, their
profiles are type conformant.
[An inner declaration
hides any outer homograph from direct visibility.]
Term entry: overriding
operation — an operation that replaces an inherited primitive
Note: Operations can be marked explicitly as overriding or not overriding.
[Two homographs are not generally allowed immediately within the same
declarative region unless one overrides
the other (see Legality
The only declarations that are overridable
are the implicit declarations for predefined operators and inherited
primitive subprograms. A declaration overrides another homograph that
occurs immediately within the same declarative region in the following
A declaration that is not overridable overrides one that is overridable,
[regardless of which declaration occurs first];
The “regardless of which declaration occurs
first” is there because the explicit declaration could be a primitive
subprogram of a partial view, and then the full view might inherit a
homograph. We are saying that the explicit one wins (within its scope),
even though the implicit one comes later.
If the overriding declaration is also a subprogram,
then it is a primitive subprogram.
As explained in 7.3.1
”, some inherited
primitive subprograms are never declared. Such subprograms cannot be
overridden, although they can be reached by dispatching calls in the
case of a tagged type.
The implicit declaration of an inherited operator
overrides that of a predefined operator;
Ramification: In a previous version of
Ada 9X, we tried to avoid the notion of predefined operators, and say
that they were inherited from some magical root type. However, this seemed
like too much mechanism. Therefore, a type can have a predefined "+"
as well as an inherited "+". The above rule says the inherited
The “regardless of which declaration occurs first” applies
here as well, in the case where derived_type_definition
in the visible part of a public library unit derives from a private type
declared in the parent unit, and the full view of the parent type has
additional predefined operators, as explained in 7.3.1
”. Those predefined
operators can be overridden by inherited subprograms implicitly declared
An implicit declaration of an inherited subprogram
overrides a previous implicit declaration of an inherited subprogram.
If two or more homographs are implicitly declared at the same place:
If at least one is a subprogram that is neither a null procedure nor
an abstract subprogram, and does not require overriding (see 3.9.3
then they override those that are null procedures, abstract subprograms,
or require overriding. If more than one such homograph remains that is
not thus overridden, then they are all hidden from all visibility.
Otherwise (all are null procedures, abstract subprograms, or require
overriding), then any null procedure overrides all abstract subprograms
and all subprograms that require overriding; if more than one such homograph
remains that is not thus overridden, then if the
profiles of the remaining homographs they
are all fully conformant with one another, one is chosen arbitrarily;
if not, they are all hidden from all visibility.
In the case where the implementation arbitrarily chooses one overrider
from among a group of inherited subprograms, users should not be able
to determine which member was chosen, as the set of inherited subprograms
which are chosen from must be fully conformant. This rule is needed in
order to allow
package Outer is
package P1 is
type Ifc1 is interface;
procedure Null_Procedure (X : Ifc1) is null;
procedure Abstract_Subp (X : Ifc1) is abstract;
package P2 is
type Ifc2 is interface;
procedure Null_Procedure (X : Ifc2) is null;
procedure Abstract_Subp (X : Ifc2) is abstract;
type T is abstract new P1.Ifc1 and P2.Ifc2 with null record;
without requiring that T explicitly override
any of its inherited operations.
Full conformance is required here, as we cannot
allow the parameter names to differ. If they did differ, the routine
which was selected for overriding could be determined by using named
parameter notation in a call.
When the subprograms do not conform, we chose not to adopt the “use
clause” rule which would make them all visible resulting in likely
ambiguity. If we had used such a rule, any successful calls would be
confusing; and the fact that there are no Beaujolais-like effects effect
to worry about means we can consider other rules. The hidden-from-all-visibility
homographs are still inherited by further derivations, which avoids order-of-declaration
dependencies and other anomalies.
We have to be careful to not include arbitrary
selection if the routines have real bodies. (This can happen in generics,
see the example in the incompatibilities section below.) We don't want
the ability to successfully call routines where the body executed depends
on the compiler or a phase of the moon.
Note that if the type is concrete, abstract
subprograms are inherited as subprograms that require overriding. We
include functions that require overriding as well; these don't have real
bodies, so they can use the more liberal rules.
[For an implicit declaration of a primitive subprogram
in a generic unit, there is a copy of this declaration in an instance.]
However, a whole new set of primitive subprograms is implicitly declared
for each type declared within the visible part of the instance. These
new declarations occur immediately after the type declaration, and override
the copied ones. [The copied ones can be called only from within the
instance; the new ones can be called only from outside the instance,
although for tagged types, the body of a new one can be executed by a
call to an old one.]
In addition, this is also
stated redundantly (again), and is repeated, in 12.3
”. The rationale
for the rule is explained there.
To be honest:
The implicit subprograms declared when an operation of a progenitor is
implemented by an entry or subprogram also override the appropriate implicitly
declared inherited operations of the progenitor.
declaration is visible within its scope, except where hidden from all
visibility, as follows:
An overridden declaration is
hidden from all visibility within the scope of the overriding declaration.
Ramification: We have to talk about the
scope of the overriding declaration, not its visibility, because it hides
even when it is itself hidden.
declaration is hidden from all visibility until the end of the declaration,
For a record type or record extension,
the declaration is hidden from all visibility only until the reserved
We're talking about the
of the construct itself, here, not some random is
might appear in a generic_formal_part
For a task declaration or protected declaration, the declaration is hidden
from all visibility only until the reserved word with
of the declaration
if there is one, or the reserved word is
of the declaration if
there is no with
To be honest: If there is neither a with
nor is, then the exception does not apply and the name is hidden
from all visibility until the end of the declaration. This oddity was
inherited from Ada 95.
We need the “with
” rule so that the visibility within an interface_list
does not vary by construct. That would make it harder to complete private
extensions and would complicate implementations.
This rule means, for example,
that within the scope of a full_type_declaration
that completes a private_type_declaration
the name of the type will denote the full_type_declaration
and therefore the full view of the type. On the other hand, if the completion
is not a declaration, then it doesn't hide anything, and you can't denote
The declaration of a library unit (including a library_unit_renaming_declaration
is hidden from all visibility at places outside its declarative region
that are not within the scope of a nonlimited_with_clause
that mentions it. The limited view of a library package is hidden from
all visibility at places that are not within the scope of a limited_with_clause
that mentions it; in addition, the limited view is hidden from all visibility
within the declarative region of the package, as well as within the scope
of any nonlimited_with_clause
that mentions the package. Where the declaration of the limited view
of a package is visible, any name that denotes the package denotes the
limited view, including those provided by a package renaming.
This is the rule that prevents with_clause
from being transitive; the [immediate] scope includes indirect semantic
dependents. This rule also prevents the limited view of a package from
being visible in the same place as the full view of the package, which
prevents various ripple effects.
[For each declaration or renaming of a generic unit as a child of some
parent generic package, there is a corresponding declaration nested immediately
within each instance of the parent.] Such a nested declaration is hidden
from all visibility except at places that are within the scope of a with_clause
that mentions the child.
A declaration is hidden from
direct visibility within the immediate scope of a homograph of the declaration,
if the homograph occurs within an inner declarative region;
A declaration is also hidden
from direct visibility where hidden from all visibility.
Name Resolution Rules
"The same as" has
the obvious meaning here, so for +, the possible interpretations are
declarations whose defining name is "+" (an operator_symbol
Direct visibility is irrelevant
In terms of overload resolution character_literal
are similar to other literals, like null
— see 4.2
there is no need to worry about hiding, since there is no way to declare
A nonoverridable declaration is illegal if there is a homograph occurring
immediately within the same declarative region that is visible at the
place of the declaration, and is not hidden from all visibility by the
nonoverridable declaration. In addition, a type extension is illegal
if somewhere within its immediate scope it has two visible components
with the same name. Similarly, the context_clause
for a compilation unit is illegal if it mentions (in a with_clause
some library unit, and there is a homograph of the library unit that
is visible at the place of the compilation unit, and the homograph and
the mentioned library unit are both declared immediately within the same
These rules also apply to dispatching
operations declared in the visible part of an instance of a generic unit.
However, they do not apply to other overloadable declarations in an instance[;
such declarations may have type conformant profiles in the instance,
so long as the corresponding declarations in the generic were not type
Normally, these rules just mean you can't explicitly declare two
homographs immediately within the same declarative region. The wording
is designed to handle the following special cases:
If the second declaration completes the first
one, the second declaration is legal.
If the body
of a library unit contains an explicit homograph of a child of that same
library unit, this is illegal only if the body mentions the child in
or if some subunit mentions the child. Here's an example:
package P is
package P.Q is
package body P is
Q : Integer; -- OK; we cannot see package P.Q here.
procedure Sub is separate;
procedure Sub is -- Illegal.
If package body P said "with
P.Q;", then it would be illegal to declare the homograph Q: Integer.
But it does not, so the body of P is OK. However, the subunit would be
able to see both P.Q's, and is therefore illegal.
A previous version of Ada 9X allowed
the subunit, and said that references to P.Q would tend to be ambiguous.
However, that was a bad idea, because it requires overload resolution
to resolve references to directly visible nonoverloadable homographs,
which is something compilers have never before been required to do.
If a type extension contains a component with the same name as a component
in an ancestor type, there must be no place where both components are
visible. For instance:
package A is
type T is tagged private;
package B is
type NT is new T with record
I: Integer; -- Illegal because T.I is visible in the body.
end record; -- T.I is not visible here.
type T is tagged record
I: Integer; -- Illegal because T.I is visible in the body.
-- T.I becomes visible here.
package A.C is
type NT2 is new A.T with record
I: Integer; -- Illegal because T.I is visible in the private part.
end record; -- T.I is not visible here.
-- T.I is visible here.
package D is
type NT3 is new A.T with record
I: Integer; -- Legal because T.I is never visible in this package.
package A.E is
type NT4 is new D.NT3 with null record;
X : NT4;
I1 : Integer := X.I; -- D.NT3.I
I2 : Integer := D.NT3(X).I; -- D.NT3.I
I3 : Integer := A.T(X).I; -- A.T.I
D.NT3 can have a component I because the component I of the parent type
is never visible. The parent component exists, of course, but is never
declared for the type D.NT3. In the child package A.E, the component
I of A.T is visible, but that does not change the fact that the A.T.I
component was never declared for type D.NT3. Thus, A.E.NT4 does not (visibly)
inherit the component I from A.T, while it does inherit the component
I from D.NT3. Of course, both components exist, and can be accessed by
a type conversion as shown above. This behavior stems from the fact that
every characteristic of a type (including components) must be declared
somewhere in the innermost declarative region containing the type —
if the characteristic is never visible in that declarative region, it
is never declared. Therefore, such characteristics do not suddenly become
available even if they are in fact visible in some other scope. See 7.3.1
for more on the rules.
It is illegal to mention both an explicit child of an instance, and a
child of the generic from which the instance was instantiated. This is
easier to understand with an example:
package G1 is
package G1.G2 is
package I1 is new G1;
package I1.G2 renames ...
with I1.G2; -- Illegal
package Bad is ...
The context clause for Bad is illegal as I1 has an implicit declaration
of I1.G2 based on the generic child G1.G2, as well as the mention of
the explicit child I1.G2. As in the previous cases, this is illegal only
if the context clause makes both children visible; the explicit child
can be mentioned as long as the generic child is not (and vice -
Note that we need to be careful which things
we make "hidden from all visibility" versus which things we
make simply illegal for names to denote. The distinction is subtle. The
rules that disallow names denoting components within a type declaration
) do not make the components invisible
at those places, so that the above rule makes components with the same
name illegal. The same is true for the rule that disallows names denoting
formal parameters within a formal_part
Discussion: The part about instances
is from AI83-00012. The reason it says “overloadable declarations”
is because we don't want it to apply to type extensions that appear in
an instance; components are not overloadable.
NOTE 2 In addition to the visibility
rules given above, the meaning of the occurrence of a direct_name
at a given place in the text can depend on the overloading rules (see
A defining name.
that appear after the reserved word end
in a proper_body
Similarly for “end loop
specific to a pragma used in a pragma argument.
specific to an aspect used in an aspect_definition
The visibility rules have nothing to do with
the above cases; the meanings of such things are defined elsewhere. Reserved
words are not identifier
the visibility rules don't apply to them either.
Because of the way we have defined "declaration",
it is possible for a usage name to denote a subprogram_body
either within that body, or (for a nonlibrary unit) after it (since the
body hides the corresponding declaration, if any). Other bodies do not
work that way. Completions of type_declaration
and deferred constant declarations do work that way. Accept_statement
are never denoted, although the parameter_specification
in their profiles can be.
The scope of a
subprogram does not start until after its profile. Thus, the following
X : constant Integer := 17;
package P is
procedure X(Y : in Integer := X);
The body of the subprogram will probably be
illegal, however, since the constant X will be hidden by then.
The rule is different
for generic subprograms, since they are not overloadable; the following
X : constant Integer := 17;
package P is
Z : Integer := X; -- Illegal!
procedure X(Y : in Integer := X); -- Illegal!
The constant X is hidden from direct visibility
by the generic declaration.
Extensions to Ada 83
Declarations with the same
defining name as that of a subprogram or entry being defined are nevertheless
visible within the subprogram specification or entry declaration.
Wording Changes from Ada 83
The term “visible by selection”
is no longer defined. We use the terms “directly visible”
and “visible” (among other things). There are only two regions
of text that are of interest, here: the region in which a declaration
is visible, and the region in which it is directly visible.
Visibility is defined only for declarations.
Incompatibilities With Ada 95
Added rules to handle the inheritance and overriding
of multiple homographs for a single type declaration, in order to support
multiple inheritance from interfaces. The new rules are intended to be
compatible with the existing rules so that programs that do not use interfaces
do not change their legality. However, there is a very rare case where
this is not true:
type T1 is private;
type T2 is private;
package G is
type T is null record;
procedure P (X : T; Y : T1);
procedure P (X : T; Z : T2);
package I is new G (Integer, Integer); -- Exports homographs of P.
type D is new I.T; -- Both Ps are inherited.
Obj : D;
P (Obj, Z => 10); -- Legal in Ada 95, illegal in Ada 2005.
The call to P would resolve in Ada 95 by using
the parameter name, while the procedures P would be hidden from all visibility
in Ada 2005 and thus would not resolve. This case doesn't seem worth
making the rules any more complex than they already are.
is illegal if it would create a homograph of an implicitly declared generic
child (see 10.1.1
). An Ada 95 compiler could
have allowed this, but which unit of the two units involved would be
denoted wasn't specified, so any successful use isn't portable. Removing
one of the two with_clause
involved will fix the problem.
Wording Changes from Ada 95
Clarified that is it never possible for two components
with the same name to be visible; any such program is illegal.
Wording Changes from Ada 2005
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe