re PR tree-optimization/84526 (ICE in generic_overlap at gcc/gimple-ssa-warn-restrict...
authorMartin Sebor <msebor@redhat.com>
Fri, 9 Mar 2018 19:06:26 +0000 (19:06 +0000)
committerJeff Law <law@gcc.gnu.org>
Fri, 9 Mar 2018 19:06:26 +0000 (12:06 -0700)
gcc/ChangeLog:

PR tree-optimization/84526
* gimple-ssa-warn-restrict.c (builtin_memref::set_base_and_offset):
Remove dead code.
(builtin_access::generic_overlap): Be prepared to handle non-array
base objects.

gcc/testsuite/ChangeLog:

PR tree-optimization/84526
* gcc.dg/Wrestrict-10.c: New test.
* gcc.dg/Wrestrict-11.c: New test.

From-SVN: r258394

gcc/ChangeLog
gcc/gimple-ssa-warn-restrict.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/Wrestrict-10.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wrestrict-11.c [new file with mode: 0644]

index 4d0b1592dafa52636ea6bddec374721892842e54..346262eec23f8de9a7a9b19d9b0f7fb3c5e2591a 100644 (file)
@@ -1,3 +1,11 @@
+2018-03-09  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/84526
+       * gimple-ssa-warn-restrict.c (builtin_memref::set_base_and_offset):
+       Remove dead code.
+       (builtin_access::generic_overlap): Be prepared to handle non-array
+       base objects.
+
 2018-03-09  Alexandre Oliva <aoliva@redhat.com>
 
        PR rtl-optimization/84682
index df775062758fcd355f96afac8e433266120a5629..25cc032c2da9c038e8a12f892cdb7d5c37745810 100644 (file)
@@ -396,6 +396,9 @@ builtin_memref::set_base_and_offset (tree expr)
   if (TREE_CODE (expr) == ADDR_EXPR)
     expr = TREE_OPERAND (expr, 0);
 
+  /* Stash the reference for offset validation.  */
+  ref = expr;
+
   poly_int64 bitsize, bitpos;
   tree var_off;
   machine_mode mode;
@@ -409,23 +412,33 @@ builtin_memref::set_base_and_offset (tree expr)
   base = get_inner_reference (expr, &bitsize, &bitpos, &var_off,
                              &mode, &sign, &reverse, &vol);
 
+  /* get_inner_reference is not expected to return null.  */
+  gcc_assert (base != NULL);
+
   poly_int64 bytepos = exact_div (bitpos, BITS_PER_UNIT);
 
-  HOST_WIDE_INT const_off;
-  if (!base || !bytepos.is_constant (&const_off))
+  /* Convert the poly_int64 offset to to offset_int.  The offset
+     should be constant but be prepared for it not to be just in
+     case.  */
+  offset_int cstoff;
+  if (bytepos.is_constant (&cstoff))
     {
-      base = get_base_address (TREE_OPERAND (expr, 0));
-      return;
-    }
+      offrange[0] += cstoff;
+      offrange[1] += cstoff;
 
-  offrange[0] += const_off;
-  offrange[1] += const_off;
+      /* Besides the reference saved above, also stash the offset
+        for validation.  */
+      if (TREE_CODE (expr) == COMPONENT_REF)
+       refoff = cstoff;
+    }
+  else
+    offrange[1] += maxobjsize;
 
   if (var_off)
     {
       if (TREE_CODE (var_off) == INTEGER_CST)
        {
-         offset_int cstoff = wi::to_offset (var_off);
+         cstoff = wi::to_offset (var_off);
          offrange[0] += cstoff;
          offrange[1] += cstoff;
        }
@@ -433,13 +446,6 @@ builtin_memref::set_base_and_offset (tree expr)
        offrange[1] += maxobjsize;
     }
 
-  /* Stash the reference for offset validation.  */
-  ref = expr;
-
-  /* Also stash the constant offset for offset validation.  */
-  if (TREE_CODE (expr) == COMPONENT_REF)
-    refoff = const_off;
-
   if (TREE_CODE (base) == MEM_REF)
     {
       tree memrefoff = TREE_OPERAND (base, 1);
@@ -918,12 +924,20 @@ builtin_access::generic_overlap ()
   if (!overlap_certain)
     {
       if (!dstref->strbounded_p && !depends_p)
+       /* Memcpy only considers certain overlap.  */
        return false;
 
       /* There's no way to distinguish an access to the same member
         of a structure from one to two distinct members of the same
         structure.  Give up to avoid excessive false positives.  */
-      tree basetype = TREE_TYPE (TREE_TYPE (dstref->base));
+      tree basetype = TREE_TYPE (dstref->base);
+
+      if (POINTER_TYPE_P (basetype))
+       basetype = TREE_TYPE (basetype);
+      else
+       while (TREE_CODE (basetype) == ARRAY_TYPE)
+         basetype = TREE_TYPE (basetype);
+
       if (RECORD_OR_UNION_TYPE_P (basetype))
        return false;
     }
index 18d987b46d6abd87c1412caeaf591e7053b9911a..ecd0fb83f371f28b04055c85fdd75dea471d89b8 100644 (file)
@@ -1,3 +1,9 @@
+2018-03-09  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/84526
+       * gcc.dg/Wrestrict-10.c: New test.
+       * gcc.dg/Wrestrict-11.c: New test.
+
 2018-03-09  Alexandre Oliva <aoliva@redhat.com>
 
        PR rtl-optimization/84682
diff --git a/gcc/testsuite/gcc.dg/Wrestrict-10.c b/gcc/testsuite/gcc.dg/Wrestrict-10.c
new file mode 100644 (file)
index 0000000..a5a5ff1
--- /dev/null
@@ -0,0 +1,121 @@
+/* PR tree-optimization/84526 - ICE in generic_overlap
+   { dg-do compile }
+   { dg-options "-O2 -Wrestrict" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void* memcpy (void* restrict, const void* restrict, size_t);
+extern char* strcat (char* restrict, const char* restrict);
+extern char* strcpy (char* restrict, const char* restrict);
+extern char* strncat (char* restrict, const char* restrict, size_t);
+extern char* strncpy (char* restrict, const char* restrict, size_t);
+
+struct
+{
+  char a[1];
+} b;
+
+int i;
+size_t n;
+
+void __attribute__ ((noclone, noinline))
+test_arr_memcpy_1 (void)
+{
+  memcpy (&b.a[i], b.a, n);
+}
+
+void __attribute__ ((noclone, noinline))
+test_arr_memcpy_2 (void)
+{
+  memcpy (b.a, &b.a[i], n);
+}
+
+void __attribute__ ((noclone, noinline))
+test_arr_strcat_1 (void)
+{
+  strcat (&b.a[i], b.a);            /* { dg-warning "\\\[-Wrestrict" } */
+}
+
+void __attribute__ ((noclone, noinline))
+test_arr_strcat_2 (void)
+{
+  /* This probably deserves a warning.  */
+  strcpy (b.a, &b.a[i]);
+}
+
+void __attribute__ ((noclone, noinline))
+test_arr_strncat_1 (void)
+{
+  strncat (&b.a[i], b.a, n);        /* { dg-warning "\\\[-Wrestrict" } */
+}
+
+void __attribute__ ((noclone, noinline))
+test_arr_strncat_2 (void)
+{
+  strncat (b.a, &b.a[i], n);        /* { dg-warning "\\\[-Wrestrict" } */
+}
+
+void __attribute__ ((noclone, noinline))
+test_arr_strcpy_1 (void)
+{
+  strcpy (&b.a[i], b.a);
+}
+
+void __attribute__ ((noclone, noinline))
+test_arr_strcpy_2 (void)
+{
+  strcpy (b.a, &b.a[i]);
+}
+
+
+struct S {
+  int a;
+  char b[10];
+} d;
+
+void __attribute__ ((noclone, noinline))
+test_obj_memcpy_1 (void)
+{
+  memcpy (d.b, (char *) &d, n);
+}
+
+void __attribute__ ((noclone, noinline))
+test_obj_memcpy_2 (void)
+{
+  memcpy ((char *) &d, d.b, n);
+}
+
+void __attribute__ ((noclone, noinline))
+test_obj_strcpy_1 (void)
+{
+  strcpy (d.b, (char *) &d);
+}
+
+void __attribute__ ((noclone, noinline))
+test_obj_strcpy_2 (void)
+{
+  strcpy ((char *) &d, d.b);
+}
+
+void __attribute__ ((noclone, noinline))
+test_obj_strncat_1 (void)
+{
+  strncat (d.b, (char *) &d, n);    /* { dg-warning "\\\[-Wrestrict" } */
+}
+
+void __attribute__ ((noclone, noinline))
+test_obj_strncat_2 (void)
+{
+  strncat ((char *) &d, d.b, n);    /* { dg-warning "\\\[-Wrestrict" } */
+}
+
+void __attribute__ ((noclone, noinline))
+test_obj_strncpy_1 (void)
+{
+  strncpy (d.b, (char *) &d, n);
+}
+
+void test_obj_strncpy_2 (void)
+{
+  strncpy ((char *) &d, d.b, n);
+}
diff --git a/gcc/testsuite/gcc.dg/Wrestrict-11.c b/gcc/testsuite/gcc.dg/Wrestrict-11.c
new file mode 100644 (file)
index 0000000..7b4b5aa
--- /dev/null
@@ -0,0 +1,205 @@
+/* PR tree-optimization/84526 - ICE in generic_overlap
+   Unrelated to the ICE but rather to PR 84095 that introduced it, verify
+   that calls to strncpy involving multidimensional arrays of structs don't
+   trigger false positive -Wrestrict warnings.
+   { dg-do compile }
+   { dg-options "-O2 -Wrestrict -ftrack-macro-expansion=0" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern char* strcpy (char*, const char*);
+
+struct MemArrays
+{
+  char a1[4];
+  char a2[4][4];
+  char a3[4][4][4];
+} ma1[4], ma2[4][4], ma3[4][4][4];
+
+#define T(dst, src) do {                               \
+    strcpy (src, "123");                               \
+    strcpy (dst, src);                                 \
+  } while (0)
+
+
+void test_ma1_cst (const char *s)
+{
+  T (ma1[0].a1, ma1[0].a1);           /* { dg-warning "\\\[-Wrestrict]" } */
+  T (ma1[0].a1, ma1[1].a1);
+  T (ma1[0].a1, ma1[2].a1);
+  T (ma1[0].a1, ma1[3].a1);
+
+  T (ma1[0].a1, ma1[0].a1);           /* { dg-warning "\\\[-Wrestrict]" } */
+  T (ma1[1].a1, ma1[0].a1);
+  T (ma1[2].a1, ma1[0].a1);
+  T (ma1[3].a1, ma1[0].a1);
+}
+
+
+void test_ma1_var_cst (const char *s, int i)
+{
+  T (ma1[i].a1, ma1[0].a1);
+  T (ma1[i].a1, ma1[1].a1);
+  T (ma1[i].a1, ma1[2].a1);
+  T (ma1[i].a1, ma1[3].a1);
+
+  T (ma1[0].a1, ma1[i].a1);
+  T (ma1[1].a1, ma1[i].a1);
+  T (ma1[2].a1, ma1[i].a1);
+  T (ma1[3].a1, ma1[i].a1);
+}
+
+
+void test_ma1_var_var (const char *s, int i, int j)
+{
+  T (ma1[i].a1, ma1[j].a1);
+  T (ma1[i].a1, ma1[j].a1);
+  T (ma1[i].a1, ma1[j].a1);
+  T (ma1[i].a1, ma1[j].a1);
+
+  T (ma1[i].a1, ma1[j].a1);
+  T (ma1[i].a1, ma1[j].a1);
+  T (ma1[i].a1, ma1[j].a1);
+  T (ma1[i].a1, ma1[j].a1);
+}
+
+
+void test_ma2_cst (const char *s)
+{
+  T (ma2[0][0].a1, ma2[0][0].a1);     /* { dg-warning "\\\[-Wrestrict]" } */
+  T (ma2[0][0].a1, ma2[0][1].a1);
+  T (ma2[0][0].a1, ma2[0][2].a1);
+  T (ma2[0][0].a1, ma2[0][3].a1);
+
+  T (ma2[0][0].a1, ma2[1][0].a1);
+  T (ma2[0][0].a1, ma2[1][1].a1);
+  T (ma2[0][0].a1, ma2[1][2].a1);
+  T (ma2[0][0].a1, ma2[1][3].a1);
+
+  T (ma2[0][0].a1, ma2[2][0].a1);
+  T (ma2[0][0].a1, ma2[2][1].a1);
+  T (ma2[0][0].a1, ma2[2][2].a1);
+  T (ma2[0][0].a1, ma2[2][3].a1);
+
+  T (ma2[0][0].a1, ma2[3][0].a1);
+  T (ma2[0][0].a1, ma2[3][1].a1);
+  T (ma2[0][0].a1, ma2[3][2].a1);
+  T (ma2[0][0].a1, ma2[3][3].a1);
+
+
+  T (ma2[0][1].a1, ma2[0][0].a1);
+  T (ma2[0][1].a1, ma2[0][1].a1);     /* { dg-warning "\\\[-Wrestrict]" } */
+  T (ma2[0][1].a1, ma2[0][2].a1);
+  T (ma2[0][1].a1, ma2[0][3].a1);
+
+  T (ma2[0][1].a1, ma2[1][0].a1);
+  T (ma2[0][1].a1, ma2[1][1].a1);
+  T (ma2[0][1].a1, ma2[1][2].a1);
+  T (ma2[0][1].a1, ma2[1][3].a1);
+
+  T (ma2[0][1].a1, ma2[2][0].a1);
+  T (ma2[0][1].a1, ma2[2][1].a1);
+  T (ma2[0][1].a1, ma2[2][2].a1);
+  T (ma2[0][1].a1, ma2[2][3].a1);
+
+  T (ma2[0][1].a1, ma2[3][0].a1);
+  T (ma2[0][1].a1, ma2[3][1].a1);
+  T (ma2[0][1].a1, ma2[3][2].a1);
+  T (ma2[0][1].a1, ma2[3][3].a1);
+
+
+  T (ma2[0][2].a1, ma2[0][0].a1);
+  T (ma2[0][2].a1, ma2[0][1].a1);
+  T (ma2[0][2].a1, ma2[0][2].a1);     /* { dg-warning "\\\[-Wrestrict]" } */
+  T (ma2[0][2].a1, ma2[0][3].a1);
+
+  T (ma2[0][2].a1, ma2[1][0].a1);
+  T (ma2[0][2].a1, ma2[1][1].a1);
+  T (ma2[0][2].a1, ma2[1][2].a1);
+  T (ma2[0][2].a1, ma2[1][3].a1);
+
+  T (ma2[0][2].a1, ma2[2][0].a1);
+  T (ma2[0][2].a1, ma2[2][1].a1);
+  T (ma2[0][2].a1, ma2[2][2].a1);
+  T (ma2[0][2].a1, ma2[2][3].a1);
+
+  T (ma2[0][2].a1, ma2[3][0].a1);
+  T (ma2[0][2].a1, ma2[3][1].a1);
+  T (ma2[0][2].a1, ma2[3][2].a1);
+  T (ma2[0][2].a1, ma2[3][3].a1);
+
+
+  T (ma2[0][3].a1, ma2[0][0].a1);
+  T (ma2[0][3].a1, ma2[0][1].a1);
+  T (ma2[0][3].a1, ma2[0][2].a1);
+  T (ma2[0][3].a1, ma2[0][3].a1);     /* { dg-warning "\\\[-Wrestrict]" } */
+
+  T (ma2[0][3].a1, ma2[1][0].a1);
+  T (ma2[0][3].a1, ma2[1][1].a1);
+  T (ma2[0][3].a1, ma2[1][2].a1);
+  T (ma2[0][3].a1, ma2[1][3].a1);
+
+  T (ma2[0][3].a1, ma2[2][0].a1);
+  T (ma2[0][3].a1, ma2[2][1].a1);
+  T (ma2[0][3].a1, ma2[2][2].a1);
+  T (ma2[0][3].a1, ma2[2][3].a1);
+
+  T (ma2[0][3].a1, ma2[3][0].a1);
+  T (ma2[0][3].a1, ma2[3][1].a1);
+  T (ma2[0][3].a1, ma2[3][2].a1);
+  T (ma2[0][3].a1, ma2[3][3].a1);
+}
+
+
+void test_ma2_var (int i0, int j0, int i1, int j1)
+{
+  T (ma2[i0][j0].a1, ma2[i0][j0].a1);       /* { dg-warning "\\\[-Wrestrict]" } */
+
+  T (ma2[i0][j0].a1, ma2[i0][j1].a1);       /* { dg-bogus "\\\[-Wrestrict]" } */
+  T (ma2[i0][j0].a1, ma2[i1][j1].a1);       /* { dg-bogus "\\\[-Wrestrict]" } */
+
+  T (ma2[0][0].a2[i0], ma2[0][0].a2[j0]);   /* { dg-bogus "\\\[-Wrestrict]" } */
+  T (ma2[0][i0].a2[0], ma2[0][i1].a2[0]);   /* { dg-bogus "\\\[-Wrestrict]" } */
+  T (ma2[i0][0].a2[0], ma2[i1][0].a2[0]);   /* { dg-bogus "\\\[-Wrestrict]" } */
+  T (ma2[i0][j0].a2[0], ma2[i1][j1].a2[0]); /* { dg-bogus "\\\[-Wrestrict]" } */
+}
+
+
+void test_p2_var (struct MemArrays **p2, int i0, int j0, int i1, int j1)
+{
+  T (p2[i0][j0].a1, p2[i0][j0].a1);         /* { dg-warning "\\\[-Wrestrict]" } */
+
+  T (p2[i0][j0].a1, p2[i0][j1].a1);
+  T (p2[i0][j0].a1, p2[i1][j1].a1);
+
+  T (p2[0][0].a2[i0], p2[0][0].a2[j0]);
+  T (p2[0][i0].a2[0], p2[0][i1].a2[0]);
+  T (p2[i0][0].a2[0], p2[i1][0].a2[0]);
+  T (p2[i0][j0].a2[0], p2[i1][j1].a2[0]);
+}
+
+
+void test_ma3_cst (const char *s)
+{
+  T (ma3[0][0][0].a1, ma3[0][0][0].a1); /* { dg-warning "\\\[-Wrestrict]" } */
+  T (ma3[0][0][0].a1, ma3[0][0][3].a1);
+
+  T (ma3[0][0][0].a1, ma3[0][1][0].a1);
+  T (ma3[0][0][0].a1, ma3[0][1][3].a1);
+  T (ma3[0][0][0].a1, ma3[1][0][0].a1);
+  T (ma3[0][0][0].a1, ma3[1][0][3].a1);
+  T (ma3[0][0][0].a1, ma3[3][0][3].a1);
+  T (ma3[0][0][0].a1, ma3[3][3][3].a1);
+}
+
+
+void test_ma3_var (const char *s,
+                  int i0, int j0, int k0,
+                  int i1, int j1, int k1)
+{
+  T (ma3[i0][j0][k0].a1, ma3[i0][j0][k0].a1);   /* { dg-warning "\\\[-Wrestrict]" } */
+
+  T (ma3[i0][j0][k0].a1, ma3[i0][j0][k1].a1);   /* { dg-bogus "\\\[-Wrestrict]" } */
+  T (ma3[i0][j0][k0].a1, ma3[i0][j1][k1].a1);   /* { dg-bogus "\\\[-Wrestrict]" } */
+  T (ma3[i0][j0][k0].a1, ma3[i1][j1][k1].a1);   /* { dg-bogus "\\\[-Wrestrict]" } */
+}