Contents   Index   Search   Previous   Next

8.3 Visibility

   [{visibility rules} 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

   {visibility (direct)} {directly visible} {directly visible} 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. {visible} 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.
   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.
   {visibility (immediate)} {visibility (use clause)} There are two kinds of direct visibility: immediate visibility and use-visibility. {immediately visible} A declaration is immediately visible at a place if it is directly visible because the place is within its immediate scope. {use-visible} A declaration is use-visible if it is directly visible because of a use_clause (see 8.4). Both conditions can apply.
   {hiding} A declaration can be hidden, either from direct visibility, or from all visibility, within certain parts of its scope. {hidden from all visibility} Where hidden from all visibility, it is not visible at all (neither using a direct_name nor a selector_name). {hidden from direct visibility} Where hidden from direct visibility, only direct visibility is lost; visibility using a selector_name is still possible.
   [{overloaded} 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.]
Ramification: Note that a name can have more than one possible interpretation even if it denotes a non-overloadable 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.
   {overloadable} The declarations of callable entities [(including enumeration literals)] are overloadable[, meaning that overloading is allowed for them].
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.
   {homograph} Two declarations are homographs if they have the same defining name, and, if both are overloadable, their profiles are type conformant. {type conformance [partial]} [An inner declaration hides any outer homograph from direct visibility.]
     {8652/0025} [Two homographs are not generally allowed immediately within the same declarative region unless one overrides the other (see Legality Rules below).] {override} The only declarations that are {overridable} 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:
Ramification: {8652/0025} And regardless of whether the non-overriddable explicit declaration is overloadable or not. For example, statement_identifiers are covered by this rule.
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, ``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.
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.
The ``regardless of which declaration occurs first'' applies here as well, in the case where derived_type_declaration 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.
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.
    {visible} {hidden from all visibility [distributed]} A declaration is visible within its scope, except where hidden from all visibility, as follows:
Ramification: We have to talk about the scope of the overriding declaration, not its visibility, because it hides even when it is itself hidden.
Note that the scope of an explicit subprogram_declaration does not start until after its profile.
Ramification: We're talking about the is of the construct itself, here, not some random is that might appear in a generic_formal_part.
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.
Discussion: This is the rule that prevents with_clauses from being transitive; the [immediate] scope includes indirect semantic dependents.
    {directly visible} {immediately visible} {visibility (direct)} {visibility (immediate)} A declaration with a defining_identifier or defining_operator_symbol is immediately visible [(and hence directly visible)] within its immediate scope {hidden from direct visibility [distributed]} except where hidden from direct visibility, as follows:

Name Resolution Rules

    {possible interpretation (for direct_names) [partial]} A direct_name shall resolve to denote a directly visible declaration whose defining name is the same as the direct_name. {possible interpretation (for selector_names) [partial]} A selector_name shall resolve to denote a visible declaration whose defining name is the same as the selector_name.
Discussion: "The same as" has the obvious meaning here, so for +, the possible interpretations are declarations whose defining name is "+" (an operator_symbol).
    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''.
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

      {8652/0025} {8652/0026} A non-overridable An explicit 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 non-overridable explicit 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 subunit 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 corresponding stub, and the homograph and the mentioned library unit are both declared immediately within the same declarative region. {generic contract issue [partial]} 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]. {type conformance [partial]}
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:
package P is
end P;
package P.Q is
end P.Q;
package body P is
    Q : Integer; -- OK; we cannot see package P.Q here.
    procedure Sub is separate;
end P;
with P.Q;
procedure Sub is -- Illegal.
end Sub;
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;
   type T is tagged record
      I: Integer; -- Illegal because T.I is visible in the body.
   end record;
end A;
package A is
package body A is
   package body B is
      -- T.I becomes visible here.
   end B;
end A;
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.
end A.C;
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;
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;
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).
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.
5  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.
6  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).
7  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.
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:
A defining name.
The identifiers or operator_symbol that appear after the reserved word end in a proper_body. Similarly for ``end loop'', etc.
An attribute_designator.
A pragma identifier.
A pragma_argument_identifier.
An identifier specific to a pragma used in a pragma argument.
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.
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 non-library unit) after it (since the body hides the corresponding declaration, if any). Other bodies do not work that way. Completions of type_ and deferred_constant_declarations do work that way. Accept_statements are never denoted, although the parameter_specifications in their profiles can be.
The scope of a subprogram does not start until after its profile. Thus, the following is legal:
X : constant Integer := 17;
package P is
    procedure X(Y : in Integer := X);
end P;
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 is illegal:
X : constant Integer := 17;
package P is
      Z : Integer := X; -- Illegal!
    procedure X(Y : in Integer := X); -- Illegal!
end P;
The constant X is hidden from direct visibility by the generic declaration.

Extensions to Ada 83

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

Contents   Index   Search   Previous   Next   Legal