Skip to main content

8.3 Visibility

danger

This Reference Manual output has not been verified, and may contain omissions or errors. Report any problems on the tracking issue

1

[ 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.]

Static Semantics

2

A declaration is defined to be directly visible at places where a name consisting of only an identifier or operator_symbol 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. A 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.

3

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, is required.

4

There are two kinds of direct visibility: immediate visibility and use-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 (see 8.4). Both conditions can apply.

5

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, only direct visibility is lost; visibility using a selector_name is still possible.

6

[ Two or more declarations are overloaded if they all have the same defining name and there is a place where they are all directly visible.]

6.a
ramification

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.

7

The declarations of callable entities [(including enumeration literals)] are overloadable[, meaning that overloading is allowed for them].

7.a
ramification

A generic_declaration 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 a generic_formal_part, 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.

8

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.]

8.a/5

Term entry: overriding operation — operation that replaces an inherited primitive operation
Note: Operations can be marked explicitly as overriding or not overriding.

9/1

{8652/0025} [Two homographs are not generally allowed immediately within the same declarative region unless one overrides the other (see Legality Rules below).] 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 cases:

10/1
  • {8652/0025} A declaration that is not overridable overrides one that is overridable, [regardless of which declaration occurs first];
10.a/1
ramification

{8652/0025} And regardless of whether the nonoverridable declaration is overloadable or not. For example, statement_identifiers are covered by this rule.

10.b

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.

10.c

If the overriding declaration is also a subprogram, then it is a primitive subprogram.

10.d

As explained in 7.3.1, “Private Operations”, 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.

11
  • The implicit declaration of an inherited operator overrides that of a predefined operator;
11.a
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 one wins.

11.b/2

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, “Private Operations”. Those predefined operators can be overridden by inherited subprograms implicitly declared earlier.

12
  • An implicit declaration of an inherited subprogram overrides a previous implicit declaration of an inherited subprogram.
  • 12.1/2
  • If two or more homographs are implicitly declared at the same place:
12.2/2
  • 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.
  • 12.3/5
  • 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 are all fully conformant with one another, one is chosen arbitrarily; if not, they are all hidden from all visibility.
12.a/2
discussion

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

12.b/2

package Outer is package P1 is type Ifc1 is interface; procedure Null_Procedure (X : Ifc1) is null; procedure Abstract_Subp (X : Ifc1) is abstract; end P1; 12.c/2 package P2 is type Ifc2 is interface; procedure Null_Procedure (X : Ifc2) is null; procedure Abstract_Subp (X : Ifc2) is abstract; end P2; 12.d/2 type T is abstract new P1.Ifc1 and P2.Ifc2 with null record; end Outer;

12.e/2

without requiring that T explicitly override any of its inherited operations.

12.f/2

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.

12.g/5

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 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.

12.h/2

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.

12.i/2

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.

13
  • [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.]
13.a
discussion

In addition, this is also stated redundantly (again), and is repeated, in 12.3, “Generic Instantiation”. The rationale for the rule is explained there.

13.b/3

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.

14

A declaration is visible within its scope, except where hidden from all visibility, as follows:

15
  • An overridden declaration is hidden from all visibility within the scope of the overriding declaration.
15.a
ramification

We have to talk about the scope of the overriding declaration, not its visibility, because it hides even when it is itself hidden.

15.b

Note that the scope of an explicit subprogram_declaration does not start until after its profile.

16
  • A declaration is hidden from all visibility until the end of the declaration, except:
17
18.a
ramification

We're talking about the is of the construct itself, here, not some random is that might appear in a generic_formal_part.

18.1/2
  • 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.
18.b/2

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.

18.c/2
reason

We need the “with or is” 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.

19
19.a
ramification

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 it.

20/2
  • 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.
20.a/2
discussion

This is the rule that prevents with_clauses 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.

20.1/2
  • [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.
21

A declaration with a defining_identifier or defining_operator_symbol is immediately visible [(and hence directly visible)] within its immediate scope except where hidden from direct visibility, as follows:

22
  • 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;
  • 23
  • A declaration is also hidden from direct visibility where hidden from all visibility.
23.1/3

An attribute_definition_clause or an aspect_specification is visible everywhere within its scope.

Name Resolution Rules

24

A direct_name shall resolve to denote a directly visible declaration whose defining name is the same as the direct_name. A selector_name shall resolve to denote a visible declaration whose defining name is the same as the selector_name.

24.a
discussion

"The same as" has the obvious meaning here, so for +, the possible interpretations are declarations whose defining name is "+" (an operator_symbol).

25

These rules on visibility and direct visibility do not apply in a context_clause, a parent_unit_name, or a pragma that appears at the place of a compilation_unit. For those contexts, see the rules in 10.1.6, “Environment-Level Visibility Rules”.

25.a
ramification

Direct visibility is irrelevant for character_literals. In terms of overload resolution character_literals are similar to other literals, like null — see 4.2. For character_literals, there is no need to worry about hiding, since there is no way to declare homographs.

Legality Rules

26/2

{8652/0025} {8652/0026} 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 declarative region. 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 conformant].

