Commit efe646c4 by Martin Sebor Committed by Martin Sebor

tree-ssa-strlen.c (get_addr_stridx): Add argument and use it.


gcc/ChangeLog:

	* tree-ssa-strlen.c (get_addr_stridx): Add argument and use it.
	(handle_store): Pass argument to get_addr_stridx.

gcc/testsuite/ChangeLog:

	* gcc.dg/strlenopt-89.c: New test.
	* gcc.dg/strlenopt-90.c: New test.
	* gcc.dg/Wstringop-overflow-20.c: New test.

From-SVN: r277546
parent 02c4de76
2019-10-28 Martin Sebor <msebor@redhat.com>
* tree-ssa-strlen.c (get_addr_stridx): Add argument and use it.
(handle_store): Pass argument to get_addr_stridx.
2019-10-28 Martin Sebor <msebor@redhat.com>
PR tree-optimization/92226
* tree-ssa-strlen.c (compare_nonzero_chars): Return -1 also when
the offset is in the open range outlined by SI's length.
2019-10-28 Martin Sebor <msebor@redhat.com>
* gcc.dg/strlenopt-89.c: New test.
* gcc.dg/strlenopt-90.c: New test.
* gcc.dg/Wstringop-overflow-20.c: New test.
2019-10-28 Martin Sebor <msebor@redhat.com>
PR tree-optimization/92226
* gcc.dg/strlenopt-88.c: New test.
......
/* PR tree-optimization/92226 - live nul char store to array eliminated
Test to verify warnings are issued for overflow detected thanks to
the enhancement committed on top of the fix for PR 92226.
{ dg-do compile }
{ dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */
#include "strlenopt.h"
#define NOIPA __attribute__ ((noipa))
#define T(MIN, MAX, SIZE, IDX) \
NOIPA void \
test_ ## MIN ## _ ## MAX ## _ ## SIZE ## _ ## IDX (const char *s) \
{ \
size_t len = strlen (s); \
if (MIN <= len && len <= MAX) \
{ \
extern char d[]; \
strcpy (d, s); \
d[IDX] = 0; \
extern char a ## SIZE[SIZE]; \
strcpy (a ## SIZE, d); \
} \
} typedef void dummy_type
T (2, 2, 1, 0);
T (2, 2, 1, 1); // { dg-warning "writing 2 bytes into a region of size 1" }
T (2, 2, 1, 2); // { dg-warning "writing 3 bytes into a region of size 1" }
T (2, 3, 1, 0);
T (2, 3, 1, 1); // { dg-warning "writing 2 bytes into a region of size 1" }
T (2, 3, 1, 2); // { dg-warning "writing 3 bytes into a region of size 1" "" { xfail *-*-*} }
T (2, 3, 1, 3); // { dg-warning "writing 4 bytes into a region of size 1" "" { xfail *-*-* } }
T (5, 7, 3, 1);
T (5, 7, 3, 2);
T (5, 7, 3, 3); // { dg-warning "writing 4 bytes into a region of size 3" }
T (5, 7, 3, 4); // { dg-warning "writing 5 bytes into a region of size 3" }
T (5, 7, 3, 5); // { dg-warning "writing 6 bytes into a region of size 3" "" { xfail *-*-* } }
/* PR tree-optimization/92226 - live nul char store to array eliminated
{ dg-do compile }
{ dg-options "-O2 -fdump-tree-strlen" } */
#include "strlenopt.h"
#define NOIPA __attribute__ ((noipa))
/* Verify that the nul store into the destination is only eliminated
when overwrites the existing terminating nul added by the strcpy call.
Also verify that the second strlen call is eliminated in all cases. */
#define T(SIZE, IDX) \
NOIPA void test_ ## SIZE ## _store_nul_ ## IDX (const char *s) \
{ \
extern char a ## SIZE[SIZE]; \
char *d = a ## SIZE; \
size_t len = SIZE - 1; \
size_t idx = IDX; \
if (strlen (s) == len) \
{ \
strcpy (d, s); \
d[idx] = 0; \
if (strlen (d) != idx) \
abort (); \
} \
} typedef void dummy_type
T (1, 0); // expect nul store to be eliminated
T (2, 0); // nul store must be retained
T (2, 1); // expect nul store to be eliminated
// Same as above but for larger arrays.
T (3, 0);
T (3, 1);
T (3, 2);
T (4, 0);
T (4, 1);
T (4, 2);
T (4, 3);
T (5, 0);
T (5, 1);
T (5, 2);
T (5, 3);
T (5, 4);
T (6, 0);
T (6, 1);
T (6, 2);
T (6, 3);
T (6, 4);
T (6, 5);
T (7, 0);
T (7, 1);
T (7, 2);
T (7, 3);
T (7, 4);
T (7, 5);
T (7, 6);
T (8, 0);
T (8, 1);
T (8, 2);
T (8, 3);
T (8, 4);
T (8, 5);
T (8, 6);
T (8, 7);
/* Verify that each function makes just one call to strlen to compute
the length of its argument (and not also to compute the length of
the copy):
{ dg-final { scan-tree-dump-times "strlen \\(s_" 36 "strlen1" } }
{ dg-final { scan-tree-dump-not "strlen \\(\\&a" "strlen1" } }
Verify that nul stores into the last array element have been eliminated
(they are preceded by a strcpy storing into all the elements of the array:
{ dg-final { scan-tree-dump-not "a1\\\] = 0;" "strlen1" } }
{ dg-final { scan-tree-dump-not "a2 \\\+ 1B\\\] = 0;" "strlen1" } }
{ dg-final { scan-tree-dump-not "a3 \\\+ 2B\\\] = 0;" "strlen1" } }
{ dg-final { scan-tree-dump-not "a4 \\\+ 3B\\\] = 0;" "strlen1" } }
{ dg-final { scan-tree-dump-not "a5 \\\+ 4B\\\] = 0;" "strlen1" } }
{ dg-final { scan-tree-dump-not "a6 \\\+ 5B\\\] = 0;" "strlen1" } }
{ dg-final { scan-tree-dump-not "a7 \\\+ 6B\\\] = 0;" "strlen1" } }
{ dg-final { scan-tree-dump-not "a8 \\\+ 7B\\\] = 0;" "strlen1" } } */
/* PR tree-optimization/92226 - live nul char store to array eliminated
{ dg-do compile }
{ dg-options "-O2 -fdump-tree-strlen" } */
#include "strlenopt.h"
#define NOIPA __attribute__ ((noipa))
#define T(MIN, MAX, SIZE, IDX) \
NOIPA void \
test_ ## MIN ## _ ## MAX ## _ ## SIZE ## _ ## IDX (const char *s) \
{ \
extern char a ## SIZE[SIZE]; \
char *d = a ## SIZE; \
size_t len = strlen (s); \
size_t idx = IDX; \
if (MIN <= len && len <= MAX) \
{ \
strcpy (d, s); \
d[idx] = 0; \
if (strlen (d) != idx) \
abort (); \
} \
} typedef void dummy_type
/* The final nul store must be retained but the second strlen call should
be eliminated because the final length of the destination after the nul
store must be equal to the index of the store. */
T (0, 2, 4, 0);
/* Not handled yet (see below):
T (0, 2, 4, 1); */
/* Not handled yet: in addition to the cases above, the second strlen
call can also be eliminated in those below because in both the final
length of the destination after the nul store must be in the same
range as the length of the source.
T (0, 2, 4, 2);
T (0, 2, 4, 3); */
T (2, 3, 4, 0);
T (2, 3, 4, 1);
/* Not handled yet (see above):
T (2, 3, 4, 2);
T (2, 3, 4, 3); */
T (3, 4, 5, 0);
T (3, 4, 5, 1);
T (3, 4, 5, 2);
/* Not handled yet (see above):
T (3, 4, 5, 3);
T (3, 4, 5, 4); */
T (3, 4, 6, 0);
T (3, 4, 6, 1);
T (3, 4, 6, 2);
/* Not handled yet (see above):
T (3, 4, 6, 3);
T (3, 4, 6, 4);
T (3, 4, 6, 5); */
/* Verify that each function makes just one call to strlen to compute
the length of its argument (and not also to compute the length of
the copy):
{ dg-final { scan-tree-dump-times "strlen \\(s_" 9 "strlen1" } }
{ dg-final { scan-tree-dump-not "strlen \\(\\&a" "strlen1" } }
Verify that nul stores into the destination have not been eliminated:
{ dg-final { scan-tree-dump-times "a4\\\] = 0;" 2 "strlen1" } }
{ dg-final { scan-tree-dump-times "a4 \\\+ 1B\\\] = 0;" 1 "strlen1" } }
{ dg-final { scan-tree-dump-times "a5\\\] = 0;" 1 "strlen1" } }
{ dg-final { scan-tree-dump-times "a5 \\\+ 1B\\\] = 0;" 1 "strlen1" } }
{ dg-final { scan-tree-dump-times "a5 \\\+ 2B\\\] = 0;" 1 "strlen1" } }
{ dg-final { scan-tree-dump-times "a6\\\] = 0;" 1 "strlen1" } }
{ dg-final { scan-tree-dump-times "a6 \\\+ 1B\\\] = 0;" 1 "strlen1" } }
{ dg-final { scan-tree-dump-times "a6 \\\+ 2B\\\] = 0;" 1 "strlen1" } } */
......@@ -281,7 +281,8 @@ get_next_strinfo (strinfo *si)
*OFFSET_OUT. */
static int
get_addr_stridx (tree exp, tree ptr, unsigned HOST_WIDE_INT *offset_out)
get_addr_stridx (tree exp, tree ptr, unsigned HOST_WIDE_INT *offset_out,
const vr_values *rvals = NULL)
{
HOST_WIDE_INT off;
struct stridxlist *list, *last = NULL;
......@@ -319,7 +320,7 @@ get_addr_stridx (tree exp, tree ptr, unsigned HOST_WIDE_INT *offset_out)
unsigned HOST_WIDE_INT rel_off
= (unsigned HOST_WIDE_INT) off - last->offset;
strinfo *si = get_strinfo (last->idx);
if (si && compare_nonzero_chars (si, rel_off) >= 0)
if (si && compare_nonzero_chars (si, rel_off, rvals) >= 0)
{
if (offset_out)
{
......@@ -4328,7 +4329,7 @@ handle_store (gimple_stmt_iterator *gsi, bool *zero_write, const vr_values *rval
}
else
{
idx = get_addr_stridx (lhs, NULL_TREE, &offset);
idx = get_addr_stridx (lhs, NULL_TREE, &offset, rvals);
if (idx > 0)
si = get_strinfo (idx);
}
......
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