Version 1.3 of ai05s/ai05-0282-1.txt

Unformatted version of ai05s/ai05-0282-1.txt version 1.3
Other versions for file ai05s/ai05-0282-1.txt

!standard 4.3.2(8)          11-12-30 AI05-0282-1/03
!class binding interpretation 11-11-08
!status Amendment 2012 11-12-30
!status ARG Approved 6-0-2 11-11-13
!status work item 11-11-08
!status received 11-09-26
!priority Low
!difficulty Easy
!qualifier Omission
!subject Bad ancestor constraints for extension aggregates
!summary
4.3.2(8) applies when the ancestor of an extension aggreate is constraint.
!question
4.3.2(8) does not seem to apply if the ancestor is constrained.
Consider:
procedure Foo is type Root (D : natural) is tagged record F1 : String (1 .. D) := (others => 'x'); end record;
subtype S1 is Root (1); subtype S2 is Root (2);
type Ext is new S1 with record F2 : Integer; end record;
Var : Ext := (S2 with F2 => 123); begin null; end Foo;
One would hope that this would raise Constraint_Error, but nothing seems to have that effect.
!recommendation
(See summary.)
!wording
Replace 4.3.2(8):
If the type of the ancestor_part has discriminants that are not inherited by the type of the extension_aggregate, then, unless the ancestor_part is a subtype_mark that denotes an unconstrained subtype, a check is made that each discriminant of the ancestor has the value specified for a corresponding discriminant, either in the record_component_association_list, or in the derived_type_definition for some ancestor of the type of the extension_aggregate. Constraint_Error is raised if this check fails.
With:
If the type of the ancestor_part has discriminants and the ancestor_part is not a subtype_mark that denotes an unconstrained subtype, then a check is made that each discriminant determined by the ancestor part has the value specified for a corresponding discriminant, if any, either in the record_component_association_list, or in the derived_type_definition for some ancestor of the type of the extension_aggregate. Constraint_Error is raised if this check fails.
!discussion
If the ancestor type of an extension aggregate has discriminants, then there are 6 cases to consider: the cross-product of whether the discriminants of the ancestor type are inherited by the type of the extension aggregate (yes or no) and the three possible forms of the ancestor part:
an expression a subtype mark denoting a constrained subtype a subtype mark denoting an unconstrained subtype.
Keep in mind that an inherited discriminant might correspond to itself.
This change is technically inconsistent with Ada 2005. An extension_aggregate with an ancestor_part whose discriminants are constrained and inherited might now raise Constraint_Error if the aggregate's type is constrained, while it was OK in Ada 2005. In almost all cases, this will make no difference as the constraint will be checked by the immediately following use of the aggregate, but it is possible to compare such an aggregate for equality; in this case, no exception would be raised by Ada 2005, while Ada 2012 will raise Constraint_Error. This should be very rare, and having the possibility means that the representation of the aggregate type has to be able to support unconstrained values of the type, even if the first subtype is constrained and no such objects can be created any other way. This is too costly to allow for such an unlikely case.
!corrigendum 4.3.2(8)
Replace the paragraph:
If the type of the ancestor_part has discriminants that are not inherited by the type of the extension_aggregate, then, unless the ancestor_part is a subtype_mark that denotes an unconstrained subtype, a check is made that each discriminant of the ancestor has the value specified for a corresponding discriminant, either in the record_component_association_list, or in the derived_type_definition for some ancestor of the type of the extension_aggregate. Constraint_Error is raised if this check fails.
by:
If the type of the ancestor_part has discriminants and the ancestor_part is not a subtype_mark that denotes an unconstrained subtype, then a check is made that each discriminant determined by the ancestor_part has the value specified for a corresponding discriminant, if any, either in the record_component_association_list, or in the derived_type_definition for some ancestor of the type of the extension_aggregate. Constraint_Error is raised if this check fails.
!ACATS Test
Create an ACATS C-Test similar to the example in the question.
!ASIS
No ASIS impact.
!appendix

From: Steve Baird
Sent: Monday, September 26, 2011  5:28 PM

The following example obviously should raise Constraint_Error
(assuming that it is not rejected at compile time - one could 
imagine adding some sort of "statically matching subtype"
legality rule, but that seems outside the scope of this discussion):
 
   procedure Foo is
      type Root (D : natural) is tagged record
         F1 : String (1 .. D) := (others => 'x');
      end record;
 
      subtype S1 is Root (1);
      subtype S2 is Root (2);
 
      type Ext is new S1 with record F2 : Integer; end record;
  
      Var : Ext := (S2 with F2 => 123);
   begin
      null;
   end Foo;
 
It seems that the present RM wording fails to capture this intent.
 
Note that 4.3.2(8) does not apply because it begins with
    "If the type of the ancestor_part has discriminants that are not
     inherited by the type of the extension_aggregate, ..."

Perhaps this condition needs to be expanded to include the case of 
inherited discriminants and a constrained ancestor subtype_mark.

****************************************************************

From: Steve Baird
Sent: Sunday, November 13, 2011  1:02 AM

Wording to discuss on Sunday.

====

In 4.3.2(7), replace:
   are initialized by default as for an object of the ancestor type.
with
   are initialized by default as for an object of the subtype denoted
   by the subtype_mark.

and append a new paragraph:

   If the type of the ancestor_part has discriminants and the
   ancestor_part is a subtype_mark that denotes an unconstrained
   subtype, each discriminant of the ancestor type
   has the value specified for a corresponding discriminant, either in
   the record_component_association_list, or in the
   derived_type_definition or some ancestor of the type of
   the extension_aggregate.

Replace 4.3.2(8):
  If the type of the ancestor_part has discriminants that are not
  inherited by the type of the extension_aggregate, then, unless the
  ancestor_part is a subtype_mark that denotes an unconstrained subtype,
  a check is made that each discriminant of the ancestor has the value
  specified for a corresponding discriminant, either in the
  record_component_association_list, or in the derived_type_definition
  for some ancestor of the type of the extension_aggregate.
  Constraint_Error is raised if this check fails.

With:

  If the type of the ancestor_part has discriminants and the
  ancestor_part is not a subtype_mark that denotes an unconstrained
  subtype, then a check is made that each discriminant of the ancestor
  has the value specified for a corresponding  discriminant, either
  in the record_component_association_list, or in the
  derived_type_definition for some ancestor of the type of
  the extension_aggregate. Constraint_Error is raised if this check
  fails.

====

In order to help understand this wording, I think it helps to realize that
if the ancestor type of an extension aggregate has discriminants, then there
are 6 cases to consider: the cross-product of whether the discriminants of
the ancestor type are inherited by the type of the extension aggregate (yes
or no) and the three possible forms of the ancestor part:
    an expression
    a subtype mark denoting a constrained subtype
    a subtype mark denoting an unconstrained subtype.

****************************************************************


Questions? Ask the ACAA Technical Agent