From f65f371bcff00263f9e870d546b580caebd953b3 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 28 May 2019 07:36:02 +0000 Subject: [PATCH] decl.c (components_to_record): Set a name on the type created for the REP part, if any. * gcc-interface/decl.c (components_to_record): Set a name on the type created for the REP part, if any. * gcc-interface/utils.c (finish_record_type): Only take the maximum when merging sizes for a variant part at offset 0. (merge_sizes): Rename has_rep parameter into max. From-SVN: r271681 --- gcc/ada/ChangeLog | 8 ++++ gcc/ada/gcc-interface/decl.c | 2 + gcc/ada/gcc-interface/utils.c | 38 ++++++++--------- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gnat.dg/specs/discr5.ads | 57 ++++++++++++++++++++++++++ 5 files changed, 90 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/specs/discr5.ads diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 6acef36fbf0..8c22c322a2c 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2019-05-28 Eric Botcazou + + * gcc-interface/decl.c (components_to_record): Set a name on the type + created for the REP part, if any. + * gcc-interface/utils.c (finish_record_type): Only take the maximum + when merging sizes for a variant part at offset 0. + (merge_sizes): Rename has_rep parameter into max. + 2019-05-28 Eric Botcazou * gcc-interface/utils.c (gnat_internal_attribute_table): Add support diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 9082d44ea5c..dc23743b55f 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -8162,6 +8162,8 @@ components_to_record (Node_Id gnat_component_list, Entity_Id gnat_record_type, gnu_field_list = gnu_rep_list; else { + TYPE_NAME (gnu_rep_type) + = create_concat_name (gnat_record_type, "REP"); TYPE_REVERSE_STORAGE_ORDER (gnu_rep_type) = TYPE_REVERSE_STORAGE_ORDER (gnu_record_type); finish_record_type (gnu_rep_type, gnu_rep_list, 1, debug_info); diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index d090d0954ac..dbf7c182506 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -1863,6 +1863,9 @@ finish_record_type (tree record_type, tree field_list, int rep_level, else this_ada_size = this_size; + const bool variant_part = (TREE_CODE (type) == QUAL_UNION_TYPE); + const bool variant_part_at_zero = variant_part && integer_zerop (pos); + /* Clear DECL_BIT_FIELD for the cases layout_decl does not handle. */ if (DECL_BIT_FIELD (field) && operand_equal_p (this_size, TYPE_SIZE (type), 0)) @@ -1904,9 +1907,7 @@ finish_record_type (tree record_type, tree field_list, int rep_level, /* Clear DECL_BIT_FIELD_TYPE for a variant part at offset 0, it's simply not supported by the DECL_BIT_FIELD_REPRESENTATIVE machinery because the variant part is always the last field in the list. */ - if (DECL_INTERNAL_P (field) - && TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE - && integer_zerop (pos)) + if (variant_part_at_zero) DECL_BIT_FIELD_TYPE (field) = NULL_TREE; /* If we still have DECL_BIT_FIELD set at this point, we know that the @@ -1941,18 +1942,18 @@ finish_record_type (tree record_type, tree field_list, int rep_level, case RECORD_TYPE: /* Since we know here that all fields are sorted in order of increasing bit position, the size of the record is one - higher than the ending bit of the last field processed - unless we have a rep clause, since in that case we might - have a field outside a QUAL_UNION_TYPE that has a higher ending - position. So use a MAX in that case. Also, if this field is a - QUAL_UNION_TYPE, we need to take into account the previous size in - the case of empty variants. */ + higher than the ending bit of the last field processed, + unless we have a variant part at offset 0, since in this + case we might have a field outside the variant part that + has a higher ending position; so use a MAX in this case. + Also, if this field is a QUAL_UNION_TYPE, we need to take + into account the previous size in the case of empty variants. */ ada_size - = merge_sizes (ada_size, pos, this_ada_size, - TREE_CODE (type) == QUAL_UNION_TYPE, rep_level > 0); + = merge_sizes (ada_size, pos, this_ada_size, variant_part, + variant_part_at_zero); size - = merge_sizes (size, pos, this_size, - TREE_CODE (type) == QUAL_UNION_TYPE, rep_level > 0); + = merge_sizes (size, pos, this_size, variant_part, + variant_part_at_zero); break; default: @@ -2233,13 +2234,12 @@ rest_of_record_type_compilation (tree record_type) /* Utility function of above to merge LAST_SIZE, the previous size of a record with FIRST_BIT and SIZE that describe a field. SPECIAL is true if this represents a QUAL_UNION_TYPE in which case we must look for COND_EXPRs and - replace a value of zero with the old size. If HAS_REP is true, we take the + replace a value of zero with the old size. If MAX is true, we take the MAX of the end position of this field with LAST_SIZE. In all other cases, we use FIRST_BIT plus SIZE. Return an expression for the size. */ static tree -merge_sizes (tree last_size, tree first_bit, tree size, bool special, - bool has_rep) +merge_sizes (tree last_size, tree first_bit, tree size, bool special, bool max) { tree type = TREE_TYPE (last_size); tree new_size; @@ -2247,7 +2247,7 @@ merge_sizes (tree last_size, tree first_bit, tree size, bool special, if (!special || TREE_CODE (size) != COND_EXPR) { new_size = size_binop (PLUS_EXPR, first_bit, size); - if (has_rep) + if (max) new_size = size_binop (MAX_EXPR, last_size, new_size); } @@ -2256,11 +2256,11 @@ merge_sizes (tree last_size, tree first_bit, tree size, bool special, integer_zerop (TREE_OPERAND (size, 1)) ? last_size : merge_sizes (last_size, first_bit, TREE_OPERAND (size, 1), - 1, has_rep), + 1, max), integer_zerop (TREE_OPERAND (size, 2)) ? last_size : merge_sizes (last_size, first_bit, TREE_OPERAND (size, 2), - 1, has_rep)); + 1, max)); /* We don't need any NON_VALUE_EXPRs and they can confuse us (especially when fed through SUBSTITUTE_IN_EXPR) into thinking that a constant diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 633ecfc5b31..0bf055b25f5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-05-28 Eric Botcazou + + * gnat.dg/specs/discr5.ads: New test. + 2019-05-28 Eric Botcazou * gnat.dg/prefetch1.ad[sb]: New test. diff --git a/gcc/testsuite/gnat.dg/specs/discr5.ads b/gcc/testsuite/gnat.dg/specs/discr5.ads new file mode 100644 index 00000000000..c265723ec47 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/discr5.ads @@ -0,0 +1,57 @@ +-- { dg-do compile } + +with System; + +package Discr5 is + + X, Y : Boolean; + + type R (D : Boolean := False) is tagged limited record + F : Integer; + case D is + when True => + F1, F2 : Integer; + when False => + null; + end case; + end record; + for R use record + F1 at 100 range 0..31; + end record; + + subtype Rt is R(True); + subtype Rf is R(False); + + type R1 (D1 : Boolean) is new R (X) with record + FF : Float; + case D1 is + when True => + F3, F4 : Float; + when False => + null; + end case; + end record; + for R1 use record + F4 at 200 range 0..31; + end record; + + subtype R1t is R1 (True); + subtype R1f is R1 (False); + + type R2 (D2 : Boolean) is new R1 (Y) with record + FFF: System.Address; + case D2 is + when True => + F5, F6: System.Address; + when False => + null; + end case; + end record; + for R2 use record + F6 at 300 range 0..63; + end record; + + subtype R2t is R2 (True); + subtype R2f is R2 (False); + +end Discr5; -- 2.30.2