gimple-fold.c (strlen_range_kind): New enum.

* gimple-fold.c (strlen_range_kind): New enum.
	(get_range_strlen): Update signature to use strlen_range_kind
	instead of type+fuzzy.
	(get_range_strlen_tree): Update signature to use
	strlen_range_kind instead of type+fuzzy.  Pass rkind down to
	get_range_strlen.  Check the rkind enum value instead of
	type+fuzzy.
	(get_range_strlen): Similarly.
	(get_maxval_strlen): Update signature to make NONSTR argument have
	a default value and make static.  Add asserts to ensure sanity of
	arguments.  Update calls to get_range_strlen.
	(gimple_fold_builtin_strcpy): Update calls to get_maxval_strlen.
	(gimple_fold_builtin_strcat, gimple_fold_builtin_fputs): Similarly.
	(gimple_fold_builtin_memory_chk): Similarly.
	(gimple_fold_builtin_stxcpy_chk): Similarly.
	(gimple_fold_builtin_snprintf_chk): Similarly.
	(gimple_fold_builtin_sprintf, gimple_fold_builtin_snprintf): Similarly.
	* gimple-fold.h (get_maxval_strlen): Delete prototype.

Co-Authored-By: Jeff Law <law@redhat.com>

From-SVN: r267482
This commit is contained in:
Martin Sebor 2018-12-31 01:01:10 +00:00 committed by Jeff Law
parent c43459cad8
commit 598f7235fb
3 changed files with 96 additions and 57 deletions

View File

@ -1,3 +1,25 @@
2018-12-30 Martin Sebor <msebor@redhat.com>
Jeff Law <law@redhat.com>
* gimple-fold.c (strlen_range_kind): New enum.
(get_range_strlen): Update signature to use strlen_range_kind
instead of type+fuzzy.
(get_range_strlen_tree): Update signature to use
strlen_range_kind instead of type+fuzzy. Pass rkind down to
get_range_strlen. Check the rkind enum value instead of
type+fuzzy.
(get_range_strlen): Similarly.
(get_maxval_strlen): Update signature to make NONSTR argument have
a default value and make static. Add asserts to ensure sanity of
arguments. Update calls to get_range_strlen.
(gimple_fold_builtin_strcpy): Update calls to get_maxval_strlen.
(gimple_fold_builtin_strcat, gimple_fold_builtin_fputs): Similarly.
(gimple_fold_builtin_memory_chk): Similarly.
(gimple_fold_builtin_stxcpy_chk): Similarly.
(gimple_fold_builtin_snprintf_chk): Similarly.
(gimple_fold_builtin_sprintf, gimple_fold_builtin_snprintf): Similarly.
* gimple-fold.h (get_maxval_strlen): Delete prototype.
2018-12-29 Jozef Lawrynowicz <jozef.l@mittosystems.com>
* config/msp430/msp430.c (msp430_attr): Warn when the critical and

View File

