From: Eric Botcazou Date: Wed, 26 Oct 2011 20:45:09 +0000 (+0000) Subject: decl.c (gnat_to_gnu_entity): Try to make a packable type for fields of union types... X-Git-Tag: releases/gcc-4.7.0~2786 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e1e5852c9f5e3c4327b0dbfbd255145a3702ff6b;p=thirdparty%2Fgcc.git decl.c (gnat_to_gnu_entity): Try to make a packable type for fields of union types as well. * gcc-interface/decl.c (gnat_to_gnu_entity) : Try to make a packable type for fields of union types as well. : Use RECORD_OR_UNION_TYPE_P predicate. (gnat_to_gnu_component_type): Try to make a packable type for fields of union types as well. (make_packable_type): Use RECORD_OR_UNION_TYPE_P predicate. (maybe_pad_type): Try to make a packable type for fields of union types as well. (gnat_to_gnu_field): Likewise. (is_variable_size): Use RECORD_OR_UNION_TYPE_P predicate. (set_rm_size): Likewise. (rm_size): Likewise. * gcc-interface/misc.c (gnat_type_max_size): Likewise. * gcc-interface/trans.c (add_decl_expr): Likewise. * gcc-interface/utils.c (finish_record_type): Likewise. * gcc-interface/utils2.c (build_simple_component_ref): Likewise. From-SVN: r180540 --- diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 3bd55bffb8b1..53ea8c575c63 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,23 @@ + +2011-10-26 Eric Botcazou + + * gcc-interface/decl.c (gnat_to_gnu_entity) : Try to + make a packable type for fields of union types as well. + : Use RECORD_OR_UNION_TYPE_P predicate. + (gnat_to_gnu_component_type): Try to make a packable type for fields + of union types as well. + (make_packable_type): Use RECORD_OR_UNION_TYPE_P predicate. + (maybe_pad_type): Try to make a packable type for fields of union types + as well. + (gnat_to_gnu_field): Likewise. + (is_variable_size): Use RECORD_OR_UNION_TYPE_P predicate. + (set_rm_size): Likewise. + (rm_size): Likewise. + * gcc-interface/misc.c (gnat_type_max_size): Likewise. + * gcc-interface/trans.c (add_decl_expr): Likewise. + * gcc-interface/utils.c (finish_record_type): Likewise. + * gcc-interface/utils2.c (build_simple_component_ref): Likewise. + 2011-10-26 Eric Botcazou * gcc-interface/decl.c (gnat_to_gnu_field): Always check components diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index d6bfe9c23587..9c7c318ced57 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -3302,7 +3302,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) == INTEGER_CST) { gnu_size = DECL_SIZE (gnu_old_field); - if (TREE_CODE (gnu_field_type) == RECORD_TYPE + if (RECORD_OR_UNION_TYPE_P (gnu_field_type) && !TYPE_FAT_POINTER_P (gnu_field_type) && host_integerp (TYPE_SIZE (gnu_field_type), 1)) gnu_field_type @@ -4645,13 +4645,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) tree size; /* If a size was specified, take it into account. Otherwise - use the RM size for records as the type size has already - been adjusted to the alignment. */ + use the RM size for records or unions as the type size has + already been adjusted to the alignment. */ if (gnu_size) size = gnu_size; - else if ((TREE_CODE (gnu_type) == RECORD_TYPE - || TREE_CODE (gnu_type) == UNION_TYPE - || TREE_CODE (gnu_type) == QUAL_UNION_TYPE) + else if (RECORD_OR_UNION_TYPE_P (gnu_type) && !TYPE_FAT_POINTER_P (gnu_type)) size = rm_size (gnu_type); else @@ -5300,7 +5298,7 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition, && !Is_Bit_Packed_Array (gnat_array) && !Has_Aliased_Components (gnat_array) && !Strict_Alignment (gnat_type) - && TREE_CODE (gnu_type) == RECORD_TYPE + && RECORD_OR_UNION_TYPE_P (gnu_type) && !TYPE_FAT_POINTER_P (gnu_type) && host_integerp (TYPE_SIZE (gnu_type), 1)) gnu_type = make_packable_type (gnu_type, false); @@ -6357,9 +6355,7 @@ make_packable_type (tree type, bool in_record) tree new_field_type = TREE_TYPE (old_field); tree new_field, new_size; - if ((TREE_CODE (new_field_type) == RECORD_TYPE - || TREE_CODE (new_field_type) == UNION_TYPE - || TREE_CODE (new_field_type) == QUAL_UNION_TYPE) + if (RECORD_OR_UNION_TYPE_P (new_field_type) && !TYPE_FAT_POINTER_P (new_field_type) && host_integerp (TYPE_SIZE (new_field_type), 1)) new_field_type = make_packable_type (new_field_type, true); @@ -6369,9 +6365,7 @@ make_packable_type (tree type, bool in_record) packable version of the record type, see finish_record_type. */ if (!DECL_CHAIN (old_field) && !TYPE_PACKED (type) - && (TREE_CODE (new_field_type) == RECORD_TYPE - || TREE_CODE (new_field_type) == UNION_TYPE - || TREE_CODE (new_field_type) == QUAL_UNION_TYPE) + && RECORD_OR_UNION_TYPE_P (new_field_type) && !TYPE_FAT_POINTER_P (new_field_type) && !TYPE_CONTAINS_TEMPLATE_P (new_field_type) && TYPE_ADA_SIZE (new_field_type)) @@ -6533,7 +6527,7 @@ maybe_pad_type (tree type, tree size, unsigned int align, between them and it might be hard to overcome afterwards, including at the RTL level when the stand-alone object is accessed as a whole. */ if (align != 0 - && TREE_CODE (type) == RECORD_TYPE + && RECORD_OR_UNION_TYPE_P (type) && TYPE_MODE (type) == BLKmode && !TREE_ADDRESSABLE (type) && TREE_CODE (orig_size) == INTEGER_CST @@ -6833,7 +6827,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed, effects on the outer record type. A typical case is a field known to be byte-aligned and not to share a byte with another field. */ if (!needs_strict_alignment - && TREE_CODE (gnu_field_type) == RECORD_TYPE + && RECORD_OR_UNION_TYPE_P (gnu_field_type) && !TYPE_FAT_POINTER_P (gnu_field_type) && host_integerp (TYPE_SIZE (gnu_field_type), 1) && (packed == 1 @@ -7047,9 +7041,7 @@ is_variable_size (tree type) && !TREE_CONSTANT (DECL_SIZE (TYPE_FIELDS (type)))) return true; - if (TREE_CODE (type) != RECORD_TYPE - && TREE_CODE (type) != UNION_TYPE - && TREE_CODE (type) != QUAL_UNION_TYPE) + if (!RECORD_OR_UNION_TYPE_P (type)) return false; for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) @@ -8090,9 +8082,7 @@ set_rm_size (Uint uint_size, tree gnu_type, Entity_Id gnat_entity) SET_TYPE_RM_SIZE (gnu_type, size); /* ...or the Ada size for record and union types. */ - else if ((TREE_CODE (gnu_type) == RECORD_TYPE - || TREE_CODE (gnu_type) == UNION_TYPE - || TREE_CODE (gnu_type) == QUAL_UNION_TYPE) + else if (RECORD_OR_UNION_TYPE_P (gnu_type) && !TYPE_FAT_POINTER_P (gnu_type)) SET_TYPE_ADA_SIZE (gnu_type, size); } @@ -8944,10 +8934,8 @@ rm_size (tree gnu_type) rm_size (TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (gnu_type)))), DECL_SIZE (TYPE_FIELDS (gnu_type))); - /* For record types, we store the size explicitly. */ - if ((TREE_CODE (gnu_type) == RECORD_TYPE - || TREE_CODE (gnu_type) == UNION_TYPE - || TREE_CODE (gnu_type) == QUAL_UNION_TYPE) + /* For record or union types, we store the size explicitly. */ + if (RECORD_OR_UNION_TYPE_P (gnu_type) && !TYPE_FAT_POINTER_P (gnu_type) && TYPE_ADA_SIZE (gnu_type)) return TYPE_ADA_SIZE (gnu_type); diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c index a2de256b1dc1..4b2fba0c191a 100644 --- a/gcc/ada/gcc-interface/misc.c +++ b/gcc/ada/gcc-interface/misc.c @@ -556,9 +556,8 @@ gnat_type_max_size (const_tree gnu_type) /* If we don't have a constant, see what we can get from TYPE_ADA_SIZE, which should stay untouched. */ if (!host_integerp (max_unitsize, 1) - && (TREE_CODE (gnu_type) == RECORD_TYPE - || TREE_CODE (gnu_type) == UNION_TYPE - || TREE_CODE (gnu_type) == QUAL_UNION_TYPE) + && RECORD_OR_UNION_TYPE_P (gnu_type) + && !TYPE_FAT_POINTER_P (gnu_type) && TYPE_ADA_SIZE (gnu_type)) { tree max_adasize = max_size (TYPE_ADA_SIZE (gnu_type), true); diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index df10c9133955..1f43f4dcc943 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -6754,10 +6754,8 @@ add_decl_expr (tree gnu_decl, Entity_Id gnat_entity) } /* In any case, we have to deal with our own TYPE_ADA_SIZE field. */ else if (TREE_CODE (gnu_decl) == TYPE_DECL - && ((TREE_CODE (type) == RECORD_TYPE - && !TYPE_FAT_POINTER_P (type)) - || TREE_CODE (type) == UNION_TYPE - || TREE_CODE (type) == QUAL_UNION_TYPE)) + && RECORD_OR_UNION_TYPE_P (type) + && !TYPE_FAT_POINTER_P (type)) MARK_VISITED (TYPE_ADA_SIZE (type)); } else if (!DECL_EXTERNAL (gnu_decl)) diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 272c192dbeec..73657528a8a0 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -726,9 +726,7 @@ finish_record_type (tree record_type, tree field_list, int rep_level, tree this_size = DECL_SIZE (field); tree this_ada_size; - if ((TREE_CODE (type) == RECORD_TYPE - || TREE_CODE (type) == UNION_TYPE - || TREE_CODE (type) == QUAL_UNION_TYPE) + if (RECORD_OR_UNION_TYPE_P (type) && !TYPE_FAT_POINTER_P (type) && !TYPE_CONTAINS_TEMPLATE_P (type) && TYPE_ADA_SIZE (type)) diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c index 10d12ef7ea30..4075a27014c1 100644 --- a/gcc/ada/gcc-interface/utils2.c +++ b/gcc/ada/gcc-interface/utils2.c @@ -1748,9 +1748,7 @@ build_simple_component_ref (tree record_variable, tree component, tree record_type = TYPE_MAIN_VARIANT (TREE_TYPE (record_variable)); tree ref, inner_variable; - gcc_assert ((TREE_CODE (record_type) == RECORD_TYPE - || TREE_CODE (record_type) == UNION_TYPE - || TREE_CODE (record_type) == QUAL_UNION_TYPE) + gcc_assert (RECORD_OR_UNION_TYPE_P (record_type) && COMPLETE_TYPE_P (record_type) && (component == NULL_TREE) != (field == NULL_TREE)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 89819e6d9193..d8380fbb6342 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2011-10-26 Eric Botcazou + + * gnat.dg/specs/unchecked_union.ads: Rename to... + * gnat.dg/specs/unchecked_union1.ads: ...this. + * gnat.dg/specs/unchecked_union2.ads: New test. + 2011-10-26 Eric Botcazou * gnat.dg/specs/atomic1.ads: New test. diff --git a/gcc/testsuite/gnat.dg/specs/unchecked_union.ads b/gcc/testsuite/gnat.dg/specs/unchecked_union1.ads similarity index 88% rename from gcc/testsuite/gnat.dg/specs/unchecked_union.ads rename to gcc/testsuite/gnat.dg/specs/unchecked_union1.ads index 260f781d89d7..06313ef88c4e 100644 --- a/gcc/testsuite/gnat.dg/specs/unchecked_union.ads +++ b/gcc/testsuite/gnat.dg/specs/unchecked_union1.ads @@ -6,7 +6,7 @@ with Interfaces; use Interfaces; -package Unchecked_Union is +package Unchecked_Union1 is type Mode_Type is (Mode_B2); type Value_Union (Mode : Mode_Type := Mode_B2) is record @@ -17,4 +17,4 @@ package Unchecked_Union is end record; pragma Unchecked_Union (Value_Union); -end Unchecked_Union; +end Unchecked_Union1; diff --git a/gcc/testsuite/gnat.dg/specs/unchecked_union2.ads b/gcc/testsuite/gnat.dg/specs/unchecked_union2.ads new file mode 100644 index 000000000000..f13421cc4748 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/unchecked_union2.ads @@ -0,0 +1,30 @@ +-- { dg-do compile } + +package Unchecked_Union2 is + + type Small_Int is range 0 .. 2**19 - 1; + + type R1 (B : Boolean := True) is record + case B is + when True => Data1 : Small_Int; + when False => Data2 : Small_Int; + end case; + end record; + + for R1 use record + Data1 at 0 range 0 .. 18; + Data2 at 0 range 0 .. 18; + end record; + for R1'Size use 24; + + pragma Unchecked_Union (R1); + + type R2 is record + Data : R1; + end record; + + for R2 use record + Data at 0 range 3 .. 26; + end record; + +end Unchecked_Union2;