26.a
discussion

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:

26.b
  • If the second declaration completes the first one, the second declaration is legal.
  • 26.c
  • 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 its context_clause, or if some subunit mentions the child. Here's an example:
26.d

package P is end P; 26.e package P.Q is end P.Q; 26.f package body P is Q : Integer; -- OK; we cannot see package P.Q here. procedure Sub is separate; end P; 26.g with P.Q; separate(P) procedure Sub is -- Illegal. begin null; end Sub;

26.h
  • 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.
  • 26.i
  • 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.
  • 26.i.1/1
  • {8652/0026} {8652/0102} 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:
26.i.2/1

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. end B; private type T is tagged record I: Integer; -- Illegal because T.I is visible in the body. end record; end A; 26.i.3/2

package body A is package body B is -- T.I becomes visible here. end B; end A; 26.i.4/1 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. private -- T.I is visible here. end A.C; 26.i.5/1 with A; package D is type NT3 is new A.T with record I: Integer; -- Legal because T.I is never visible in this package. end record; end D; 26.i.6/1 with D; 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 end A.E;

26.i.7/1
  • {8652/0102} 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.
  • 26.i.8/2
  • 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:
26.i.9/2

generic package G1 is end G1; 26.i.10/2 generic package G1.G2 is end G1.G2; 26.i.11/2 with G1; package I1 is new G1; 26.i.12/2 package I1.G2 renames ... 26.i.13/2 with G1.G2; with I1.G2; -- Illegal package Bad is ...

26.i.14/5
  • 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 versa).
26.j

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 (see 3.7) 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 (see 6.1).

26.k
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.

27

NOTE 1 Visibility for compilation units follows from the definition of the environment in 10.1.4, except that it is necessary to apply a with_clause to obtain visibility to a library_unit_declaration or library_unit_renaming_declaration.

28

NOTE 2 In addition to the visibility rules given above, the meaning of the occurrence of a direct_name or selector_name at a given place in the text can depend on the overloading rules (see 8.6).

29

NOTE 3 Not all contexts where an identifier, character_literal, or operator_symbol are allowed require visibility of a corresponding declaration. Contexts where visibility is not required are identified by using one of these three syntactic categories directly in a syntax rule, rather than using direct_name or selector_name.

29.a
ramification

An identifier, character_literal or operator_symbol that occurs in one of the following contexts is not required to denote a visible or directly visible declaration:

29.b

1.
A defining name.
29.c

2.
The identifiers or operator_symbol that appear after the reserved word end in a proper_body. Similarly for “end loop”, etc.
29.d

3.
An attribute_designator.
29.e

4.
A pragma identifier.
29.f

5.
A pragma_argument_identifier.
29.g

6.
An identifier specific to a pragma used in a pragma argument.
29.g.1/3

7.
An aspect_mark;
29.g.2/3

8.
An identifier specific to an aspect used in an aspect_definition.
29.h

The visibility rules have nothing to do with the above cases; the meanings of such things are defined elsewhere. Reserved words are not identifiers; the visibility rules don't apply to them either.

29.i

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_declarations and deferred constant declarations do work that way. Accept_statements are never denoted, although the parameter_specifications in their profiles can be.

29.j

The scope of a subprogram does not start until after its profile. Thus, the following is legal:

29.k

X : constant Integer := 17; ... package P is procedure X(Y : in Integer := X); end P;

29.l

The body of the subprogram will probably be illegal, however, since the constant X will be hidden by then.

29.m

The rule is different for generic subprograms, since they are not overloadable; the following is illegal:

29.n

X : constant Integer := 17; package P is generic Z : Integer := X; -- Illegal! procedure X(Y : in Integer := X); -- Illegal! end P;

29.o

The constant X is hidden from direct visibility by the generic declaration.

Extensions to Ada 83

29.p

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

29.q

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.

29.r

Visibility is defined only for declarations.

Incompatibilities With Ada 95

