AI22-0166-1

!standard 3.9.2(10/2)                                    26-07-20  AI22-0166-1/03

!standard 3.10.2(32/5)

!standard 4.6(24.26/6)

!standard 4.6(24.27/2)

!standard 5.5.3(18/5)

!standard 5.5.3(20/5)

!standard 6.1.2(29/5)

!standard 6.1.2(38/5)

!standard 6.1.2(39/5)

!standard 6.1.2(40/5)

!standard 6.5.1(3.3/5)

!standard 6.5.1(7.1/6)

!standard 6.5.1(7.2/6)

!standard 8.3(12.3/5)

!standard 9.5(20/5)

!standard 9.5(54/5)

!standard 9.10.1(24/5)

!standard 12.6(8/3)

!standard 13.1.1(33/3)

!class Binding Interpretation 26-06-30

!status work item 26-06-30

!status received 26-06-30

!assigned author Stephen Baird

!submitter Stephen Baird

!priority Medium

!difficulty Medium

!qualifier Omission

!subject Subprogram aspect compatibility

!summary

Some rules requiring profile conformance need accompanying aspect compatibility checks.

!issue

The No_Return aspect illustrates a property that is shared with several other aspects that can be specified for subprograms. In an indirect call (either via dispatching or via an access-to-subprogram value), if the view that the caller sees has No_Return => False then it is ok if the No_Return aspect of the callee whose body is executed at run-time turns out to have No_Return => True. The reverse is not true. If the caller sees No_Return => True but nonetheless the call returns, then that's a (big) problem. Exactly three of the four possible combinations of aspect values are ok. One combination must be disallowed via a special legality rule.

There is a similar problem with generic formal subprograms. If a formal subprogram has No_Return => False but the actual has No_Return => True, that's ok. Again, the reverse is not true.

The same problem also comes up with access-to-subprogram type conversions.

There is also a related problem in a corner case where the visibility rules depend on the idea that null procedures with corresponding profiles are largely interchangeable. Suppose we have two interface types. Each has a single-parameter primitive procedure named Foo; their parameters match in name, mode, etc. But exactly one of the two has No_Return => True.

So the two are not interchangeable. Now we have a type that implements both interfaces and has its own inherited Foo procedure. This breaks the 8.3 "one is chosen arbitrarily" visibility rule because that choice is not supposed to have user-visible consequences.

In one respect, No_Return is not an ideal choice to illustrate the general problem. In the specific case of No_Return, some but not all of the problems discussed in this AI have already been addressed in AI22-0090. The legality rules added in that AI are removed because they are implied by the more general solution of this AI. Analogous rules that are specific to the Global aspect are also removed for the same reason. We want to avoid legality rules that are specific to individual aspects when a more general rule is appropriate.

!recommendation

To avoid duplication in the RM, a new category of aspects is defined: call-specializing aspects. An aspect defined to be in this category must also define (perhaps implicitly) a compatibility rule indicating which combinations are "ok". For constructs where additional legality checking is needed, legality rules of the form "shall be compatible ... with respect to every call-specializing aspect" are defined.

For the "one is chosen arbitrarily" 8.3 rule, we include a requirement that the candidates must agree with respect to all call-specializing aspects.

!wording

 Modify 3.9.2(10/2):

In the declaration of a dispatching operation of a tagged type, everywhere a subtype of the tagged type appears as a subtype of the profile (see 6.1), it shall statically match the first subtype of the tagged type. If the dispatching operation overrides an inherited subprogram, it shall be subtype conformant with the inherited subprogram. The convention of an inherited dispatching operation is the convention of the corresponding primitive operation of the parent or progenitor type. The default convention of a dispatching operation that overrides an inherited primitive operation is the convention of the inherited operation; if the operation overrides multiple inherited operations, then they shall all have the same convention. An explicitly declared dispatching operation shall not be of convention Intrinsic. {An overriding subprogram shall be compatible with the overridden inherited subprogram with respect to every call-specializing aspect. In addition to the places where Legality Rules normally apply (see 12.3), these rules apply also in the private part of an instance of a generic unit.}

Modify 3.10.2(32/5):

P'Access

P'Access yields an access value that designates the subprogram denoted by P. The type of P'Access is an access-to-subprogram type (S), as determined by the expected type. The accessibility level of P shall not be statically deeper than that of S. [If S is nonblocking, P shall be nonblocking. In addition to the places where Legality Rules normally apply (see 12.3), these rules apply also in the private part of an instance of a generic unit. ] The profile of P shall be subtype conformant with the designated profile of S, and shall not be Intrinsic. {The subprogram P shall be compatible with the access type S with respect to every  call-specializing aspect.} If the subprogram denoted by P is declared within a generic unit, and the expression P'Access occurs within the body of that generic unit or within the body of a generic unit declared within the declarative region of the generic unit, then the ultimate ancestor of S shall be either a nonformal type declared within the generic unit or an anonymous access type of an access parameter.

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

Replace 4.6(24.26/6):

with

Delete 4.6(24.27/2):

Modify 5.5.3(18/5):

Allows_Exit

The Allows_Exit aspect is of type Boolean. The specified value shall be static. The Allows_Exit aspect of an inherited primitive subprogram is True if Allows_Exit is True either for the corresponding subprogram of the {parent or} progenitor type or for any other inherited subprogram that it overrides. If not specified or inherited as True, the Allows_Exit aspect of a callable entity is False. For an entry, only a confirming specification of False is permitted for the Allows_Exit aspect. {Allows_Exit is a call-specializing aspect.}

