Commit f1c8c7ee by Eric Botcazou Committed by Eric Botcazou

decl.c (gnat_to_gnu_entity): If the type has strict alignment...

	* decl.c (gnat_to_gnu_entity) <E_Record_Type>: If the type has
	strict alignment, no alignment clause and a known static size, cap
	the type alignment to the greatest power of 2 factor of the size.
	(gnat_to_gnu_field): If the field has a component clause, is aliased
	or of a type with strict alignment, require that its size be equal to
	that of the type.
	(validate_size): Use the type size as the minimum size for a type with
	strict alignment.

From-SVN: r130406
parent 64f6a0ef
2007-11-25 Eric Botcazou <ebotcazou@adacore.com>
* decl.c (gnat_to_gnu_entity) <E_Record_Type>: If the type has
strict alignment, no alignment clause and a known static size, cap
the type alignment to the greatest power of 2 factor of the size.
(gnat_to_gnu_field): If the field has a component clause, is aliased
or of a type with strict alignment, require that its size be equal to
that of the type.
(validate_size): Use the type size as the minimum size for a type with
strict alignment.
2007-11-23 Samuel Tardieu <sam@rfc1149.net>
* s-inmaop-posix.adb, s-intman-vxworks.adb, s-taprop-hpux-dce.adb,
......@@ -2405,12 +2405,15 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
tree gnu_field;
tree gnu_field_list = NULL_TREE;
tree gnu_get_parent;
/* Set PACKED in keeping with gnat_to_gnu_field. */
int packed
= Is_Packed (gnat_entity)
? 1
: Component_Alignment (gnat_entity) == Calign_Storage_Unit
? -1
: Known_Alignment (gnat_entity)
: (Known_Alignment (gnat_entity)
|| (Strict_Alignment (gnat_entity)
&& Known_Static_Esize (gnat_entity)))
? -2
: 0;
bool has_rep = Has_Specified_Layout (gnat_entity);
......@@ -2466,6 +2469,16 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
else if (Is_Atomic (gnat_entity))
TYPE_ALIGN (gnu_type)
= esize >= BITS_PER_WORD ? BITS_PER_WORD : ceil_alignment (esize);
/* If a type needs strict alignment, the minimum size will be the
type size instead of the RM size (see validate_size). Cap the
alignment, lest it causes this type size to become too large. */
else if (Strict_Alignment (gnat_entity)
&& Known_Static_Esize (gnat_entity))
{
unsigned int raw_size = UI_To_Int (Esize (gnat_entity));
TYPE_ALIGN (gnu_type)
= MIN (BIGGEST_ALIGNMENT, raw_size & -raw_size);
}
else
TYPE_ALIGN (gnu_type) = 0;
......@@ -5709,38 +5722,32 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
consistent with the alignment. */
if (needs_strict_alignment)
{
tree gnu_rounded_size = round_up (rm_size (gnu_field_type),
TYPE_ALIGN (gnu_field_type));
TYPE_ALIGN (gnu_record_type)
= MAX (TYPE_ALIGN (gnu_record_type), TYPE_ALIGN (gnu_field_type));
/* If Atomic, the size must match exactly that of the field. */
if ((Is_Atomic (gnat_field) || Is_Atomic (Etype (gnat_field)))
if (gnu_size
&& !operand_equal_p (gnu_size, TYPE_SIZE (gnu_field_type), 0))
{
post_error_ne_tree
("atomic field& must be natural size of type{ (^)}",
Last_Bit (Component_Clause (gnat_field)), gnat_field,
TYPE_SIZE (gnu_field_type));
if (Is_Atomic (gnat_field) || Is_Atomic (Etype (gnat_field)))
post_error_ne_tree
("atomic field& must be natural size of type{ (^)}",
Last_Bit (Component_Clause (gnat_field)), gnat_field,
TYPE_SIZE (gnu_field_type));
else if (Is_Aliased (gnat_field))
post_error_ne_tree
("size of aliased field& must be ^ bits",
Last_Bit (Component_Clause (gnat_field)), gnat_field,
TYPE_SIZE (gnu_field_type));
gnu_size = NULL_TREE;
}
else if (Strict_Alignment (Etype (gnat_field)))
post_error_ne_tree
("size of & with aliased or tagged components not ^ bits",
Last_Bit (Component_Clause (gnat_field)), gnat_field,
TYPE_SIZE (gnu_field_type));
/* If Aliased, the size must match exactly the rounded size. We
used to be more accommodating here and accept greater sizes, but
fully supporting this case on big-endian platforms would require
switching to a more involved layout for the field. */
else if (Is_Aliased (gnat_field)
&& gnu_size
&& ! operand_equal_p (gnu_size, gnu_rounded_size, 0))
{
post_error_ne_tree
("size of aliased field& must be ^ bits",
Last_Bit (Component_Clause (gnat_field)), gnat_field,
gnu_rounded_size);
gnu_size = NULL_TREE;
}
}
if (!integer_zerop (size_binop
(TRUNC_MOD_EXPR, gnu_pos,
......@@ -5763,6 +5770,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
("position of & with aliased or tagged components not multiple of ^ bits",
First_Bit (Component_Clause (gnat_field)), gnat_field,
TYPE_ALIGN (gnu_field_type));
else
gcc_unreachable ();
......@@ -6479,9 +6487,15 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object,
enum tree_code kind, bool component_p, bool zero_ok)
{
Node_Id gnat_error_node;
tree type_size
= kind == VAR_DECL ? TYPE_SIZE (gnu_type) : rm_size (gnu_type);
tree size;
tree type_size, size;
if (kind == VAR_DECL
/* If a type needs strict alignment, a component of this type in
a packed record cannot be packed and thus uses the type size. */
|| (kind == TYPE_DECL && Strict_Alignment (gnat_object)))
type_size = TYPE_SIZE (gnu_type);
else
type_size = rm_size (gnu_type);
/* Find the node to use for errors. */
if ((Ekind (gnat_object) == E_Component
......
2007-11-25 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/specs/size_clause1.ads: New test.
* gnat.dg/specs/size_clause2.ads: Likewise.
* gnat.dg/specs/size_clause3.ads: Likewise.
2007-11-25 Paul Thomas <pault@gcc.gnu.org>
PR fortran/33499
-- { dg-do compile }
package Size_Clause1 is
-- The record inherits the alignment of Integer, which is 4, so
-- the real size is 64 instead of 40. That's OK, as long as the
-- size of a component of type R1 in a packed record is 40.
type R1 is record
I : Integer;
B : Boolean;
end record;
for R1'Size use 40;
type S1 is record
rr : R1; -- size must be 40
end record;
pragma Pack(S1);
-- The record is explicitly given alignment 1 so its real type is 40 too.
-- The size of a component of type R2 in a packed record is naturally 40.
type R2 is record
I : Integer;
B : Boolean;
end record;
for R2'Size use 40;
for R2'Alignment use 1;
type S2 is record
rr : R2; -- size must be 40
end record;
pragma Pack(S2);
-- The record is explicitly given alignment 4 so its real type is 64.
-- That's OK, as long as the size of a component of type R3 in a packed
-- record is 40.
type R3 is record
I : Integer;
B : Boolean;
end record;
for R3'Size use 40;
for R3'Alignment use 4;
type S3 is record
rr : R3; -- size must be 40
end record;
pragma Pack(S3);
end Size_Clause1;
-- { dg-do compile }
package Size_Clause2 is
-- The alignment of the record is capped to the greatest power of 2
-- factor of the size, so that the real size is 40 too and the size
-- of a component of type R1 in a packed record can be 40.
type R1 is record
I : Integer;
B : aliased Boolean;
end record;
for R1'Size use 40;
type S1 is record
rr : R1; -- size must be 40
end record;
pragma Pack(S1);
-- The record is explicitly given alignment 1 so its real type is 40 too.
-- The size of a component of type R2 in a packed record is naturally 40.
type R2 is record
I : Integer;
B : aliased Boolean;
end record;
for R2'Size use 40;
for R2'Alignment use 1;
type S2 is record
rr : R2; -- size must be 40
end record;
pragma Pack(S2);
-- The record is explicitly given alignment 4 so its real type is 64.
-- That's not OK, because the size of a component of type R3 in a packed
-- record cannot be 40 so the size clause is violated.
type R3 is record
I : Integer;
B : aliased Boolean;
end record;
for R3'Size use 40; -- { dg-error "size for .R3. too small" }
for R3'Alignment use 4;
type S3 is record
rr : R3; -- size must be 40
end record;
pragma Pack(S3);
end Size_Clause2;
-- { dg-do compile }
package Size_Clause3 is
-- The record inherits the alignment of Integer, which is 4, so
-- the real size is 64 instead of 40.
type R1 is record
I : Integer;
B : aliased Boolean;
end record;
-- That's not OK, the size of a component of type R1 cannot be 40.
type S1 is record
rr : R1; -- size must be 40
end record;
for S1 use record
rr at 0 range 0 .. 39; -- { dg-error "size of .rr. with aliased or tagged component" }
end record;
-- The record is explicitly given alignment 1 so its real type is 40.
type R2 is record
I : Integer;
B : aliased Boolean;
end record;
for R2'Alignment use 1;
-- That's OK, the size of a component of type R2 can be 40.
type S2 is record
rr : R2; -- size must be 40
end record;
for S2 use record
rr at 0 range 0 .. 39;
end record;
-- The record is explicitly given alignment 4 so its real type is 64.
type R3 is record
I : Integer;
B : aliased Boolean;
end record;
for R3'Alignment use 4;
-- That's not OK, the size of a component of type R3 cannot be 40.
type S3 is record
rr : R3; -- size must be 40
end record;
for S3 use record
rr at 0 range 0 .. 39; -- { dg-error "size of .rr. with aliased or tagged component" }
end record;
end Size_Clause3;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment