diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2007-11-25 13:37:12 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2007-11-25 13:37:12 +0000 |
commit | f1c8c7eef7349f0aae539bd1b45875ac5bcbaede (patch) | |
tree | c2f30f08a620652b6703d34c9395cbbceb397f12 /gcc | |
parent | 64f6a0efdfa5c03132c45952bd1986a8adc2c19d (diff) | |
download | gcc-f1c8c7eef7349f0aae539bd1b45875ac5bcbaede.zip gcc-f1c8c7eef7349f0aae539bd1b45875ac5bcbaede.tar.gz gcc-f1c8c7eef7349f0aae539bd1b45875ac5bcbaede.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ada/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/ada/decl.c | 70 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/specs/size_clause1.ads | 48 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/specs/size_clause2.ads | 48 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/specs/size_clause3.ads | 50 |
6 files changed, 205 insertions, 28 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index b8f8e24..4f229ba 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,14 @@ +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, diff --git a/gcc/ada/decl.c b/gcc/ada/decl.c index 20b65d2..8cac29a 100644 --- a/gcc/ada/decl.c +++ b/gcc/ada/decl.c @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9ec0be0..6c4f2ac 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +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 diff --git a/gcc/testsuite/gnat.dg/specs/size_clause1.ads b/gcc/testsuite/gnat.dg/specs/size_clause1.ads new file mode 100644 index 0000000..5b8417e --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/size_clause1.ads @@ -0,0 +1,48 @@ +-- { 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; diff --git a/gcc/testsuite/gnat.dg/specs/size_clause2.ads b/gcc/testsuite/gnat.dg/specs/size_clause2.ads new file mode 100644 index 0000000..957d392 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/size_clause2.ads @@ -0,0 +1,48 @@ +-- { 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; diff --git a/gcc/testsuite/gnat.dg/specs/size_clause3.ads b/gcc/testsuite/gnat.dg/specs/size_clause3.ads new file mode 100644 index 0000000..6a89114 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/size_clause3.ads @@ -0,0 +1,50 @@ +-- { 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; |