This patch reworks the handling when the alignment is not set
but the size is set. Basically in this case, we always set a
reasonable alignment from the size. This is true even if the
size is confirming (we really have no way of telling if a size
clause is or is not confirming in the general case).
And in the case where neither size nor alignment is set for
a subtype or derived type, we inherit both object size and
alignment from the parent type. This avoids some anomolies
that were previously showing up.
The following example:
1. package Pkg is
2. type Time_Xtype is delta 0.1 range 0.0 .. 999_999.9;
3. for Time_Xtype'Small use 0.1;
4. for Time_Xtype'Size use 24;
5. for Time_Xtype'Alignment use 1;
6.
7. subtype Ddc_Delay_Stype is Time_Xtype range 0.0 .. 51.1;
8. end;
Was one of the anomolous cases, the result of -gnatR2 is
Representation information for unit Pkg (spec)
for Time_Xtype'Object_Size use 32;
for Time_Xtype'Value_Size use 24;
for Time_Xtype'Alignment use 1;
for Time_Xtype'Small use 0.1;
for Time_Xtype'Range use 0.0 .. 999999.9;
for Ddc_Delay_Stype'Object_Size use 32;
for Ddc_Delay_Stype'Value_Size use 9;
for Ddc_Delay_Stype'Alignment use 1;
for Ddc_Delay_Stype'Small use 0.1;
for Ddc_Delay_Stype'Range use 0.0 .. 51.1;
Previously the subtype Ddc_Delay had an alignment of 4, which was
definitely strange. The impact of this change is small, it had no
visible effect on our entire test suite.
Tested on x86_64-pc-linux-gnu, committed on trunk
2011-11-21 Robert Dewar <[email protected]>
* freeze.adb (Freeze_Enumeration_Type): Make sure to set both
size and alignment for foreign convention enumeration types.
* layout.adb (Set_Elem_Alignment): Redo setting of alignment
when size is set.
Index: layout.adb
===================================================================
--- layout.adb (revision 181556)
+++ layout.adb (working copy)
@@ -3088,7 +3088,7 @@
end if;
-- Here we calculate the alignment as the largest power of two multiple
- -- of System.Storage_Unit that does not exceed either the actual size of
+ -- of System.Storage_Unit that does not exceed either the object size of
-- the type, or the maximum allowed alignment.
declare
@@ -3126,21 +3126,101 @@
A := 2 * A;
end loop;
- -- Now we think we should set the alignment to A, but we skip this if
- -- an alignment is already set to a value greater than A (happens for
- -- derived types).
+ -- If alignment is currently not set, then we can safetly set it to
+ -- this new calculated value.
- -- However, if the alignment is known and too small it must be
- -- increased, this happens in a case like:
+ if Unknown_Alignment (E) then
+ Init_Alignment (E, A);
- -- type R is new Character;
- -- for R'Size use 16;
+ -- Cases where we have inherited an alignment
- -- Here the alignment inherited from Character is 1, but it must be
- -- increased to 2 to reflect the increased size.
+ -- For constructed types, always reset the alignment, these are
+ -- Generally invisible to the user anyway, and that way we are
+ -- sure that no constructed types have weird alignments.
- if Unknown_Alignment (E) or else Alignment (E) < A then
+ elsif not Comes_From_Source (E) then
Init_Alignment (E, A);
+
+ -- If this inherited alignment is the same as the one we computed,
+ -- then obviously everything is fine, and we do not need to reset it.
+
+ elsif Alignment (E) = A then
+ null;
+
+ -- Now we come to the difficult cases where we have inherited an
+ -- alignment and size, but overridden the size but not the alignment.
+
+ elsif Has_Size_Clause (E) or else Has_Object_Size_Clause (E) then
+
+ -- This is tricky, it might be thought that we should try to
+ -- inherit the alignment, since that's what the RM implies, but
+ -- that leads to complex rules and oddities. Consider for example:
+
+ -- type R is new Character;
+ -- for R'Size use 16;
+
+ -- It seems quite bogus in this case to inherit an alignment of 1
+ -- from the parent type Character. Furthermore, if that's what the
+ -- programmer really wanted for some odd reason, then they could
+ -- specify the alignment they wanted.
+
+ -- Furthermore we really don't want to inherit the alignment in
+ -- the case of a specified Object_Size for a subtype, since then
+ -- there would be no way of overriding to give a reasonable value
+ -- (we don't have an Object_Subtype attribute). Consider:
+
+ -- subtype R is new Character;
+ -- for R'Object_Size use 16;
+
+ -- If we inherit the alignment of 1, then we have an odd
+ -- inefficient alignment for the subtype, which cannot be fixed.
+
+ -- So we make the decision that if Size (or Object_Size) is given
+ -- (and, in the case of a first subtype, the alignment is not set
+ -- with a specific alignment clause). We reset the alignment to
+ -- the appropriate value for the specified size. This is a nice
+ -- simple rule to implement and document.
+
+ -- There is one slight glitch, which is that a confirming size
+ -- clause can now change the alignment, which, if we really think
+ -- that confirming rep clauses should have no effect, is a no-no.
+
+ -- type R is new Character;
+ -- for R'Alignment use 2;
+ -- type S is new R;
+ -- for S'Size use Character'Size;
+
+ -- Now the alignment of S is 1 instead of 2, as a result of
+ -- applying the above rule to the confirming rep clause for S. Not
+ -- clear this is worth worrying about. If we recorded whether a
+ -- size clause was confirming we could avoid this, but right now
+ -- we have no way of doing that or easily figuring it out, so we
+ -- don't bother.
+
+ -- Historical note. In versions of GNAT prior to Nov 6th, 2010, an
+ -- odd distinction was made between inherited alignments greater
+ -- than the computed alignment (where the larger alignment was
+ -- inherited) and inherited alignments smaller than the computed
+ -- alignment (where the smaller alignment was overridden). This
+ -- was a dubious fix to get around an ACATS problem which seems
+ -- to have disappeared anyway, and in any case, this peculiarity
+ -- was never documented.
+
+ Init_Alignment (E, A);
+
+ -- If no Size (or Object_Size) was specified, then we inherited the
+ -- object size, so we should inherit the alignment as well and not
+ -- modify it. This takes care of cases like:
+
+ -- type R is new Integer;
+ -- for R'Alignment use 1;
+ -- subtype S is R;
+
+ -- Here we have R has a default Object_Size of 32, and a specified
+ -- alignment of 1, and it seeems right for S to inherit both values.
+
+ else
+ null;
end if;
end;
end Set_Elem_Alignment;
Index: freeze.adb
===================================================================
--- freeze.adb (revision 181556)
+++ freeze.adb (working copy)
@@ -4239,7 +4239,8 @@
-- By default, if no size clause is present, an enumeration type with
-- Convention C is assumed to interface to a C enum, and has integer
-- size. This applies to types. For subtypes, verify that its base
- -- type has no size clause either.
+ -- type has no size clause either. Treat other foreign conventions
+ -- in the same way, and also make sure alignment is set right.
if Has_Foreign_Convention (Typ)
and then not Has_Size_Clause (Typ)
@@ -4247,6 +4248,7 @@
and then Esize (Typ) < Standard_Integer_Size
then
Init_Esize (Typ, Standard_Integer_Size);
+ Set_Alignment (Typ, Alignment (Standard_Integer));
else
-- If the enumeration type interfaces to C, and it has a size clause