re PR c/83844 (ICE with warn_if_not_aligned attribute)
authorJakub Jelinek <jakub@redhat.com>
Tue, 16 Jan 2018 15:08:32 +0000 (16:08 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 16 Jan 2018 15:08:32 +0000 (16:08 +0100)
PR c/83844
* stor-layout.c (handle_warn_if_not_align): Use byte_position and
multiple_of_p instead of unchecked tree_to_uhwi and UHWI check.
If off is not INTEGER_CST, issue a may not be aligned warning
rather than isn't aligned.  Use isn%'t rather than isn't.
* fold-const.c (multiple_of_p) <case BIT_AND_EXPR>: Don't fall through
into MULT_EXPR.
<case MULT_EXPR>: Improve the case when bottom and one of the
MULT_EXPR operands are INTEGER_CSTs and bottom is multiple of that
operand, in that case check if the other operand is multiple of
bottom divided by the INTEGER_CST operand.

* gcc.dg/pr83844.c: New test.

From-SVN: r256745

gcc/ChangeLog
gcc/fold-const.c
gcc/stor-layout.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr83844.c [new file with mode: 0644]

index abe3295e61e9756e67ff61120a418f7a741f8509..9b7bf83cb770fd1c5df90fc9a9be5424f0f3f3e9 100644 (file)
@@ -1,3 +1,17 @@
+2018-01-16  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/83844
+       * stor-layout.c (handle_warn_if_not_align): Use byte_position and
+       multiple_of_p instead of unchecked tree_to_uhwi and UHWI check.
+       If off is not INTEGER_CST, issue a may not be aligned warning
+       rather than isn't aligned.  Use isn%'t rather than isn't.
+       * fold-const.c (multiple_of_p) <case BIT_AND_EXPR>: Don't fall through
+       into MULT_EXPR.
+       <case MULT_EXPR>: Improve the case when bottom and one of the
+       MULT_EXPR operands are INTEGER_CSTs and bottom is multiple of that
+       operand, in that case check if the other operand is multiple of
+       bottom divided by the INTEGER_CST operand.
+
 2018-01-16  Richard Sandiford  <richard.sandiford@linaro.org>
 
        PR target/83858
index 5cf20521daf9b0067212b689a2645df587785673..1ea37666131266f3d8ad1fa00fc6f43a4ccec254 100644 (file)
@@ -12595,9 +12595,34 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
         a multiple of BOTTOM then TOP is a multiple of BOTTOM.  */
       if (!integer_pow2p (bottom))
        return 0;
-      /* FALLTHRU */
+      return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
+             || multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
 
     case MULT_EXPR:
+      if (TREE_CODE (bottom) == INTEGER_CST)
+       {
+         op1 = TREE_OPERAND (top, 0);
+         op2 = TREE_OPERAND (top, 1);
+         if (TREE_CODE (op1) == INTEGER_CST)
+           std::swap (op1, op2);
+         if (TREE_CODE (op2) == INTEGER_CST)
+           {
+             if (multiple_of_p (type, op2, bottom))
+               return 1;
+             /* Handle multiple_of_p ((x * 2 + 2) * 4, 8).  */
+             if (multiple_of_p (type, bottom, op2))
+               {
+                 widest_int w = wi::sdiv_trunc (wi::to_widest (bottom),
+                                                wi::to_widest (op2));
+                 if (wi::fits_to_tree_p (w, TREE_TYPE (bottom)))
+                   {
+                     op2 = wide_int_to_tree (TREE_TYPE (bottom), w);
+                     return multiple_of_p (type, op1, op2);
+                   }
+               }
+             return multiple_of_p (type, op1, bottom);
+           }
+       }
       return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
              || multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
 
index 0f65e166411dab479291b0ad4ab431516d0271a1..8c415ebb6ac8e04478c671385e2d4e70a27bfc5d 100644 (file)
@@ -1150,12 +1150,16 @@ handle_warn_if_not_align (tree field, unsigned int record_align)
     warning (opt_w, "alignment %u of %qT is less than %u",
             record_align, context, warn_if_not_align);
 
-  unsigned HOST_WIDE_INT off
-    = (tree_to_uhwi (DECL_FIELD_OFFSET (field))
-       + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field)) / BITS_PER_UNIT);
-  if ((off % warn_if_not_align) != 0)
-    warning (opt_w, "%q+D offset %wu in %qT isn't aligned to %u",
-            field, off, context, warn_if_not_align);
+  tree off = byte_position (field);
+  if (!multiple_of_p (TREE_TYPE (off), off, size_int (warn_if_not_align)))
+    {
+      if (TREE_CODE (off) == INTEGER_CST)
+       warning (opt_w, "%q+D offset %E in %qT isn%'t aligned to %u",
+                field, off, context, warn_if_not_align);
+      else
+       warning (opt_w, "%q+D offset %E in %qT may not be aligned to %u",
+                field, off, context, warn_if_not_align);
+    }
 }
 
 /* Called from place_field to handle unions.  */
index 9bc4d7be97c9b7b01b607b800078670771a994c1..ec9f4695cc315c7695b62f98948c48f3240a01be 100644 (file)
@@ -1,3 +1,8 @@
+2018-01-16  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/83844
+       * gcc.dg/pr83844.c: New test.
+
 2018-01-16  Richard Sandiford  <richard.sandiford@linaro.org>
 
        * gcc.dg/torture/pr83847.c: New test.
diff --git a/gcc/testsuite/gcc.dg/pr83844.c b/gcc/testsuite/gcc.dg/pr83844.c
new file mode 100644 (file)
index 0000000..c6db68a
--- /dev/null
@@ -0,0 +1,36 @@
+/* PR c/83844 */
+/* { dg-do compile } */
+/* { dg-options "-O0 -Wall" } */
+
+typedef unsigned long long __u64 __attribute__((aligned(4),warn_if_not_aligned(8)));
+void bar (void *, void *, void *);
+
+void
+foo (int n)
+{
+  struct A
+  {
+    int i1;
+    int i2;
+    int i3[n];
+    __u64 x;   /* { dg-warning "in 'struct A' may not be aligned to 8" } */
+  } __attribute__((aligned (8)));
+  struct B
+  {
+    int i1;
+    int i2;
+    long long i3[n];
+    __u64 x;
+  } __attribute__((aligned (8)));
+  struct C
+  {
+    int i1;
+    int i2;
+    int i3[2 * n];
+    __u64 x;
+  } __attribute__((aligned (8)));
+  struct A a;
+  struct B b;
+  struct C c;
+  bar (&a, &b, &c);
+}