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;
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;
}
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);
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;
}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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]" } */
+}