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 <[email protected]>
* 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