Commit 816fad6e by Martin Sebor Committed by Martin Sebor

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
parent 7c102986
2018-02-14 Martin Sebor <msebor@redhat.com> 2018-02-14 Martin Sebor <msebor@redhat.com>
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 <msebor@redhat.com>
PR c/84108 PR c/84108
* attribs.c (diag_attr_exclusions): Consider the exclusion(s) * attribs.c (diag_attr_exclusions): Consider the exclusion(s)
that correspond to the kind of a declaration. that correspond to the kind of a declaration.
......
...@@ -375,6 +375,14 @@ builtin_memref::builtin_memref (tree expr, tree size) ...@@ -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) if (size)
{ {
tree range[2]; tree range[2];
...@@ -1070,14 +1078,35 @@ builtin_access::strcat_overlap () ...@@ -1070,14 +1078,35 @@ builtin_access::strcat_overlap ()
return false; return false;
/* When strcat overlap is certain it is always a single byte: /* 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]. */ overlap is only possible its range is [0, 1]. */
acs.ovlsiz[0] = dstref->sizrange[0] == dstref->sizrange[1] ? 1 : 0; acs.ovlsiz[0] = dstref->sizrange[0] == dstref->sizrange[1] ? 1 : 0;
acs.ovlsiz[1] = 1; 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 (); acs.sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi ();
return true; return true;
} }
...@@ -1215,8 +1244,12 @@ builtin_access::overlap () ...@@ -1215,8 +1244,12 @@ builtin_access::overlap ()
/* Call the appropriate function to determine the overlap. */ /* Call the appropriate function to determine the overlap. */
if ((this->*detect_overlap) ()) if ((this->*detect_overlap) ())
{ {
sizrange[0] = wi::smax (acs.dstsiz[0], srcref->sizrange[0]).to_shwi (); if (!sizrange[1])
sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi (); {
/* 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; return true;
} }
...@@ -1392,10 +1425,17 @@ maybe_diag_overlap (location_t loc, gcall *call, builtin_access &acs) ...@@ -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 /* Use more concise wording when one of the offsets is unbounded
to avoid confusing the user with large and mostly meaningless to avoid confusing the user with large and mostly meaningless
numbers. */ numbers. */
bool open_range = ((dstref.offrange[0] == -maxobjsize - 1 bool open_range;
&& dstref.offrange[1] == maxobjsize) if (DECL_P (dstref.base) && TREE_CODE (TREE_TYPE (dstref.base)) == ARRAY_TYPE)
|| (srcref.offrange[0] == -maxobjsize - 1 open_range = ((dstref.offrange[0] == 0
&& srcref.offrange[1] == maxobjsize)); && 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) if (sizrange[0] == sizrange[1] || sizrange[1] == 1)
{ {
......
...@@ -5,6 +5,13 @@ ...@@ -5,6 +5,13 @@
2018-02-14 Martin Sebor <msebor@redhat.com> 2018-02-14 Martin Sebor <msebor@redhat.com>
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 <msebor@redhat.com>
PR c/84108 PR c/84108
* gcc.dg/Wattributes-8.c: New test. * gcc.dg/Wattributes-8.c: New test.
......
...@@ -616,10 +616,13 @@ void test_strcat_var (char *d, const char *s) ...@@ -616,10 +616,13 @@ void test_strcat_var (char *d, const char *s)
} while (0) } while (0)
T (d, d); /* { dg-warning "source argument is the same as destination" "strcat" } */ 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 + 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 0 or more bytes at offsets 0 and 2 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 0 or more bytes at offsets 0 and 999 may overlap 1 byte" "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" } */
T (d, d + -99); /* { dg-warning "accessing 0 or more bytes at offsets 0 and -99 may overlap 1 byte" "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 (); size_t n = unsigned_value ();
......
/* 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\]+]" } */
}
...@@ -51,7 +51,7 @@ void test_strcpy (void) ...@@ -51,7 +51,7 @@ void test_strcpy (void)
void test_strcat (int n) 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) void test_strncat (int n)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment