]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
decl.c (components_to_record): Set a name on the type created for the REP part, if...
authorEric Botcazou <ebotcazou@adacore.com>
Tue, 28 May 2019 07:36:02 +0000 (07:36 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Tue, 28 May 2019 07:36:02 +0000 (07:36 +0000)
* 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
gcc/ada/gcc-interface/decl.c
gcc/ada/gcc-interface/utils.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/specs/discr5.ads [new file with mode: 0644]

index 6acef36fbf0805975df9cd9c01302498166a7c4a..8c22c322a2c5c375138ae64054a48881e114f6a4 100644 (file)
@@ -1,3 +1,11 @@
+2019-05-28  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * 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  <ebotcazou@adacore.com>
 
        * gcc-interface/utils.c (gnat_internal_attribute_table): Add support
index 9082d44ea5c3b922cd0761db42be70c442c2c4a9..dc23743b55f5895bd756f99607a8b08e5eec4d9f 100644 (file)
@@ -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);
index d090d0954ac1c3cbaf7f01bcdd549309ac105475..dbf7c1825060665af9cd0003f85ccba5e3457d21 100644 (file)
@@ -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
index 633ecfc5b317278d989fd6ce7ad8661e0861270e..0bf055b25f582def2233447722a8db293306b876 100644 (file)
@@ -1,3 +1,7 @@
+2019-05-28  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/specs/discr5.ads: New test.
+
 2019-05-28  Eric Botcazou  <ebotcazou@adacore.com>
 
        * 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 (file)
index 0000000..c265723
--- /dev/null
@@ -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;