From 8286793a2b050a9c51501b0b3737ff73c71d189d Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Fri, 9 Mar 2018 19:06:26 +0000 Subject: [PATCH] re PR tree-optimization/84526 (ICE in generic_overlap at gcc/gimple-ssa-warn-restrict.c:927 since r257860) 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 | 8 ++ gcc/gimple-ssa-warn-restrict.c | 46 ++++--- gcc/testsuite/ChangeLog | 6 + gcc/testsuite/gcc.dg/Wrestrict-10.c | 121 ++++++++++++++++ gcc/testsuite/gcc.dg/Wrestrict-11.c | 205 ++++++++++++++++++++++++++++ 5 files changed, 370 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/Wrestrict-10.c create mode 100644 gcc/testsuite/gcc.dg/Wrestrict-11.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4d0b1592daf..346262eec23 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2018-03-09 Martin Sebor + + 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 PR rtl-optimization/84682 diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c index df775062758..25cc032c2da 100644 --- a/gcc/gimple-ssa-warn-restrict.c +++ b/gcc/gimple-ssa-warn-restrict.c @@ -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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 18d987b46d6..ecd0fb83f37 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-03-09 Martin Sebor + + PR tree-optimization/84526 + * gcc.dg/Wrestrict-10.c: New test. + * gcc.dg/Wrestrict-11.c: New test. + 2018-03-09 Alexandre Oliva 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 index 00000000000..a5a5ff1b5b2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wrestrict-10.c @@ -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 index 00000000000..7b4b5aa2527 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wrestrict-11.c @@ -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]" } */ +} -- 2.30.2