aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2018-12-31 01:01:10 +0000
committerJeff Law <law@gcc.gnu.org>2018-12-30 18:01:10 -0700
commit598f7235fb4e9d6c201999d66f1db2b247d74de3 (patch)
tree89cf4de700b14afe3ba494d93c7e7f9cfb73e54f
parentc43459cad848d5137426676f52976994cc221902 (diff)
downloadgcc-598f7235fb4e9d6c201999d66f1db2b247d74de3.zip
gcc-598f7235fb4e9d6c201999d66f1db2b247d74de3.tar.gz
gcc-598f7235fb4e9d6c201999d66f1db2b247d74de3.tar.bz2
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
-rw-r--r--gcc/ChangeLog22
-rw-r--r--gcc/gimple-fold.c130
-rw-r--r--gcc/gimple-fold.h1
3 files changed, 96 insertions, 57 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index bb02095..1ee865e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 4f84f0c..76fa328 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -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;
diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h
index 26e2727..e1da276 100644
--- a/gcc/gimple-fold.h
+++ b/gcc/gimple-fold.h
@@ -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));