aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-ssa-warn-restrict.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2018-02-14 23:22:15 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2018-02-14 16:22:15 -0700
commit816fad6ed44fb327c4034c40eb9d2bccafd6538d (patch)
tree4abe2f0ee56e212baf1980d760fbb71436a2cbfb /gcc/gimple-ssa-warn-restrict.c
parent7c102986d6f8205ebc3952344c64edbcd7018fbc (diff)
downloadgcc-816fad6ed44fb327c4034c40eb9d2bccafd6538d.zip
gcc-816fad6ed44fb327c4034c40eb9d2bccafd6538d.tar.gz
gcc-816fad6ed44fb327c4034c40eb9d2bccafd6538d.tar.bz2
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. From-SVN: r257676
Diffstat (limited to 'gcc/gimple-ssa-warn-restrict.c')
-rw-r--r--gcc/gimple-ssa-warn-restrict.c60
1 files changed, 50 insertions, 10 deletions
diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c
index 5b3b969..d0e1854 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)
{