29.s/2

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:

29.t/2

generic 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); end G;] 29.u/2 package I is new G (Integer, Integer); -- Exports homographs of P. 29.v/2 type D is new I.T; -- Both Ps are inherited. 29.w/2 Obj : D; 29.x/2 P (Obj, Z => 10); -- Legal in Ada 95, illegal in Ada 2005.

29.y/2

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.

29.z/2
correction

Amendment A with_clause 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_clauses involved will fix the problem.

Wording Changes from Ada 95

29.aa/2

{8652/0025} Corrigendum: Clarified the overriding rules so that "/=" and statement_identifiers are covered.

29.bb/2

{8652/0026} Corrigendum: Clarified that is it never possible for two components with the same name to be visible; any such program is illegal.

29.cc/2

The visibility of an attribute_definition_clause is defined so that it can be used by the stream attribute availability rules (see 13.13.2).

29.dd/2

The visibility of a limited view of a library package is defined (see 10.1.1).

Wording Changes from Ada 2005

29.ee/4

Added wording so that the parameters of an expression_function_declaration are visible in the return expression of the function. (It would be pretty useless without such a rule.)

29.ff/3

The visibility of an aspect_specification is defined so that it can be used in various other rules.

8.3.1 Overriding Indicators

1/2

An overriding_indicator is used to declare that an operation is intended to override (or not override) an inherited operation.

Syntax

2/2

overriding_indicator ::= [not] overriding

Legality Rules

3/3

If an abstract_subprogram_declaration, null_procedure_declaration, expression_function_declaration, subprogram_body, subprogram_body_stub, subprogram_renaming_declaration, generic_instantiation of a subprogram, or subprogram_declaration other than a protected subprogram has an overriding_indicator, then:

4/2
  • the operation shall be a primitive operation for some type;
  • 5/2
  • if the overriding_indicator is overriding, then the operation shall override a homograph at the place of the declaration or body;
5.a/3

To be honest: This doesn't require that the overriding happen at precisely the place of the declaration or body; it only requires that the region in which the overriding is known to have happened includes this place. That is, the overriding can happen at or before the place of the declaration or body.

6/2
  • if the overriding_indicator is not overriding, then the operation shall not override any homograph (at any place).
7/2

In addition to the places where Legality Rules normally apply, these rules also apply in the private part of an instance of a generic unit.

7.a/2
discussion

The overriding and not overriding rules differ slightly. For overriding, we want the indicator to reflect the overriding state at the place of the declaration; otherwise the indicator would be “lying”. Whether a homograph is implicitly declared after the declaration (see 7.3.1 to see how this can happen) has no impact on this check. However, not overriding is different; “lying” would happen if a homograph declared later actually is overriding. So, we require this check to take into account later overridings. That can be implemented either by looking ahead, or by rechecking when additional operations are declared.

7.b/2

The “no lying” rules are needed to prevent a subprogram_declaration and subprogram_body from having contradictory overriding_indicators.

8/2

NOTE Rules for overriding_indicators of task and protected entries and of protected subprograms are found in 9.5.2 and 9.4, respectively.

Examples

9/5

Example of use of an overriding indicator when declaring a security queue derived from the Queue interface of 3.9.4:

10/2

type Security_Queue is new Queue with record ...; 11/2 overriding procedure Append(Q : in out Security_Queue; Person : in Person_Name); 12/5

overriding procedure Remove_First(Q : in out Security_Queue; Person : out Person_Name); 13/2 overriding function Cur_Count(Q : in Security_Queue) return Natural; 14/2 overriding function Max_Count(Q : in Security_Queue) return Natural; 15/2 not overriding procedure Arrest(Q : in out Security_Queue; Person : in Person_Name);

16/5

The first four subprogram declarations guarantee that these subprograms will override the four subprograms inherited from the Queue interface. A misspelling in one of these subprograms will be detected at compile time by the implementation. Conversely, the declaration of Arrest guarantees that this is a new operation.

16.a/2
discussion

In this case, the subprograms are abstract, so misspellings will get detected anyway. But for other subprograms (especially when deriving from concrete types), the error might never be detected, and a body other than the one the programmer intended might be executed without warning. Thus our new motto: “Overriding indicators — don't derive a type without them!”

Extensions to Ada 95

16.b/2

Overriding_indicators are new. These let the programmer state her overriding intentions to the compiler; if the compiler disagrees, an error will be produced rather than a hard to find bug.

Wording Changes from Ada 2005

16.c/3

Expression functions can have overriding indicators.