Version 1.3 of ais/ai-00117.txt
!standard 03.09.02 (10) 99-04-01 AI95-00117/04
!class binding interpretation 96-04-04
!status ARG Approved (with changes) 7-1-1 99-03-24
!status work item 96-04-04
!status received 96-04-04
!priority High
!difficulty Hard
!subject Calling Conventions
!summary
Unless specified otherwise in the RM, the default convention of any
entity is Ada.
An inherited or overriding subprogram of a type extension inherits the
calling convention of the parent subprogram.
New operations of type extensions have the convention of their type
unless a new convention is defined for the operation, if this is
supported by an implementation.
The convention of the partial view of a private type or private
extension is the convention of the full type.
An explicitly declared dispatching operation shall not have convention
Intrinsic. An implicitly declared dispatching "/=" operator with
boolean result has convention Intrinsic, and this is legal.
!question
6.3.1 defines the default convention of various entities (that is, the
convention in the absence of a convention-specifying pragma):
2 As explained in B.1, ``Interfacing Pragmas'', a convention can be
specified for an entity. For a callable entity or access-to-subprogram type,
the convention is called the calling convention. The following conventions
are defined by the language:
3 The default calling convention for any subprogram not listed
below is Ada. A pragma Convention, Import, or Export may be used
to override the default calling convention (see B.1).
4 The Intrinsic calling convention represents subprograms that are
``built in'' to the compiler. The default calling convention is
Intrinsic for the following:
5 an enumeration literal;
6 a "/=" operator declared implicitly due to the declaration
of "=" (see 6.6);
7 any other implicitly declared subprogram unless it is a
dispatching operation of a tagged type;
8 an inherited subprogram of a generic formal tagged type
with unknown discriminants;
9 an attribute that is a subprogram;
10 a subprogram declared immediately within a protected_body.
11 The Access attribute is not allowed for Intrinsic
subprograms.
12 The default calling convention is protected for a protected
subprogram, and for an access-to-subprogram type with the
reserved word protected in its definition.
13 The default calling convention is entry for an entry.
- ----------------
1. What is the default convention of an entity not covered by 6.3.1,
such as a record type? (Ada.)
- ----------------
2. Does an inherited or overriding subprogram have (by default) the same
convention as the parent subprogram? (Yes.)
6.3.1(3) implies that if the calling convention of a parent subprogram
is not Ada, the default convention of an overriding subprogram is,
nonetheless, Ada. However, 3.9.2(10) says:
If the dispatching operation overrides an inherited subprogram, it
shall be subtype conformant with the inherited subprogram.
6.3.1(17) requires matching conventions for subtype conformance.
Thus, the default calling convention for this overriding case
is illegal; the programmer must give a pragma specifying the
convention in this case. This seems unfriendly.
On the other hand, 3.4(18) says:
18 The profile of an inherited subprogram (including an
inherited enumeration literal) is obtained from the profile of
the corresponding (user-defined) primitive subprogram of the
parent type, after systematic replacement of each subtype of its
profile (see 6.1) that is of the parent type with a corresponding
subtype of the derived type. ...
And 6.1(22) says:
Associated with a profile is a calling convention.
These paragraphs seem to imply that an inherited subprogram inherits the
calling convention of its parent, as part of the inherited profile.
- ----------------
3. Is an implicitly declared dispatching "/=" operator legal? (Yes.)
Paragraph 3.9.1(1) says that the primitive subprograms of a tagged
type are called dispatching operations. Paragraph 3.9.2(10) goes
on to say that a dispatching operation shall not be of convention
Intrinsic. However, paragraph 6.3.1(6) says that "/=" declared
implicitly due to the declaration of "=" is of convention Intrinsic,
by default.
Together these imply that the "/=" implicitly declared due to the
declaration of "=" of a tagged type is an illegal dispatching operation.
Is this the intent? (No.)
!recommendation
(See summary.)
!wording
Add two bullets after 6.3.1(13):
"If not listed above, the calling convention for any inherited
or overriding dispatching operation of a tagged type is that
of the corresponding subprogram of the parent type. The
default calling convention for a new dispatching operation
of a tagged type is the convention of the full view of the type.
The default convention of any entity not listed above is Ada."
Add a Note to 6.3.1.:
"An implementation need not support a pragma Convention on a
new dispatching operation that specifies a convention different
from the convention of the type or its other dispatching operations."
The last two sentences of 3.9.2(10) should be replaced by:
"The convention of an inherited or overriding dispatching operation
is the convention of the inherited operation. An explicitly declared
dispatching operation shall not have convention Intrinsic."
!discussion
1. The default convention ought to be Ada for any entity not covered by
6.3.1. The dispatching operations of a type ought to inherit the
convention of the type, for convenient interfacing to other OOP
languages. (See below for more discussion of this point.)
- ----------------
2. It is important that Ada allow clean interfaces to other programming
languages. In particular, it is important that Ada's tagged types can
be used to interface to other OOP languages.
If an Ada 95 implementation is tightly integrated with another
language, such as C++ or Java, it is nice if an Ada tagged type
can be declared as an extension of a (foreign) type (or class) of the
other language. Presumably, all of the dispatching operations of this
foreign type would be defined as imported, with the convention of
that other language. When defining the type extension in Ada, it
would be very inconvenient if every overriding would have to have
a pragma Convention on it to match that of the inherited operation,
as required by 3.9.2(10).
Hence, it seems appropriate to define the default calling convention
of an overriding of an inherited dispatching operation to be the same as
that of the corresponding operation on the parent type, rather than
always being convention "Ada" as specified in 6.3.1(3).
For example:
package Java.Graphics is
type Graphics_Obj is tagged limited private;
procedure drawString(G : in out Graphics_Obj; S : String);
pragma Import(Java, drawString);
...
end Java.Graphics;
with Java.Graphics; use Java.Graphics;
package Flight_Simulator is
type Simulator_Obj is new Graphics_Obj with private;
procedure drawString(S : in out Simulator_Obj; S : String);
--
...
end Flight_Simulator;
The "pragma Convention(Java, ...);" should be implicit when overriding
a dispatching operation with convention Java. Anything else would be
illegal by 3.9.2(10), and it seems silly to require the programmer
to litter their program with redundant "pragma Convention"s.
The Note B.1(42) - derived from 13.1 - implies permission of
implementation-defined restrictions of interfacing pragmas. Hence an
implementation will be allowed to reject the attempt to create
"heterogeneous" tagged types, i.e., types having primitive operations
of different, explicitly specified conventions or of explicity
specified conventions different from the convention of the type.
- ----------------
2.a. The "Breach of Privacy" Issue
Presently, the convention of a primitive subprogram can be specified
in the private part of the declaring package. The current rules
require explicit confirmation of this convention for overriding
subprograms and thus constitute a breach of the privacy of the private
part, since the user needs to know about this privately specified
convention in order to make the overriding declaration legal.
We are very reluctant to mandate Convention pragmas in the visible part
of the package. Although such a rule might be derivable from freezing
rules, it nevertheless could create a compatibility problem for existing
code.
The proposed new rule of inheriting the convention eases, but does not
eliminate, the breach of privacy, as any explicitly specified convention
will still need to confirm the inherited convention.
At the implementation level, both the existing and the proposed model
breach the private part, as subtype conformance of overriding with
inherited subprograms includes checking for equality of the convention.
- ----------------
2.b. Deriving the convention of operations from the type
Having dispatching operations with the convention of some
other OOP language, while the type is not represented according to the
convention of this other language, will be almost impossible to
implement. The "normal" case will be that both type and operations
need the convention pragma. In this context, it makes little sense
that the convention of primitive operations defaults to Ada rather
than to the convention of their type. The user will be forced to
repeat the pragma for all the operations of the type. Considerably
more convenient is a model, in which the default convention of
dispatching operations is inherited from the type, but overridable if
the implementation allows for such mixed conventions.
Since current rules imply that the convention of a type needs to be
specified for the full view of the type, such dependency creates yet
another breach of privacy in the case of private tagged types. However,
the breach already exists as explained in 2.a. and to then exploit it
for more convenience to the user and a cleaner overall model seems
justified.
Mandating the specification of the convention for the partial view in
order to avoid the breach of privacy seems too much of an
incompatibility for existing code.
- ----------------
3. Clearly, an implicitly declared dispatching "/=" should not
automatically be illegal.
The proposed new wording precludes declaring a dispatching operation by
renaming the Intrinsic "/=", which is good (since there is no real body
associated with "/="). It does not make "/=" itself illegal, which is
also good.
The reason for 6.3.1(4-10) making various subprograms Intrinsic is that
these subprograms don't really exist in machine code. For example, an
implementation would typically not generate any code for the
implicitly-declared "/=" operator -- instead, it would call the "="
operator, and then do a "not" operation at the call site. We don't want
to allow 'Access of such subprograms, because it would introduce an
implementation burden -- the implementation would have to materialize
these subprograms as real machine-code subprograms, which is not
otherwise necessary.
A similar issue arises with 6.3.1, which says that an inherited
subprogram of a generic formal type with unknown discriminants is of
convention Intrinsic, by default.
The reason for this rule is obscure enough that it should have been
documented in the AARM: Consider:
package P is
type Root is tagged null record;
procedure Proc(X: Root);
end P;
generic
type Formal(<>) is new Root with private;
package G is
...
end G;
package body G is
...
X: Formal := ...;
...
Proc(X); --
--
...
--
--
end G;
type Actual is new Root with ...;
procedure Proc(X: Actual);
package Instance is new G(Formal => Actual'Class);
--
--
Within Instance, all calls to Proc will be dispatching calls, so Proc
doesn't really exist in machine code, so we wish to avoid taking 'Access
of it. 6.3.1(8) applies to those cases where the actual type might be
class-wide, and makes these Intrinsic, thus forbidding 'Access.
The wording change to 3.9.2(10) shown above means that it's OK to have
such an inherited subprogram. If the spec of G contained a type
extension of Formal, then that type's inherited Proc would also have
convention Intrinsic, which would be legal. However, an explicit
overriding of that Proc would be illegal.
!appendix
!section 3.9.2(1)
!subject Implicit /= is a legal dispatching operation
!reference RM95 3.9.2(1,10)
!reference RM95 6.3.1(6)
!from Tucker Taft 95-07-06
!reference as: 95-5209.a Tucker Taft 95-7-6>>
!discussion
Paragraph 3.9.1(1) says that the primitive subprograms of a tagged
type are called dispatching operations. Paragraph 3.9.2(10) goes
on to say that a dispatching operation shall not be of convention
Intrinsic. However, paragraph 6.3.1(6) says that "/=" declared
implicitly due to the declaration of "=" is of convention Intrinsic.
Together these imply that the "/=" implicitly declarated due to the
declaration of "=" of a tagged type is an illegal dispatching operation.
Presumably 3.9.2(10) should be modified to say something like:
An explicitly declared dispatching operation shall not have
convention Intrinsic.
This precludes declaring a dispatching operation by renaming the
Intrinsic "/=", which is good (since there is no real body
associated with "/="). It does not make "/=" itself illegal,
which is also good.
- -Tuck
****************************************************************
!section 3.9.2(10)
!subject Convention of an overriding dispatching operation
!reference RM95-3.9.2(10)
!reference RM95-6.3.1(3)
!from Tucker Taft 95-11-21
!reference 95-5394.a Tucker Taft 95-11-21>>
!discussion
If an Ada 95 implementation is tightly integrated with another
language, such as C++ or Java, it is nice if an Ada tagged type
can be declared as an extension of a (foreign) type (or class) of the
other language. Presumably, all of the dispatching operations of this
foreign type would be defined as imported, with the convention of
that other language. When defining the type extension in Ada, it
would be very inconvenient if every overriding would have to have
a pragma Convention on it to match that of the inherited operation,
as required by 3.9.2(10).
Hence, it seems appropriate to define the default calling convention
of an overriding of an inherited dispatching operation to be the same as
that of the corresponding operation on the parent type, rather than
always being convention "Ada" as specified in 6.3.1(3).
For example:
package Java.Graphics is
type Graphics_Obj is tagged limited private;
procedure drawString(G : in out Graphics_Obj; S : String);
pragma Import(Java, drawString);
...
end Java.Graphics;
with Java.Graphics; use Java.Graphics;
package Flight_Simulator is
type Simulator_Obj is new Graphics_Obj with private;
procedure drawString(S : in out Simulator_Obj; S : String);
-- implicit: pragma Convention(Java, drawString);
...
end Flight_Simulator;
The "pragma Convention(Java, ...);" should be implicit when overriding
a dispatching operation with convention Java. Anything else would be
illegal by 3.9.2(10), and it seems silly to require the programmer
to litter their program with redundant "pragma Convention"s.
- -Tuck
****************************************************************
!section 3.9.2(10)
!subject Convention of an overriding dispatching operation
!reference RM95-3.9.2(10)
!reference RM95-6.3.1(3)
!reference 95-5394.a Tucker Taft 95-11-21
!reference AI95-00117
!from Bob Duff
!reference 96-5759.a Robert A Duff 96-11-18>>
!discussion
Tucker wrote:
> Hence, it seems appropriate to define the default calling convention
> of an overriding of an inherited dispatching operation to be the same as
> that of the corresponding operation on the parent type, rather than
> always being convention "Ada" as specified in 6.3.1(3).
AI-117 responds to this issue.
At the Vermont ARG meeting, several folks suggested that the solution
should instead be that the dispatching operations should get their
default convention from the *type*. That is, when interfacing to (say)
Java, one would normally want the type to be of Convention Java, and all
dispatching operations also Convention Java. So a new dispatching
operation would get convention Java, and an overriding operation would
get the convention from the parent operation, which, unless explicitly
overridden, would be Java. Presumably, a type extension should inherit
the parent type's convention.
I see a problem with this: For a private type, the Convention pragma
must appear in the private part. If subprograms in the visible part
inherit their convention from the type, then we have a violation of
privacy. That is, code in the private part would affect the legality of
'Access outside the package.
I also see a problem with Tucker's solution: Suppose package P declares
type T1, and package P.C declares T2 as a type extension of T1. For a
primitive subprogram of T2, we don't necessarily know at the point of
declaration whether it overrides anything -- we might find out about
overriding in the private part of P.C. If this operation inherits its
convention from the parent operation, then we have a violation of
privacy w.r.t. 'Access. If it does not, then presumably it *must* have
a pragma Convention, which must match that of the parent op.
Actually, is it not worse? Consider a simple example with no
inheritance. A subprogram is declared in the visible part of a package,
and a pragma Convention is given in the private part. How are clients
supposed to know whether 'Access is legal?
It seems odd that pragma Convention is allowed to be in the private part
for subprograms, and *required* to be in the private part, for private
types.
Another issue: 6.3.1 defines the default convention for subprograms, and
for access-to-subprogram types. Should it not also define the default
convention for everything else (e.g. record types)?
Another issue: How are untagged derived types affected? Note that an
overriding operation really has little to do with what it overrides,
except that it hides it.
- - Bob
****************************************************************
!section 3.9.2(10)
!subject Convention of an overriding dispatching operation
!reference RM95-3.9.2(10)
!reference RM95-6.3.1(3)
!reference 95-5394.a Tucker Taft 95-11-21
!reference AI95-00117
!reference 96-5759.a Robert A Duff 96-11-18
!from Erhard Ploedereder
!reference 96-5775.a Erhard Ploedereder 96-11-28>>
!discussion
In 96-5759.a, Bob argues that the rules proposed in the AI and some
improvements suggested at the recent meeting all share the problem
that they violate the privacy principles of Ada.
This is true. However, the current ARM semantics do so in the very same way
by requiring the user to specify a pragma on inherited primitive operations,
while he has no business knowing about the Convention Pragma applied
privately to the original operation. In fact, the situation is worse than
under the AI: The RM requires explicit action to react to something
supposedly unknown. Under the AI, at least no such explicit action is
required, albeit that 'Access ramifications may exist (as they do for
the RM).
Bob argues further:
> Another issue: 6.3.1 defines the default convention for subprograms, and
> for access-to-subprogram types. Should it not also define the default
> convention for everything else (e.g. record types)?
Very good point and it does need to be addressed. (Wouldn't this be a
natural fall-out of implicit inheritance of Convention from types, as I
understood the cited alternative solution suggested at the meeting ?)
****************************************************************
Questions? Ask the ACAA Technical Agent