From 484051f7fd0513e33c839394ee1ca41b5ee40b31 Mon Sep 17 00:00:00 2001 From: msebor Date: Wed, 14 Feb 2018 23:22:15 +0000 Subject: [PATCH] PR tree-optimization/83698 - bogus offset in -Wrestrict messages for strcat of unknown strings gcc/ChangeLog: PR tree-optimization/83698 * gimple-ssa-warn-restrict.c (builtin_memref::builtin_memref): For arrays constrain the offset range to their bounds. (builtin_access::strcat_overlap): Adjust the bounds of overlap offset. (builtin_access::overlap): Avoid setting the size of overlap if it's already been set. (maybe_diag_overlap): Also consider arrays when deciding what values of offsets to include in diagnostics. gcc/testsuite/ChangeLog: PR tree-optimization/83698 * gcc.dg/Wrestrict-7.c: New test. * c-c++-common/Wrestrict.c: Adjust expected values for strcat. * gcc.target/i386/chkp-stropt-17.c: Same. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@257676 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 11 +++++ gcc/gimple-ssa-warn-restrict.c | 60 +++++++++++++++++++++----- gcc/testsuite/ChangeLog | 7 +++ gcc/testsuite/c-c++-common/Wrestrict.c | 11 +++-- gcc/testsuite/gcc.dg/Wrestrict-7.c | 51 ++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/chkp-stropt-17.c | 2 +- 6 files changed, 127 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/Wrestrict-7.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e16acd45413..6b092077979 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,16 @@ 2018-02-14 Martin Sebor + PR tree-optimization/83698 + * gimple-ssa-warn-restrict.c (builtin_memref::builtin_memref): For + arrays constrain the offset range to their bounds. + (builtin_access::strcat_overlap): Adjust the bounds of overlap offset. + (builtin_access::overlap): Avoid setting the size of overlap if it's + already been set. + (maybe_diag_overlap): Also consider arrays when deciding what values + of offsets to include in diagnostics. + +2018-02-14 Martin Sebor + PR c/84108 * attribs.c (diag_attr_exclusions): Consider the exclusion(s) that correspond to the kind of a declaration. diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c index 5b3b9691313..d0e18541275 100644 --- a/gcc/gimple-ssa-warn-restrict.c +++ b/gcc/gimple-ssa-warn-restrict.c @@ -375,6 +375,14 @@ builtin_memref::builtin_memref (tree expr, tree size) } } + if (DECL_P (base) && TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE) + { + /* For array objects, where a negative offset wouldn't make + sense, use zero instead if the upper bound is positive. */ + if (offrange[0] < 0 && offrange[1] > 0) + offrange[0] = 0; + } + if (size) { tree range[2]; @@ -1070,14 +1078,35 @@ builtin_access::strcat_overlap () return false; /* When strcat overlap is certain it is always a single byte: - the terminatinn NUL, regardless of offsets and sizes. When + the terminating NUL, regardless of offsets and sizes. When overlap is only possible its range is [0, 1]. */ acs.ovlsiz[0] = dstref->sizrange[0] == dstref->sizrange[1] ? 1 : 0; acs.ovlsiz[1] = 1; - acs.ovloff[0] = (dstref->sizrange[0] + dstref->offrange[0]).to_shwi (); - acs.ovloff[1] = (dstref->sizrange[1] + dstref->offrange[1]).to_shwi (); - acs.sizrange[0] = wi::smax (acs.dstsiz[0], srcref->sizrange[0]).to_shwi (); + offset_int endoff = dstref->offrange[0] + dstref->sizrange[0]; + if (endoff <= srcref->offrange[0]) + acs.ovloff[0] = wi::smin (maxobjsize, srcref->offrange[0]).to_shwi (); + else + acs.ovloff[0] = wi::smin (maxobjsize, endoff).to_shwi (); + + acs.sizrange[0] = wi::smax (wi::abs (endoff - srcref->offrange[0]) + 1, + srcref->sizrange[0]).to_shwi (); + if (dstref->offrange[0] == dstref->offrange[1]) + { + if (srcref->offrange[0] == srcref->offrange[1]) + acs.ovloff[1] = acs.ovloff[0]; + else + acs.ovloff[1] + = wi::smin (maxobjsize, + srcref->offrange[1] + srcref->sizrange[1]).to_shwi (); + } + else + acs.ovloff[1] + = wi::smin (maxobjsize, + dstref->offrange[1] + dstref->sizrange[1]).to_shwi (); + + if (acs.sizrange[0] == 0) + acs.sizrange[0] = 1; acs.sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi (); return true; } @@ -1215,8 +1244,12 @@ builtin_access::overlap () /* Call the appropriate function to determine the overlap. */ if ((this->*detect_overlap) ()) { - sizrange[0] = wi::smax (acs.dstsiz[0], srcref->sizrange[0]).to_shwi (); - sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi (); + if (!sizrange[1]) + { + /* Unless the access size range has already been set, do so here. */ + sizrange[0] = wi::smax (acs.dstsiz[0], srcref->sizrange[0]).to_shwi (); + sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi (); + } return true; } @@ -1392,10 +1425,17 @@ maybe_diag_overlap (location_t loc, gcall *call, builtin_access &acs) /* Use more concise wording when one of the offsets is unbounded to avoid confusing the user with large and mostly meaningless numbers. */ - bool open_range = ((dstref.offrange[0] == -maxobjsize - 1 - && dstref.offrange[1] == maxobjsize) - || (srcref.offrange[0] == -maxobjsize - 1 - && srcref.offrange[1] == maxobjsize)); + bool open_range; + if (DECL_P (dstref.base) && TREE_CODE (TREE_TYPE (dstref.base)) == ARRAY_TYPE) + open_range = ((dstref.offrange[0] == 0 + && dstref.offrange[1] == maxobjsize) + || (srcref.offrange[0] == 0 + && srcref.offrange[1] == maxobjsize)); + else + open_range = ((dstref.offrange[0] == -maxobjsize - 1 + && dstref.offrange[1] == maxobjsize) + || (srcref.offrange[0] == -maxobjsize - 1 + && srcref.offrange[1] == maxobjsize)); if (sizrange[0] == sizrange[1] || sizrange[1] == 1) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e769dd5647b..431af1a9008 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -5,6 +5,13 @@ 2018-02-14 Martin Sebor + PR tree-optimization/83698 + * gcc.dg/Wrestrict-7.c: New test. + * c-c++-common/Wrestrict.c: Adjust expected values for strcat. + * gcc.target/i386/chkp-stropt-17.c: Same. + +2018-02-14 Martin Sebor + PR c/84108 * gcc.dg/Wattributes-8.c: New test. diff --git a/gcc/testsuite/c-c++-common/Wrestrict.c b/gcc/testsuite/c-c++-common/Wrestrict.c index 671497ea3e6..72d9a4716fb 100644 --- a/gcc/testsuite/c-c++-common/Wrestrict.c +++ b/gcc/testsuite/c-c++-common/Wrestrict.c @@ -616,10 +616,13 @@ void test_strcat_var (char *d, const char *s) } while (0) T (d, d); /* { dg-warning "source argument is the same as destination" "strcat" } */ - T (d, d + 1); /* { dg-warning "accessing 0 or more bytes at offsets 0 and 1 may overlap 1 byte" "strcat" } */ - T (d, d + 2); /* { dg-warning "accessing 0 or more bytes at offsets 0 and 2 may overlap 1 byte" "strcat" } */ - T (d, d + 999); /* { dg-warning "accessing 0 or more bytes at offsets 0 and 999 may overlap 1 byte" "strcat" } */ - T (d, d + -99); /* { dg-warning "accessing 0 or more bytes at offsets 0 and -99 may overlap 1 byte" "strcat" } */ + T (d, d + 1); /* { dg-warning "accessing 2 or more bytes at offsets 0 and 1 may overlap 1 byte" "strcat" } */ + T (d, d + 2); /* { dg-warning "accessing 3 or more bytes at offsets 0 and 2 may overlap 1 byte at offset 2" "strcat" } */ + T (d, d + 999); /* { dg-warning "accessing 1000 or more bytes at offsets 0 and 999 may overlap 1 byte at offset 999" "strcat" } */ + + /* The source string must be at least 100 bytes in length for the copy + below to overlap. */ + T (d, d + -99); /* { dg-warning "accessing 100 or more bytes at offsets 0 and -99 may overlap 1 byte" "strcat" } */ size_t n = unsigned_value (); diff --git a/gcc/testsuite/gcc.dg/Wrestrict-7.c b/gcc/testsuite/gcc.dg/Wrestrict-7.c new file mode 100644 index 00000000000..5be5e0bd051 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wrestrict-7.c @@ -0,0 +1,51 @@ +/* PR tree-optimization/83698 - bogus offset in -Wrestrict messages for + strcat of unknown strings + { dg-do compile } + { dg-options "-O2 -Wrestrict -ftrack-macro-expansion=0" } */ + +extern char* strcat (char*, const char*); + +void sink (char*); + +#define T(d, s) sink (strcat (d, s)) + +extern char arr[]; + + +void test_strcat_array_cst_offset (void) +{ + T (arr, arr + 1); /* { dg-warning "accessing 2 or more bytes at offsets 0 and 1 may overlap 1 byte at offset 1" } */ + T (arr, arr + 2); /* { dg-warning "accessing 3 or more bytes at offsets 0 and 2 may overlap 1 byte at offset 2" } */ + T (arr, arr + 13); /* { dg-warning "accessing 14 or more bytes at offsets 0 and 13 may overlap 1 byte at offset 13" } */ + + T (arr + 1, arr); /* { dg-warning "accessing 2 or more bytes at offsets 1 and 0 may overlap 1 byte at offset 1" } */ + T (arr + 17, arr + 11); /* { dg-warning "accessing 7 or more bytes at offsets 17 and 11 may overlap 1 byte at offset 17" } */ + T (arr + 36, arr + 20); /* { dg-warning "accessing 17 or more bytes at offsets 36 and 20 may overlap 1 byte at offset 36" } */ +} + +void test_strcat_ptr_cst_offset (char *d) +{ + T (d - 12, d + 34); /* { dg-warning "accessing 47 or more bytes at offsets -12 and 34 may overlap 1 byte at offset 34" } */ + T (d + 12, d + 34); /* { dg-warning "accessing 23 or more bytes at offsets 12 and 34 may overlap 1 byte at offset 34" } */ + T (d + 20, d + 36); /* { dg-warning "accessing 17 or more bytes at offsets 20 and 36 may overlap 1 byte at offset 36" } */ +} + +void test_strcat_array_var_offset (int i, int j) +{ + T (arr + i, arr); /* { dg-warning "accessing 1 or more bytes at offsets \\\[0, \[0-9\]+] and 0 may overlap 1 byte at offset \\\[0, \[0-9\]+]" } */ + T (arr, arr + j); /* { dg-warning "accessing 1 or more bytes at offsets 0 and \\\[0, \[0-9\]+] may overlap 1 byte at offset \\\[0, \[0-9\]+]" } */ + T (arr + i, arr + j); /* { dg-warning "accessing 1 or more bytes at offsets \\\[0, \[0-9\]+] and \\\[0, \[0-9\]+] may overlap 1 byte at offset \\\[0, \[0-9\]+]" } */ + + T (arr + i, arr + 5); /* { dg-warning "accessing 6 or more bytes at offsets \\\[0, \[0-9\]+] and 5 may overlap 1 byte at offset \\\[5, \[0-9\]+]" } */ + T (arr + 7, arr + j); /* { dg-warning "accessing 8 or more bytes at offsets 7 and \\\[0, \[0-9\]+] may overlap 1 byte at offset \\\[7, \[0-9\]+]" } */ +} + +void test_strcat_ptr_var_offset (char *d, int i, int j) +{ + T (d + i, d); /* { dg-warning "accessing \[0-9\]+ or more bytes at offsets \\\[-\[0-9\]+, \[0-9\]+] and 0 may overlap 1 byte at offset \\\[0, \[0-9\]+]" } */ + T (d, d + j); /* { dg-warning "accessing \[0-9\]+ or more bytes at offsets 0 and \\\[-\[0-9\]+, \[0-9\]+] may overlap 1 byte at offset \\\[0, \[0-9\]+]" } */ + T (d + i, d + j); /* { dg-warning "accessing 1 or more bytes at offsets \\\[-\[0-9\]+, \[0-9\]+] and \\\[-\[0-9\]+, \[0-9\]+] may overlap 1 byte at offset \\\[-\[0-9\]+, \[0-9\]+]" } */ + + T (d + i, d + 3); /* { dg-warning "accessing \[0-9\]+ or more bytes at offsets \\\[-\[0-9\]+, \[0-9\]+] and 3 may overlap 1 byte at offset \\\[3, \[0-9\]+]" } */ + T (d + 9, d + j); /* { dg-warning "accessing \[0-9\]+ or more bytes at offsets 9 and \\\[-\[0-9\]+, \[0-9\]+] may overlap 1 byte at offset \\\[9, \[0-9\]+]" } */ +} diff --git a/gcc/testsuite/gcc.target/i386/chkp-stropt-17.c b/gcc/testsuite/gcc.target/i386/chkp-stropt-17.c index 1be4922fd53..faf304c3303 100644 --- a/gcc/testsuite/gcc.target/i386/chkp-stropt-17.c +++ b/gcc/testsuite/gcc.target/i386/chkp-stropt-17.c @@ -51,7 +51,7 @@ void test_strcpy (void) void test_strcat (int n) { - strcat (a, a + 3); /* { dg-warning ".strcat\.chkp. accessing 0 or more bytes at offsets 0 and 3 may overlap 1 byte" } */ + strcat (a, a + 3); /* { dg-warning ".strcat\.chkp. accessing 4 or more bytes at offsets 0 and 3 may overlap 1 byte at offset 3" } */ } void test_strncat (int n) -- 2.11.4.GIT