Scalar_Storage_Order must be consistent between any component of a composite
type (array or record) and the composite type itself. We already enforced
this in the case where the enclosing type has a Scalar_Storage_Order
attribute definition, and the component type has none. We now also do so
also in the opposite case when the enclosing type has no Scalar_Storage_Order
clause, and any component does have one.

The following compilation must be rejected with the indicated error messages:

$ gcc -c nat_comp_rev_el.ads
nat_comp_rev_el.ads:26:04: composite type must have explicit scalar storage 
order
nat_comp_rev_el.ads:27:04: composite type must have explicit scalar storage 
order
nat_comp_rev_el.ads:29:07: composite type must have explicit scalar storage 
order
nat_comp_rev_el.ads:34:07: composite type must have explicit scalar storage 
order

with System; use System;
package Nat_Comp_Rev_El is
   type U32 is mod 2**32;

   type LE_Record is record
      X : U32;
   end record;
   for LE_Record use record
      X at 0 range 0 .. 31;
   end record;
   for LE_Record'Bit_Order use Low_Order_First;
   for LE_Record'Scalar_Storage_Order use Low_Order_First;

   type BE_Record is record
      X : U32;
   end record;
   for BE_Record use record
      X at 0 range 0 .. 31;
   end record;
   for BE_Record'Bit_Order use High_Order_First;
   for BE_Record'Scalar_Storage_Order use High_Order_First;

   --  Reject the below declarations: the component type has an explicit SSO,
   --  so we also require one on the enclosing composite type.

   type Two_LE is array (1 .. 2) of LE_Record;
   type Two_BE is array (1 .. 2) of BE_Record;
   type Rec_LE is record
      Comp : LE_Record;
      X    : Integer;
   end record;

   type Rec_BE is record
      Comp : BE_Record;
      X    : Integer;
   end record;

end Nat_Comp_Rev_El;

Tested on x86_64-pc-linux-gnu, committed on trunk

2013-10-17  Thomas Quinot  <qui...@adacore.com>

        * freeze.adb (Check_Component_Storage_Order): Reject a record or
        array type that does not have an explicit Scalar_Storage_Order
        attribute definition if a component of the record, or the
        elements of the array, have one.
        * gnat_rm.texi (attribute Scalar_Storage_Order): Document the above
        rule.

Index: gnat_rm.texi
===================================================================
--- gnat_rm.texi        (revision 203568)
+++ gnat_rm.texi        (working copy)
@@ -8727,6 +8727,10 @@
 if the component does not start on a byte boundary, then the scalar storage
 order specified for S and for the nested component type shall be identical.
 
+If @var{S} appears as the type of a record or array component, the enclosing
+record or array shall also have a @code{Scalar_Storage_Order} attribute
+definition clause.
+
 No component of a type that has a @code{Scalar_Storage_Order} attribute
 definition may be aliased.
 
Index: freeze.adb
===================================================================
--- freeze.adb  (revision 203568)
+++ freeze.adb  (working copy)
@@ -92,11 +92,15 @@
 
    procedure Check_Component_Storage_Order
      (Encl_Type : Entity_Id;
-      Comp      : Entity_Id);
+      Comp      : Entity_Id;
+      ADC       : Node_Id);
    --  For an Encl_Type that has a Scalar_Storage_Order attribute definition
-   --  clause, verify that the component type is compatible. For arrays,
-   --  Comp is Empty; for records, it is the entity of the component under
-   --  consideration.
+   --  clause, verify that the component type has an explicit and compatible
+   --  attribute/aspect. For arrays, Comp is Empty; for records, it is the
+   --  entity of the component under consideration. For an Encl_Type that
+   --  does not have a Scalar_Storage_Order attribute definition clause,
+   --  verify that the component also does not have such a clause.
+   --  ADC is the attribute definition clause if present (or Empty).
 
    procedure Check_Strict_Alignment (E : Entity_Id);
    --  E is a base type. If E is tagged or has a component that is aliased
@@ -1068,11 +1072,12 @@
 
    procedure Check_Component_Storage_Order
      (Encl_Type : Entity_Id;
-      Comp      : Entity_Id)
+      Comp      : Entity_Id;
+      ADC       : Node_Id)
    is
       Comp_Type : Entity_Id;
+      Comp_ADC  : Node_Id;
       Err_Node  : Node_Id;
-      ADC       : Node_Id;
 
       Comp_Byte_Aligned : Boolean;
       --  Set True for the record case, when Comp starts on a byte boundary
@@ -1113,11 +1118,24 @@
       --  the attribute definition clause is attached to the first subtype.
 
       Comp_Type := Base_Type (Comp_Type);
-      ADC := Get_Attribute_Definition_Clause
-               (First_Subtype (Comp_Type),
-                Attribute_Scalar_Storage_Order);
+      Comp_ADC := Get_Attribute_Definition_Clause
+                    (First_Subtype (Comp_Type),
+                     Attribute_Scalar_Storage_Order);
 
-      if Is_Record_Type (Comp_Type) or else Is_Array_Type (Comp_Type) then
+      --  Case of enclosing type not having explicit SSO: component cannot
+      --  have it either.
+
+      if No (ADC) then
+         if Present (Comp_ADC) then
+            Error_Msg_N
+              ("composite type must have explicit scalar storage order",
+               Err_Node);
+         end if;
+
+      --  Case of enclosing type having explicit SSO: check compatible
+      --  attribute on Comp_Type if composite.
+
+      elsif Is_Record_Type (Comp_Type) or else Is_Array_Type (Comp_Type) then
          if Present (Comp) and then Chars (Comp) = Name_uParent then
             if Reverse_Storage_Order (Encl_Type)
                  /=
@@ -1142,6 +1160,9 @@
                & "storage order as enclosing composite", Err_Node);
          end if;
 
+      --  Enclosing type has explicit SSO, non-composite component must not
+      --  be aliased.
+
       elsif Component_Aliased then
          Error_Msg_N
            ("aliased component not permitted for type with "
@@ -2312,11 +2333,12 @@
 
             --  Check for scalar storage order
 
-            if Present (Get_Attribute_Definition_Clause
-                        (Arr, Attribute_Scalar_Storage_Order))
-            then
-               Check_Component_Storage_Order (Arr, Empty);
-            end if;
+            Check_Component_Storage_Order
+              (Encl_Type => Arr,
+               Comp      => Empty,
+               ADC       => Get_Attribute_Definition_Clause
+                              (First_Subtype (Arr),
+                               Attribute_Scalar_Storage_Order));
 
             --  Processing that is done only for subtypes
 
@@ -2999,15 +3021,16 @@
                  ("??scalar storage order specified but no component clause",
                   ADC);
             end if;
+         end if;
 
-            --  Check attribute on component types
+         --  Check consistent attribute setting on component types
 
-            Comp := First_Component (Rec);
-            while Present (Comp) loop
-               Check_Component_Storage_Order (Rec, Comp);
-               Next_Component (Comp);
-            end loop;
-         end if;
+         Comp := First_Component (Rec);
+         while Present (Comp) loop
+            Check_Component_Storage_Order
+              (Encl_Type => Rec, Comp => Comp, ADC => ADC);
+            Next_Component (Comp);
+         end loop;
 
          --  Deal with Bit_Order aspect specifying a non-default bit order
 

Reply via email to