From 90a000b848389c45b4043da420968aac97b1e152 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 28 May 2019 07:40:07 +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: r271682 --- 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 d0b67375b18e..fe2870107aa1 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-27 Eric Botcazou * gcc-interface/trans.c (Call_to_gnu): Do not initialize the temporary diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index ed015baa57f6..5d95d9aee49d 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 ab8b93abf5ff..2290f0413d59 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -1860,6 +1860,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)) @@ -1901,9 +1904,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 @@ -1938,18 +1939,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: @@ -2230,13 +2231,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; @@ -2244,7 +2244,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); } @@ -2253,11 +2253,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 e7b8b575a601..31b52c22aec2 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-27 Eric Botcazou * gnat.dg/specs/array4.ads: 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 000000000000..c265723ec470 --- /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.47.2