8.5.4 Subprogram Renaming Declarations
Ramification: A renaming-as-body is a
declaration, as defined in Clause
3.
Syntax
Name Resolution Rules
Legality Rules
{
AI05-0239-1}
{
AI12-0373-1}
The profile of a renaming-as-declaration shall be mode conformant with
that of the renamed callable entity.
{
AI12-0287-1}
if the
callable_entity_name
statically denotes a generic formal subprogram of a generic unit
G,
and the
subprogram_renaming_declaration
occurs within the body of a generic unit
G or within the body
of a generic unit declared within the declarative region of the generic
unit
G, then the corresponding parameter or result subtype of
the formal subprogram of
G shall have a
null_exclusion;
otherwise, the subtype of the corresponding parameter
or result type of the renamed callable entity shall exclude null.
In
addition to the places where Legality Rules normally apply (see
12.3),
this rule applies also in the private part of an instance of a generic
unit.
Reason: This
rule prevents “lying”.
Null must never be the value
of a parameter or result with an explicit
null_exclusion.
The first bullet is an assume-the-worst rule which prevents trouble in
generic bodies (including bodies of child units) when the formal subtype
excludes null implicitly.
{
8652/0027}
{
8652/0028} {
AI95-00135-01}
{
AI95-00145-01}
{
AI05-0239-1}
The profile of a renaming-as-body shall conform fully to that of the
declaration it completes.
If the renaming-as-body
completes that declaration before the subprogram it declares is frozen,
the profile shall be mode conformant
with that of
the renamed callable entity and the subprogram it declares takes its
convention from the renamed subprogram; otherwise, the profile shall
be subtype conformant with that of the renamed callable entity and the
convention of the renamed subprogram shall not be Intrinsic.
A
renaming-as-body is illegal if the declaration occurs before the subprogram
whose declaration it completes is frozen, and the renaming renames the
subprogram itself, through one or more subprogram renaming declarations,
none of whose subprograms has been frozen.
Reason: The otherwise part of the second
sentence is to allow an implementation of a renaming-as-body as a single
jump instruction to the target subprogram. Among other things, this prevents
a subprogram from being completed with a renaming of an entry. (In most
cases, the target of the jump can be filled in at link time. In some
cases, such as a renaming of a name like "A(I).all",
an indirect jump is needed. Note that the name is evaluated at renaming
time, not at call time.)
{
8652/0028}
{
AI95-00145-01}
The first part of the second sentence is intended to allow renaming-as-body
of predefined operators before the
subprogram_declaration
is frozen. For some types (such as integer types), the parameter type
for operators is the base type, and it would be very strange for
function Equal (A, B : in T) return
Boolean;
function Equal (A, B : in T) return
Boolean renames "=";
to be illegal. (Note that predefined operators cannot be renamed this
way after the
subprogram_declaration
is frozen, as they have convention Intrinsic.)
The syntax rules prevent a protected subprogram
declaration from being completed by a renaming. This is fortunate, because
it allows us to avoid worrying about whether the implicit protected object
parameter of a protected operation is involved in the conformance rules.
Reason: {
8652/0027}
{
AI95-00135-01}
Circular renames before freezing is illegal, as the compiler would not
be able to determine the convention of the subprogram. Other circular
renames are handled below; see Bounded (Run-Time) Errors.
{
AI95-00228-01}
The
callable_entity_name
of a renaming shall not denote a subprogram that requires overriding
(see
3.9.3).
Reason: {
AI95-00228-01}
Such a rename cannot be of the inherited subprogram (which requires overriding
because it cannot be called), and thus cannot squirrel away a subprogram
(see below). That would be confusing, so we make it illegal. The renaming
is allowed after the overriding, as then the
name
will denote the overriding subprogram, not the inherited one.
{
AI95-00228-01}
The
callable_entity_name
of a renaming-as-body shall not denote an abstract subprogram.
Reason: {
AI95-00228-01}
Such a subprogram has no body, so it hardly can replace one in the program.
{
AI12-0204-1}
If the
callable_entity_name
of a renaming is a prefixed view, the prefix of that view shall denote
an object for which renaming is allowed.
Reason: {
AI12-0204-1}
The prefix in such a case is essentially renamed and passed to any calls
of the renamed subprogram. If the prefix isn't legal to rename, that
doesn't make sense (and allowing it might end up passing a nonexistent
object to some calls).
Reason: This
is to prevent things like this:
function F(X : Integer) return Integer renames Table(X).all;
A similar
rule in
6.1 forbids things like this:
function F(X : Integer; Y : Integer := X) return Integer;
Static Semantics
A renaming-as-declaration declares a new view of
the renamed entity. The profile of this new view takes its subtypes,
parameter modes, and calling convention from the original profile of
the callable entity, while taking the formal parameter
names
and
default_expressions
from the profile given in the
subprogram_renaming_declaration.
The new view is a function or procedure, never an entry.
To be honest: When renaming an entry
as a procedure, the compile-time rules apply as if the new view is a
procedure, but the run-time semantics of a call are that of an entry
call.
Ramification: For example, it is illegal
for the
entry_call_statement
of a
timed_entry_call
to call the new view. But what looks like a procedure call will do things
like barrier waiting.
{
8652/0105}
{
AI95-00211-01}
{
AI95-00228-01}
{
AI05-0095-1}
All properties of the renamed entity are inherited by the new view unless
otherwise stated by this document. In particular, if the renamed entity
is abstract, the new view also is abstract. Similarly, if the renamed
entity is not a program unit, then neither is the renaming. (Implicitly
declared subprograms are not program units, see
10.1).
Dynamic Semantics
{
8652/0014}
{
AI95-00064-01}
For a call to a subprogram whose body is given as a renaming-as-body,
the execution of the renaming-as-body is equivalent to the execution
of a
subprogram_body
that simply calls the renamed subprogram with its formal parameters as
the actual parameters and, if it is a function, returns the value of
the call.
Ramification: This implies that the subprogram
completed by the renaming-as-body has its own elaboration check.
{
AI05-0123-1}
For a call on a renaming of a dispatching subprogram that is overridden,
if the overriding occurred before the renaming, then the body executed
is that of the overriding declaration, even if the overriding declaration
is not visible at the place of the renaming; otherwise, the inherited
or predefined subprogram is called. A corresponding rule applies to a
call on a renaming of a predefined equality operator for an untagged
record type.
Discussion: Note that whether or not
the renaming is itself primitive has nothing to do with the renamed subprogram.
{
AI05-0123-1}
Note that the above rule is only for tagged types and equality of untagged
record types.
Consider the following
example:
package P is
type T is tagged null record;
function Predefined_Equal(X, Y : T) return Boolean renames "=";
private
function "="(X, Y : T) return Boolean; -- Override predefined "=".
end P;
with P; use P;
package Q is
function User_Defined_Equal(X, Y : T) return Boolean renames P."=";
end Q;
A call on Predefined_Equal will execute the
predefined equality operator of T, whereas a call on User_Defined_Equal
will execute the body of the overriding declaration in the private part
of P.
Thus a renaming allows one to squirrel away
a copy of an inherited or predefined subprogram before later overriding
it.
Bounded (Run-Time) Errors
{
8652/0027}
{
AI95-00135-01}
If a subprogram directly or indirectly renames itself, then it is a bounded
error to call that subprogram. Possible consequences are that Program_Error
or Storage_Error is raised, or that the call results in infinite recursion.
Reason: {
8652/0027}
{
AI95-00135-01}
This has to be a bounded error, as it is possible for a renaming-as-body
appearing in a package body to cause this problem. Thus it is not possible
in general to detect this problem at compile time.
NOTE 1 A procedure can only be renamed
as a procedure. A function whose
defining_designator
is either an
identifier
or an
operator_symbol
can be renamed with either an
identifier
or an
operator_symbol;
for renaming as an operator, the subprogram specification given in the
renaming_declaration
is subject to the rules given in
6.6 for operator
declarations. Enumeration literals can be renamed as functions; similarly,
attribute_references
that denote functions (such as references to Succ and Pred) can be renamed
as functions. An entry can only be renamed as a procedure; the new
name
is only allowed to appear in contexts that allow a procedure
name.
An entry of a family can be renamed, but an entry family cannot be renamed
as a whole.
NOTE 2 The operators of the root
numeric types cannot be renamed because the types in the profile are
anonymous, so the corresponding specifications cannot be written; the
same holds for certain attributes, such as Pos.
NOTE 3 The primitiveness of a renaming-as-declaration
is determined by its profile, and by where it occurs, as for any declaration
of (a view of) a subprogram; primitiveness is not determined by the renamed
view. In order to perform a dispatching call, the subprogram name has
to denote a primitive subprogram, not a nonprimitive renaming of a primitive
subprogram.
Reason: A
subprogram_renaming_declaration
could more properly be called
renaming_as_subprogram_declaration,
since you're renaming something as a subprogram, but you're not necessarily
renaming a subprogram. But that's too much of a mouthful. Or, alternatively,
we could call it a
callable_entity_renaming_declaration,
but that's even worse. Not only is it a mouthful, it emphasizes the entity
being renamed, rather than the new view, which we think is a bad idea.
We'll live with the oddity.
Examples
Examples of subprogram
renaming declarations:
procedure My_Write(C :
in Character)
renames Pool(K).Write; --
see 4.1.3
function Real_Plus(Left, Right : Real ) return Real renames "+";
function Int_Plus (Left, Right : Integer) return Integer renames "+";
function Rouge
return Color
renames Red; --
see 3.5.1
function Rot
return Color
renames Red;
function Rosso
return Color
renames Rouge;
function Next(X : Color)
return Color
renames Color'Succ; --
see 3.5.1
Example of a subprogram
renaming declaration with new parameter names:
function "*" (X,Y : Vector)
return Real
renames Dot_Product; --
see 6.1
Example of a subprogram
renaming declaration with a new default expression:
function Minimum(L : Link := Head)
return Cell
renames Min_Cell; --
see 6.1
Extensions to Ada 95
{
8652/0028}
{
AI95-00145-01}
Corrigendum: Allowed a renaming-as-body to
be just mode conformant with the specification if the subprogram is not
yet frozen.
Wording Changes from Ada 95
{
8652/0014}
{
AI95-00064-01}
Corrigendum: Described the semantics of renaming-as-body, so that
the location of elaboration checks is clear.
{
8652/0027}
{
AI95-00135-01}
Corrigendum: Clarified that circular renaming-as-body is illegal
(if it can be detected in time) or a bounded error.
{
AI95-00228-01}
Amendment Correction: Clarified that renaming a shall-be-overridden
subprogram is illegal, as well as renaming-as-body an abstract subprogram.
Inconsistencies With Ada 2005
{
AI05-0123-1}
Renaming of user-defined untagged record equality
is now defined to call the overridden body so long as the overriding
occurred before the renames. This could change the body called in unusual
cases; the change is necessary to preserve the principle that the body
called for an explicit call to "=" (via a renames in this case)
is the same as the one inherited for a derived type and used in generics.
Note that any renamings before the overriding will be unchanged. Any
differences caused by the change will be rare and most likely will fix
a bug.
Extensions to Ada 2005
Incompatibilities With Ada 2012
{
AI12-0204-1}
Correction: Added a rule to ensure that the
prefix of a renaming of a prefixed view continues to exist during the
life of a renames. If the prefix is a subcomponent that depends on discriminants,
Ada 2005 and 2012 would have allowed the prefix while Ada 2022 would
not. Without this change, explicit forms (renaming the object and then
using that in calls) would be safer than the renaming; that's inconsistent
with other kinds of renaming.
Wording Changes from Ada 2012
{
AI12-0287-1}
Correction: Added wording to ensure that the object subject to
a Legality Rule can be determined at compile-time. The alternative being
nonsense, we treat this as a wording change.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe