AI22-0014-1
!standard 3.4(27/2) 22-02-03 AI22-0014-1/02
!class binding interpretation 21-11-12
!status Corrigendum 1-2022 22-02-03
!status WG9 Approved 22-10-18
!status ARG Approved 15-0-1 22-02-03
!status work item 21-11-12
!status received 21-09-09
!priority Low
!difficulty Easy
!qualifier Omission
!subject Predicates on inherited functions
It should be clarified that a predicate check is performed on the result
returned by a function with a controlling result that is inherited by a
null extension, if there is a predicate on the null extension.
In the following example:
procedure Inherited is |
P1.T1 is a tagged type and P2.T2 is derived from T1 with a null extension and a subtype predicate. The primitive function F of T1 is inherited by T2. The question is, should there be a predicate check when calling P2.F? (Yes.)
There should be a predicate check when calling P2.F in the above,
because if we were to write the overriding manually, there would be one.
Modify 3.4(27/2):
... If the result type of the inherited subprogram is the derived type, the result of calling the subprogram of the parent or progenitor is converted to the derived type, or in the case of a null extension, extended to the derived type using the equivalent of an extension_aggregate with the original result as the ancestor_part and null record as the record_component_association_list. {In either case, the result is then converted to the corresponding subtype [Redundant:(as defined above)] of the derived type.}
It was unclear whether a predicate check is mandated by the RM in the example given in the !question, as no predicate checks occur on aggregates and it is not said that the result of the call is converted to the derived (sub)type.
In an earlier paragraph in the same section (3.4(19)), "corresponding subtype" is defined to be the first subtype in the case of a record extension (and hence also a null extension), and in the example, the first subtype of the derived type has a dynamic predicate. So by clarifying that the conversion to the corresponding subtype occurs, the appropriate check would be performed.
@drepl
For the execution of a call on an inherited subprogram, a call on the
corresponding primitive subprogram of the parent or progenitor type is
performed; the normal conversion of each actual parameter to the subtype of the
corresponding formal parameter (see 6.4.1) performs any necessary type
conversion as well. If the result type of the inherited subprogram is the
derived type, the result of calling the subprogram of the parent or progenitor
is converted to the derived type, or in the case of a null extension, extended
to the derived type using the equivalent of an @fa{extension_aggregate} with
the original result as the @fa{ancestor_part} and @b{null record} as the
@fa{record_component_association_list}.
@dby
For the execution of a call on an inherited subprogram, a call on the
corresponding primitive subprogram of the parent or progenitor type is
performed; the normal conversion of each actual parameter to the subtype of the
corresponding formal parameter (see 6.4.1) performs any necessary type
conversion as well. If the result type of the inherited subprogram is the
derived type, the result of calling the subprogram of the parent or progenitor
is converted to the derived type, or in the case of a null extension, extended
to the derived type using the equivalent of an @fa{extension_aggregate} with
the original result as the @fa{ancestor_part} and @b{null record} as the
@fa{record_component_association_list}. In either case, the result is then
converted to the corresponding subtype (as defined above) of the derived type.
An ACATS C-Test should be constructed to check that the runtime predicate check is made.
From: Claire Dross
Sent: Thursday, September 9, 2021 9:14 AM
Hi all,
We have come up recently with the following example:
procedure Inherited with SPARK_Mode is
package P1 is
type T1 is tagged record
X : Integer;
end record;
function F return T1;
V : constant T1 := (X => 0);
end P1;
package P2 is
type T2 is new P1.T1 with null record with Predicate => X > 0;
V : constant T2 := (X => 1);
end P2;
package body P1 is
function F return T1 is (V);
end P1;
procedure Bad is
begin
pragma Assert (P1.T1'Class (P2.F).X = 0); --@PREDICATE_CHECK:FAIL
end Bad;
begin
Bad;
end Inherited;
P1.T1 is a tagged type and P2.T2 is derived from T1 with a null extension
and a subtype predicate. The primitive function F of T1 is inherited by T2.
The question is, should there be a predicate check when calling P2.F? I
personally think there should be one, because if we were to write the
overriding manually, there would be one. However it is unclear whether such
a check is mandated by the RM as no predicate checks occur on aggregates and
it is not said that the result of the call is converted to the derived type.
What do others think?
****************************************************************
From: Tucker Taft
Sent: Thursday, September 9, 2021 12:13 PM
I agree that the wording in 3.4(27/2) should be augmented, perhaps as follows:
... If the result type of the inherited subprogram is the derived type, the
result of calling the subprogram of the parent or progenitor is converted to
the derived type, or in the case of a null extension, extended to the derived
type using the equivalent of an extension_aggregate with the original result
as the ancestor_part and null record as the record_component_association_list.
{In either case, the result is then converted to the corresponding subtype
[Redundant:(as defined above)] of the derived type.}
In an earlier paragraph in the same section (3.4(19)), "corresponding subtype"
is defined to be the first subtype in the case of a record extension (and hence
also a null extension), and in the example, the first subtype of the derived
type has a dynamic predicate. (The example uses the GNAT-specific Predicate
aspect, which automatically selects Dynamic_Predicate or Static_Predicate.)
So by clarifying that the conversion to the corresponding subtype occurs, the
appropriate check would be performed.
****************************************************************