Modify 5.5.3(20/5):

Parallel_Iterator

The Parallel_Iterator aspect is of type Boolean. The specified value shall be static. The Parallel_Iterator aspect of an inherited primitive subprogram is True if Parallel_Iterator is True either for the corresponding subprogram of the {parent or }progenitor type or for any other inherited subprogram that it overrides. If not specified or inherited as True, the Parallel_Iterator aspect of a callable entity is False. {Parallel_Iterator is a call-specializing aspect.}

Add after 6.1.2(29/5): (at the end of the Static Semantics category):

Global is a call-specializing aspect. A global aspect G1 is compatible with a global aspect G2 if G2 is either Unspecified or in out all, or if the set of variables that G1 identifies as readable or updatable is a subset of the corresponding set for G2. [Redundant: An explicit definition of compatibility is required for any non-Boolean call-specializing aspect.] The definition of any implementation-defined global mode shall extend this definition  of compatibility to account for that mode.

Delete 6.1.2(38/5):

If a Global aspect other than Unspecified or in out all applies to an access-to-subprogram type, then the prefix of an Access attribute_reference producing a value of such a type shall denote a subprogram whose Global aspect is not Unspecified and is covered by that of the result type, where a global aspect G1 is covered by a global aspect G2 if the set of variables that G1 identifies as readable or updatable is a subset of the corresponding set for G2. Similarly on a conversion to such a type, the operand shall be of a named access-to-subprogram type whose Global aspect is covered by that of the target type.

Delete 6.1.2(39/5):

If an implementation-defined global_mode applies to a given set of variables, an implementation-defined rule determines what sort of references to them are permitted.

Delete 6.1.2(40/5):

For a subprogram that is a dispatching operation of a tagged type T, each mode of its Global aspect shall identify a subset of the variables identified by the corresponding mode, or by the in out mode, of the Global'Class aspect of a corresponding dispatching subprogram of any ancestor of T, unless the aspect of that ancestor is Unspecified.

Modify 6.5.1(3.3/5):

If directly specified, the aspect_definition shall be a static expression. When not directly specified, if the subprogram is a primitive subprogram inherited by a derived type, then the aspect is True if any corresponding subprogram of the parent or progenitor types is nonreturning. Otherwise, the aspect is False. { No_Return is a call-specializing aspect.}

Delete 6.5.1(6/5):

A subprogram shall be nonreturning if it overrides a dispatching nonreturning subprogram. 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.

Delete 6.5.1(7.1/6):

If a No_Return aspect is True for a generic formal subprogram or a generic formal access-to-subprogram type, it shall be True for the matching actual in an instantiation.

     Delete 6.5.1(7.2/6):

If a No_Return aspect is True for an access-to-subprogram type T, then it shall be True for a subprogram S if S'Access has an expected type of T. Similarly, on a conversion to such a type, the No_Return aspect shall be true for the operand type.

Modify 8.3(12.3/5):

Modify 9.5(20/5):

Nonblocking

This aspect specifies the blocking restriction for the entity; it shall be specified by a static Boolean expression. [Redundant: The aspect_definition can be omitted from the specification of this aspect; in that case, the aspect for the entity is True.] {Non_Blocking is a call-specializing aspect.}

      Modify 9.5(54/5):

[A subprogram shall be nonblocking if it overrides a nonblocking dispatching operation.] An entry shall not implement a nonblocking procedure.[ If an inherited dispatching subprogram allows blocking, then the corresponding subprogram of each ancestor shall allow blocking.]

Modify 9.10.1(24/5):

Parallel_Calls

The Parallel_Calls aspect is of type Boolean. The specified value shall be static. The Parallel_Calls aspect of an inherited primitive subprogram is True if Parallel_Calls is True either for the corresponding subprogram of the {parent or }progenitor type or for any other inherited subprogram that it overrides. If not specified or inherited as True, the Parallel_Calls aspect of a subprogram is False. {Parallel_Calls is a call-specializing aspect.}

Modify 12.6(8/3):

The profiles of the formal and actual shall be mode conformant. {The actual subprogram shall be compatible with the formal subprogram with respect to every call-specializing aspect. In addition to the places where Legality Rules normally apply (see 12.3), this rule also applies in the private part of an instance of a generic unit.}.

     Add after 13.1.1(33/3):

Some aspects which can be specified for subprograms are defined to be call-specializing [Redundant: ; such aspects may allow callers to make assumptions about the called subprogram]. Each aspect definition that defines a call-specializing aspect shall specify[a] a compatibility rule. The compatibility rule defines, for any two values of that aspect, whether the first value is compatible with the second value. Unless otherwise specified for a particular Boolean-valued call-specializing aspect, an aspect value V1 is compatible with an aspect value V2 unless V1 is True and V2 is False.

!discussion

We also take this opportunity to clean up some misuses of the term “progenitor”.

!example

package Example is
   type T1 is tagged null record;

   procedure Proc (X : T1) with No_Return;

   type T2 is new T1 with null record;

   overriding procedure Proc (X : T2); –  illegal

end Example;

!ACATS test

A B-test similar to the example would be appropriate.

!appendix

[a]Is this really "shall", which is usually used for Legality Rules. This seems to be a requirement on the Standard itself, which should just say "specifies".