aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2018-01-16 16:08:32 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2018-01-16 16:08:32 +0100
commit38943500babbfda935c1108a16ecbb03cb1a33e8 (patch)
tree8c56b282c07c85b373c44f431ced983c5995758c
parent42b394ff00b100d2c968db6478c87a259333ccec (diff)
downloadgcc-38943500babbfda935c1108a16ecbb03cb1a33e8.zip
gcc-38943500babbfda935c1108a16ecbb03cb1a33e8.tar.gz
gcc-38943500babbfda935c1108a16ecbb03cb1a33e8.tar.bz2
re PR c/83844 (ICE with warn_if_not_aligned attribute)
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
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/fold-const.c27
-rw-r--r--gcc/stor-layout.c16
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr83844.c36
5 files changed, 91 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index abe3295..9b7bf83 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 5cf2052..1ea3766 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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));
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 0f65e16..8c415ebb 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -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. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9bc4d7b..ec9f469 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..c6db68a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr83844.c
@@ -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);
+}