@ -66,8 +66,25 @@ along with GCC; see the file COPYING3. If not see
#include "tree-vector-builder.h"
#include "tree-ssa-strlen.h"
static bool get_range_strlen (tree, tree[2], bitmap *, int,
int, bool *, unsigned, tree *);
enum strlen_range_kind {
/* Compute the exact constant string length. */
SRK_STRLEN,
/* Compute the maximum constant string length. */
SRK_STRLENMAX,
/* Compute a range of string lengths bounded by object sizes. When
the length of a string cannot be determined, consider as the upper
bound the size of the enclosing object the string may be a member
or element of. Also determine the size of the largest character
array the string may refer to. */
SRK_LENRANGE,
/* Temporary until the rest of Martin's strlen range work is integrated. */
SRK_LENRANGE_2,
/* Determine the integer value of the argument (not string length). */
SRK_INT_VALUE
};
static bool get_range_strlen (tree, tree[2], bitmap *, strlen_range_kind,
bool *, unsigned, tree *);
/* Return true when DECL can be referenced from current unit.
FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
@ -1264,8 +1281,9 @@ gimple_fold_builtin_memset (gimple_stmt_iterator *gsi, tree c, tree len)
/* Helper of get_range_strlen for ARG that is not an SSA_NAME. */
static bool
get_range_strlen_tree (tree arg, tree length[2], bitmap *visited, int type,
int fuzzy, bool *flexp, unsigned eltsize, tree *nonstr)
get_range_strlen_tree (tree arg, tree length[2], bitmap *visited,
strlen_range_kind rkind,
bool *flexp, unsigned eltsize, tree *nonstr)
{
gcc_assert (TREE_CODE (arg) != SSA_NAME);
@ -1287,10 +1305,11 @@ get_range_strlen_tree (tree arg, tree length[2], bitmap *visited, int type,
if (TREE_CODE (aop0) == INDIRECT_REF
&& TREE_CODE (TREE_OPERAND (aop0, 0)) == SSA_NAME)
return get_range_strlen (TREE_OPERAND (aop0, 0), length,
visited, type, fuzzy, flexp,
visited, rkind, flexp,
eltsize, nonstr);
}
else if (TREE_CODE (TREE_OPERAND (op, 0)) == COMPONENT_REF && fuzzy)
else if (TREE_CODE (TREE_OPERAND (op, 0)) == COMPONENT_REF
&& (rkind == SRK_LENRANGE || rkind == SRK_LENRANGE_2))
{
/* Fail if an array is the last member of a struct object
since it could be treated as a (fake) flexible array
@ -1308,7 +1327,7 @@ get_range_strlen_tree (tree arg, tree length[2], bitmap *visited, int type,
}
}
if (type == 2)
if (rkind == SRK_INT_VALUE)
{
/* We are computing the maximum value (not string length). */
val = arg;
@ -1328,15 +1347,15 @@ get_range_strlen_tree (tree arg, tree length[2], bitmap *visited, int type,
*nonstr = lendata.decl;
*minlen = lendata.minlen;
*maxlen = lendata.minlen;
return type == 0 ? false : true;
return rkind == SRK_STRLEN ? false : true;
}
}
if (!val && fuzzy)
if (!val && (rkind == SRK_LENRANGE || rkind == SRK_LENRANGE_2))
{
if (TREE_CODE (arg) == ADDR_EXPR)
return get_range_strlen (TREE_OPERAND (arg, 0), length,
visited, type, fuzzy, flexp,
visited, rkind, flexp,
eltsize, nonstr);
if (TREE_CODE (arg) == ARRAY_REF)
@ -1435,7 +1454,7 @@ get_range_strlen_tree (tree arg, tree length[2], bitmap *visited, int type,
/* Adjust the lower bound on the string length as necessary. */
if (!*minlen
|| (type > 0
|| (rkind != SRK_STRLEN
&& TREE_CODE (*minlen) == INTEGER_CST
&& TREE_CODE (val) == INTEGER_CST
&& tree_int_cst_lt (val, *minlen)))
@ -1445,7 +1464,7 @@ get_range_strlen_tree (tree arg, tree length[2], bitmap *visited, int type,
{
/* Adjust the more conservative bound if possible/necessary
and fail otherwise. */
if (type > 0)
if (rkind != SRK_STRLEN)
{
if (TREE_CODE (*maxlen) != INTEGER_CST
|| TREE_CODE (val) != INTEGER_CST)
@ -1473,29 +1492,21 @@ get_range_strlen_tree (tree arg, tree length[2], bitmap *visited, int type,
TYPE == 0, if LENGTH[1] is not equal to the length we determine or
if we are unable to determine the length or value, return false.
VISITED is a bitmap of visited variables.
TYPE is 0 if string length should be obtained, 1 for maximum string
length and 2 for maximum value ARG can have.
When FUZZY is non-zero and the length of a string cannot be determined,
the function instead considers as the maximum possible length the
size of a character array it may refer to. If FUZZY is 2, it will handle
PHIs and COND_EXPRs optimistically, if we can determine string length
minimum and maximum, it will use the minimum from the ones where it
can be determined.
Set *FLEXP to true if the range of the string lengths has been
obtained from the upper bound of an array at the end of a struct.
Such an array may hold a string that's longer than its upper bound
due to it being used as a poor-man's flexible array member.
Pass NONSTR through to children.
ELTSIZE is 1 for normal single byte character strings, and 2 or
4 for wide characer strings. ELTSIZE is by default 1. */
RKIND determines the kind of value or range to obtain (see
strlen_range_kind).
Set PDATA->DECL if ARG refers to an unterminated constant array.
On input, set ELTSIZE to 1 for normal single byte character strings,
and either 2 or 4 for wide characer strings (the size of wchar_t).
Return true if *PDATA was successfully populated and false otherwise. */
static bool
get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
int fuzzy, bool *flexp, unsigned eltsize, tree *nonstr)
get_range_strlen (tree arg, tree length[2], bitmap *visited,
strlen_range_kind rkind,
bool *flexp, unsigned eltsize, tree *nonstr)
{
if (TREE_CODE (arg) != SSA_NAME)
return get_range_strlen_tree (arg, length, visited, type, fuzzy, flexp,
return get_range_strlen_tree (arg, length, visited, rkind, flexp,
eltsize, nonstr);
/* If ARG is registered for SSA update we cannot look at its defining
@ -1518,14 +1529,14 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
switch (gimple_code (def_stmt))
{
case GIMPLE_ASSIGN:
/* The RHS of the statement defining VAR must either have a
constant length or come from another SSA_NAME with a constant
length. */
/* The RHS of the statement defining VAR must either have a
constant length or come from another SSA_NAME with a constant
length. */
if (gimple_assign_single_p (def_stmt)
|| gimple_assign_unary_nop_p (def_stmt))
{
tree rhs = gimple_assign_rhs1 (def_stmt);
return get_range_strlen (rhs, length, visited, type, fuzzy, flexp,
tree rhs = gimple_assign_rhs1 (def_stmt);
return get_range_strlen (rhs, length, visited, rkind, flexp,
eltsize, nonstr);
}
else if (gimple_assign_rhs_code (def_stmt) == COND_EXPR)
@ -1534,10 +1545,10 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
gimple_assign_rhs3 (def_stmt) };
for (unsigned int i = 0; i < 2; i++)
if (!get_range_strlen (ops[i], length, visited, type, fuzzy,
if (!get_range_strlen (ops[i], length, visited, rkind,
flexp, eltsize, nonstr))
{
if (fuzzy == 2)
if (rkind == SRK_LENRANGE_2)
*maxlen = build_all_ones_cst (size_type_node);
else
return false;
@ -1547,8 +1558,8 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
return false;
case GIMPLE_PHI:
/* All the arguments of the PHI node must have the same constant
length. */
/* Unless RKIND == SRK_LENRANGE, all arguments of the PHI node
must have a constant length. */
for (unsigned i = 0; i < gimple_phi_num_args (def_stmt); i++)
{
tree arg = gimple_phi_arg (def_stmt, i)->def;
@ -1562,10 +1573,10 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
if (arg == gimple_phi_result (def_stmt))
continue;
if (!get_range_strlen (arg, length, visited, type, fuzzy, flexp,
if (!get_range_strlen (arg, length, visited, rkind, flexp,
eltsize, nonstr))
{
if (fuzzy == 2)
if (rkind == SRK_LENRANGE_2)
*maxlen = build_all_ones_cst (size_type_node);
else
return false;
@ -1617,7 +1628,8 @@ get_range_strlen (tree arg, tree minmaxlen[2], unsigned eltsize,
*nonstr = NULL_TREE;
bool flexarray = false;
if (!get_range_strlen (arg, minmaxlen, &visited, 1, strict ? 1 : 2,
if (!get_range_strlen (arg, minmaxlen, &visited,
strict ? SRK_LENRANGE : SRK_LENRANGE_2,
&flexarray, eltsize, nonstr))
{
minmaxlen[0] = NULL_TREE;
@ -1638,16 +1650,22 @@ get_range_strlen (tree arg, tree minmaxlen[2], unsigned eltsize,
unterminated strings, then bubble up the offending DECL and
return the maximum size. Otherwise return NULL. */
tree
get_maxval_strlen (tree arg, int type, tree *nonstr /* = NULL */)
static tree
get_maxval_strlen (tree arg, strlen_range_kind rkind, tree *nonstr = NULL)
{
/* A non-null NONSTR is meaningless when determining the maximum
value of an integer ARG. */
gcc_assert (rkind != SRK_INT_VALUE || nonstr == NULL);
/* ARG must have an integral type when RKIND says so. */
gcc_assert (rkind != SRK_INT_VALUE || INTEGRAL_TYPE_P (TREE_TYPE (arg)));
bitmap visited = NULL;
tree len[2] = { NULL_TREE, NULL_TREE };
bool dummy;
/* Set to non-null if ARG refers to an untermianted array. */
tree mynonstr = NULL_TREE;
if (!get_range_strlen (arg, len, &visited, type, 0, &dummy, 1, &mynonstr))
if (!get_range_strlen (arg, len, &visited, rkind, &dummy, 1, &mynonstr))
len[1] = NULL_TREE;
if (visited)
BITMAP_FREE (visited);
@ -1707,7 +1725,7 @@ gimple_fold_builtin_strcpy (gimple_stmt_iterator *gsi,
/* Set to non-null if ARG refers to an unterminated array. */
tree nonstr = NULL;
tree len = get_maxval_strlen (src, 0, &nonstr);
tree len = get_maxval_strlen (src, SRK_STRLEN, &nonstr);
if (nonstr)
{
@ -1753,7 +1771,7 @@ gimple_fold_builtin_strncpy (gimple_stmt_iterator *gsi,
/* Warn about the lack of nul termination: the result is not
a (nul-terminated) string. */
tree slen = get_maxval_strlen (src, 0);
tree slen = get_maxval_strlen (src, SRK_STRLEN);
if (slen && !integer_zerop (slen))
warning_at (loc, OPT_Wstringop_truncation,
"%G%qD destination unchanged after copying no bytes "
@ -1775,7 +1793,7 @@ gimple_fold_builtin_strncpy (gimple_stmt_iterator *gsi,
return false;
/* Now, we must be passed a constant src ptr parameter. */
tree slen = get_maxval_strlen (src, 0);
tree slen = get_maxval_strlen (src, SRK_STRLEN);
if (!slen || TREE_CODE (slen) != INTEGER_CST)
return false;
@ -1997,7 +2015,7 @@ gimple_fold_builtin_strcat (gimple_stmt_iterator *gsi, tree dst, tree src)
/* If the length of the source string isn't computable don't
split strcat into strlen and memcpy. */
tree len = get_maxval_strlen (src, 0);
tree len = get_maxval_strlen (src, SRK_STRLEN);
if (! len)
return false;
@ -2513,7 +2531,7 @@ gimple_fold_builtin_fputs (gimple_stmt_iterator *gsi,
/* Get the length of the string passed to fputs. If the length
can't be determined, punt. */
tree len = get_maxval_strlen (arg0, 0);
tree len = get_maxval_strlen (arg0, SRK_STRLEN);
if (!len
|| TREE_CODE (len) != INTEGER_CST)
return false;
@ -2601,7 +2619,7 @@ gimple_fold_builtin_memory_chk (gimple_stmt_iterator *gsi,
if (! tree_fits_uhwi_p (size))
return false;
tree maxlen = get_maxval_strlen (len, 2);
tree maxlen = get_maxval_strlen (len, SRK_INT_VALUE);
if (! integer_all_onesp (size))
{
if (! tree_fits_uhwi_p (len))
@ -2702,7 +2720,7 @@ gimple_fold_builtin_stxcpy_chk (gimple_stmt_iterator *gsi,
if (! tree_fits_uhwi_p (size))
return false;
tree maxlen = get_maxval_strlen (src, 1);
tree maxlen = get_maxval_strlen (src, SRK_STRLENMAX);
if (! integer_all_onesp (size))
{
len = c_strlen (src, 1);
@ -2798,7 +2816,7 @@ gimple_fold_builtin_stxncpy_chk (gimple_stmt_iterator *gsi,
if (! tree_fits_uhwi_p (size))
return false;
tree maxlen = get_maxval_strlen (len, 2);
tree maxlen = get_maxval_strlen (len, SRK_INT_VALUE);
if (! integer_all_onesp (size))
{
if (! tree_fits_uhwi_p (len))
@ -2935,7 +2953,7 @@ gimple_fold_builtin_snprintf_chk (gimple_stmt_iterator *gsi,
if (! integer_all_onesp (size))
{
tree maxlen = get_maxval_strlen (len, 2);
tree maxlen = get_maxval_strlen (len, SRK_INT_VALUE);
if (! tree_fits_uhwi_p (len))
{
/* If LEN is not constant, try MAXLEN too.
@ -3177,7 +3195,7 @@ gimple_fold_builtin_sprintf (gimple_stmt_iterator *gsi)
tree orig_len = NULL_TREE;
if (gimple_call_lhs (stmt))
{
orig_len = get_maxval_strlen (orig, 0);
orig_len = get_maxval_strlen (orig, SRK_STRLEN);
if (!orig_len)
return false;
}
@ -3310,7 +3328,7 @@ gimple_fold_builtin_snprintf (gimple_stmt_iterator *gsi)
if (!orig)
return false;
tree orig_len = get_maxval_strlen (orig, 0);
tree orig_len = get_maxval_strlen (orig, SRK_STRLEN);
if (!orig_len || TREE_CODE (orig_len) != INTEGER_CST)
return false;

View File

@ -27,7 +27,6 @@ extern tree canonicalize_constructor_val (tree, tree);
extern tree get_symbol_constant_value (tree);
extern bool get_range_strlen (tree, tree[2], unsigned = 1,
bool = false, tree * = NULL);
extern tree get_maxval_strlen (tree, int, tree * = NULL);
extern void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree);
extern bool fold_stmt (gimple_stmt_iterator *);
extern bool fold_stmt (gimple_stmt_iterator *, tree (*) (tree));