Version 1.1 of ais/ai-00117.txt

Unformatted version of ais/ai-00117.txt version 1.1
Other versions for file ais/ai-00117.txt

!standard 03.09.02 (10)          97-03-19 AI95-00117/02
!class binding interpretation 96-04-04
!status work item 96-04-04
!status received 96-04-04
!priority High
!difficulty Hard
!subject Calling Conventions
!summary 96-11-18
????At the Vermont ARG meeting, it was suggested that:
By default, the convention of a dispatching op should be same as the type.
Type extensions should inherit their convention from the parent type.
The Discussion should mention that it's legitimate to reject convention Ada on added subprograms. Or on the extended type.
???However, I don't think this is viable -- see the Appendix. In any case, this AI has been only partly updated after the Vermont meeting, pending discussion of these points.
----------------
An inherited or overriding subprogram inherits the calling convention of the parent subprogram.
An explicitly declared dispatching operation shall not have convention Intrinsic. An implicitly declared dispatching "/=" operator has convention Intrinsic, and this is legal.
!question 96-11-18
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 96-04-04
(See summary.)
!wording 96-04-04
Add a bullet after 6.3.1(13): The default calling convention for any inherited or overriding subprogram not listed above is that of the parent subprogram.
3.9.2(10) should say: An explicitly declared dispatching operation shall not have convention Intrinsic.
!discussion 96-11-18
Note: This AI subsumes AI95-00065.
----------------
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); -- 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.
----------------
3. Clearly, an implicitly declared dispatching "/=" should not automatically be illegal.
The above 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 subprogram 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); -- This is a dispatching call in Instance, because -- the actual type for Formal is class-wide. ... -- Proc'Access would be illegal here, because it is of -- convention Intrinsic, by 6.3.1(8). end G;
type Actual is new Root with ...; procedure Proc(X: Actual); package Instance is new G(Formal => Actual'Class); -- It is legal to pass in a class-wide actual, because Formal -- has unknown discriminants.
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. 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