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>
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
* attribs.c (diag_attr_exclusions): Consider the exclusion(s)
that correspond to the kind of a declaration.
......
......@@ -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) ())
{
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,7 +1425,14 @@ 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
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));
......
......@@ -5,6 +5,13 @@
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
* gcc.dg/Wattributes-8.c: New test.
......
......@@ -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 ();
......
/* 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)
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)
......
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