Fix bogus alignment warning on address clause
authorEric Botcazou <ebotcazou@adacore.com>
Mon, 28 Sep 2020 07:00:46 +0000 (09:00 +0200)
committerEric Botcazou <ebotcazou@adacore.com>
Mon, 28 Sep 2020 07:32:27 +0000 (09:32 +0200)
The compiler gives a bogus alignment warning on an address clause and
a discriminated record type with variable size.

gcc/ada/ChangeLog:
* gcc-interface/decl.c (maybe_saturate_size): Add ALIGN parameter
and round down the result to ALIGN.
(gnat_to_gnu_entity): Adjust calls to maybe_saturate_size.

gcc/testsuite/ChangeLog:
* gnat.dg/addr16.adb: New test.
* gnat.dg/addr16_pkg.ads: New helper.

gcc/ada/gcc-interface/decl.c
gcc/testsuite/gnat.dg/addr16.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/addr16_pkg.ads [new file with mode: 0644]

index c9c2a95170f36c8d1fc0fd00c0b074b8ed02bb89..cd0a50b2083d5cc96ac80bfc69eccf6111d405a5 100644 (file)
@@ -232,7 +232,7 @@ static tree build_position_list (tree, bool, tree, tree, unsigned int, tree);
 static vec<subst_pair> build_subst_list (Entity_Id, Entity_Id, bool);
 static vec<variant_desc> build_variant_list (tree, Node_Id, vec<subst_pair>,
                                             vec<variant_desc>);
-static tree maybe_saturate_size (tree);
+static tree maybe_saturate_size (tree, unsigned int align);
 static tree validate_size (Uint, tree, Entity_Id, enum tree_code, bool, bool,
                           const char *, const char *);
 static void set_rm_size (Uint, tree, Entity_Id);
@@ -4425,7 +4425,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
          /* If the size is self-referential, annotate the maximum value
             after saturating it, if need be, to avoid a No_Uint value.  */
          if (CONTAINS_PLACEHOLDER_P (gnu_size))
-           gnu_size = maybe_saturate_size (max_size (gnu_size, true));
+           {
+             const unsigned int align
+               = UI_To_Int (Alignment (gnat_entity)) * BITS_PER_UNIT;
+             gnu_size
+               = maybe_saturate_size (max_size (gnu_size, true), align);
+           }
 
          /* If we are just annotating types and the type is tagged, the tag
             and the parent components are not generated by the front-end so
@@ -4461,7 +4466,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
                  gnu_size = size_binop (PLUS_EXPR, gnu_size, offset);
                }
 
-             gnu_size = maybe_saturate_size (round_up (gnu_size, align));
+             gnu_size
+               = maybe_saturate_size (round_up (gnu_size, align), align);
              Set_Esize (gnat_entity, annotate_value (gnu_size));
 
              /* Tagged types are Strict_Alignment so RM_Size = Esize.  */
@@ -8946,15 +8952,21 @@ build_variant_list (tree gnu_qual_union_type, Node_Id gnat_variant_part,
 }
 \f
 /* If SIZE has overflowed, return the maximum valid size, which is the upper
-   bound of the signed sizetype in bits; otherwise return SIZE unmodified.  */
+   bound of the signed sizetype in bits, rounded down to ALIGN.  Otherwise
+   return SIZE unmodified.  */
 
 static tree
-maybe_saturate_size (tree size)
+maybe_saturate_size (tree size, unsigned int align)
 {
   if (TREE_CODE (size) == INTEGER_CST && TREE_OVERFLOW (size))
-    size = size_binop (MULT_EXPR,
-                      fold_convert (bitsizetype, TYPE_MAX_VALUE (ssizetype)),
-                      build_int_cst (bitsizetype, BITS_PER_UNIT));
+    {
+      size
+       = size_binop (MULT_EXPR,
+                     fold_convert (bitsizetype, TYPE_MAX_VALUE (ssizetype)),
+                     build_int_cst (bitsizetype, BITS_PER_UNIT));
+      size = round_down (size, align);
+    }
+
   return size;
 }
 
diff --git a/gcc/testsuite/gnat.dg/addr16.adb b/gcc/testsuite/gnat.dg/addr16.adb
new file mode 100644 (file)
index 0000000..8f09da0
--- /dev/null
@@ -0,0 +1,14 @@
+-- { dg-do compile }
+
+with Addr16_Pkg; use Addr16_Pkg;
+
+procedure Addr16 (R : Rec) is
+
+  pragma Unsuppress (Alignment_Check);
+
+  B : Integer;
+  for B'Address use R.A'Address;
+
+begin
+  null;
+end;
diff --git a/gcc/testsuite/gnat.dg/addr16_pkg.ads b/gcc/testsuite/gnat.dg/addr16_pkg.ads
new file mode 100644 (file)
index 0000000..9a1b9e3
--- /dev/null
@@ -0,0 +1,9 @@
+package Addr16_Pkg is
+
+  type Arr is array (Positive range <>) of Long_Long_Integer;
+
+  type Rec (D : Positive) is record
+    A : Arr (1 .. D);
+  end record;
+
+end Addr16_Pkg;