Commit 9bc83f27 by Jakub Jelinek Committed by Jakub Jelinek

re PR tree-optimization/89500 (ICE: tree check: expected integer_cst, have…

re PR tree-optimization/89500 (ICE: tree check: expected integer_cst, have ssa_name in get_len, at tree.h:5653)

	PR tree-optimization/89500
	* tree-ssa-strlen.c (stridx_strlenloc): Adjust comment.
	(handle_builtin_strlen): Remove noncst_bound variable.  Always
	optimize strnlen (x, 0) to 0.  Optimize strnlen (x, cst) to
	cst if the first cst bytes starting at x are known to be non-zero,
	even if the string is not zero terminated.  Don't try to modify
	*si for strnlen.  Update strlen_to_stridx only for strlen or if
	we can prove strnlen returns the same value as strlen would.

	* gcc.dg/pr89500.c: New test.
	* gcc.dg/Wstringop-overflow-10.c: New test.
	* gcc.dg/strlenopt-60.c: New test.

From-SVN: r269230
parent 3d7beb79
2019-02-26 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/89500
* tree-ssa-strlen.c (stridx_strlenloc): Adjust comment.
(handle_builtin_strlen): Remove noncst_bound variable. Always
optimize strnlen (x, 0) to 0. Optimize strnlen (x, cst) to
cst if the first cst bytes starting at x are known to be non-zero,
even if the string is not zero terminated. Don't try to modify
*si for strnlen. Update strlen_to_stridx only for strlen or if
we can prove strnlen returns the same value as strlen would.
2019-02-26 Martin Liska <mliska@suse.cz>
* alloc-pool.h (struct pool_usage): Remove extra
......
2019-02-26 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/89500
* gcc.dg/pr89500.c: New test.
* gcc.dg/Wstringop-overflow-10.c: New test.
* gcc.dg/strlenopt-60.c: New test.
2019-02-26 Harald Anlauf <anlauf@gmx.de>
PR fortran/89492
......
/* { dg-do compile } */
/* { dg-options "-O2 -Wstringop-overflow" } */
void
foo (char *a)
{
char b[16] = "abcdefg";
__builtin_strncpy (a, b, __builtin_strlen (b)); /* { dg-warning "specified bound depends on the length of the source argument" } */
}
void
bar (char *a)
{
char b[16] = "abcdefg";
__builtin_strncpy (a, b, __builtin_strnlen (b, 8)); /* { dg-warning "specified bound depends on the length of the source argument" } */
}
void
baz (char *a)
{
char b[16] = "abcdefg";
__builtin_strncpy (a, b, __builtin_strnlen (b, 7)); /* { dg-bogus "specified bound depends on the length of the source argument" } */
}
void fill (char *);
void
qux (char *a)
{
char b[16];
fill (b);
__builtin_memcpy (b, "abcdefg", 7);
__builtin_strncpy (a, b, __builtin_strnlen (b, 8)); /* { dg-bogus "specified bound depends on the length of the source argument" } */
}
/* PR tree-optimization/89500 */
/* { dg-do compile } */
/* { dg-options "-O2" } */
typedef __SIZE_TYPE__ size_t;
extern size_t strlen (const char *);
extern size_t strnlen (const char *, size_t);
extern void bar (char *);
void
foo (int *a)
{
char c[64];
bar (c);
a[0] = strlen (c);
a[1] = strnlen (c, 0);
}
/* PR tree-optimization/89500 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
/* { dg-final { scan-tree-dump-times "return 10;" 2 "optimized" } } */
/* { dg-final { scan-tree-dump-times "return 5;" 1 "optimized" } } */
/* { dg-final { scan-tree-dump-times "return 0;" 2 "optimized" } } */
/* { dg-final { scan-tree-dump-times "strnlen " 1 "optimized" } } */
#include "strlenopt.h"
void foo (char *);
size_t
f1 (void)
{
char a[10] = "0123456789";
return strnlen (a, 10);
}
size_t
f2 (void)
{
char a[10] = "0123456789";
return strnlen (a, 5);
}
size_t
f3 (void)
{
char a[10] = "0123456789";
return strnlen (a, 0);
}
size_t
f4 (void)
{
char a[20];
foo (a);
memcpy (a, "0123456789", 10);
return strnlen (a, 10);
}
size_t
f5 (void)
{
char a[20];
foo (a);
memcpy (a, "0123456789", 10);
return strnlen (a, 14);
}
size_t
f6 (void)
{
char a[20];
foo (a);
return strnlen (a, 0);
}
......@@ -156,7 +156,8 @@ struct decl_stridxlist_map
mappings. */
static hash_map<tree_decl_hash, stridxlist> *decl_to_stridxlist_htab;
/* Hash table mapping strlen calls to stridx instances describing
/* Hash table mapping strlen (or strnlen with constant bound and return
smaller than bound) calls to stridx instances describing
the calls' arguments. Non-null only when warn_stringop_truncation
is non-zero. */
typedef std::pair<int, location_t> stridx_strlenloc;
......@@ -1269,19 +1270,33 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
tree bound = (DECL_FUNCTION_CODE (callee) == BUILT_IN_STRNLEN
? gimple_call_arg (stmt, 1) : NULL_TREE);
int idx = get_stridx (src);
if (idx)
if (idx || (bound && integer_zerop (bound)))
{
strinfo *si = NULL;
tree rhs;
if (idx < 0)
rhs = build_int_cst (TREE_TYPE (lhs), ~idx);
else if (idx == 0)
rhs = bound;
else
{
rhs = NULL_TREE;
si = get_strinfo (idx);
if (si != NULL)
rhs = get_string_length (si);
{
rhs = get_string_length (si);
/* For strnlen, if bound is constant, even if si is not known
to be zero terminated, if we know at least bound bytes are
not zero, the return value will be bound. */
if (rhs == NULL_TREE
&& bound != NULL_TREE
&& TREE_CODE (bound) == INTEGER_CST
&& si->nonzero_chars != NULL_TREE
&& TREE_CODE (si->nonzero_chars) == INTEGER_CST
&& tree_int_cst_le (bound, si->nonzero_chars))
rhs = bound;
}
}
if (rhs != NULL_TREE)
{
......@@ -1294,18 +1309,8 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
/* Set for strnlen() calls with a non-constant bound. */
bool noncst_bound = false;
if (bound)
{
tree new_rhs
= fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (rhs), rhs, bound);
noncst_bound = (TREE_CODE (new_rhs) != INTEGER_CST
|| tree_int_cst_lt (new_rhs, rhs));
rhs = new_rhs;
}
rhs = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (rhs), rhs, bound);
if (!update_call_from_tree (gsi, rhs))
gimplify_and_update_call_from_tree (gsi, rhs);
......@@ -1317,12 +1322,9 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
}
/* Avoid storing the length for calls to strnlen() with
a non-constant bound. */
if (noncst_bound)
return;
if (si != NULL
/* Don't update anything for strnlen. */
&& bound == NULL_TREE
&& TREE_CODE (si->nonzero_chars) != SSA_NAME
&& TREE_CODE (si->nonzero_chars) != INTEGER_CST
&& !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
......@@ -1332,7 +1334,13 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
gcc_assert (si->full_string_p);
}
if (strlen_to_stridx)
if (strlen_to_stridx
&& (bound == NULL_TREE
/* For strnlen record this only if the call is proven
to return the same value as strlen would. */
|| (TREE_CODE (bound) == INTEGER_CST
&& TREE_CODE (rhs) == INTEGER_CST
&& tree_int_cst_lt (rhs, bound))))
strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
return;
......
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