Avoid assuming maximum string length is constant [PR102960].
Resolves: PR tree-optimization/102960 - ICE: in sign_mask, at wide-int.h:855 in GCC 10.3.0 gcc/ChangeLog: PR tree-optimization/102960 * gimple-fold.c (get_range_strlen): Take bitmap as an argument rather than a pointer to it. (get_range_strlen_tree): Same. Remove bitmap allocation. Use an auto_bitmap. (get_maxval_strlen): Use an auto_bitmap. * tree-ssa-strlen.c (get_range_strlen_dynamic): Factor out PHI handling... (get_range_strlen_phi): ...into this function. Avoid assuming maximum string length is constant (printf_strlen_execute): Dump pointer query cache contents when details are requisted. gcc/testsuite/ChangeLog: PR tree-optimization/102960 * gcc.dg/Wstringop-overflow-84.c: New test.
This commit is contained in:
parent
0002a8a199
commit
ba6e17e78d
|
@ -86,7 +86,7 @@ enum strlen_range_kind {
|
|||
};
|
||||
|
||||
static bool
|
||||
get_range_strlen (tree, bitmap *, strlen_range_kind, c_strlen_data *, unsigned);
|
||||
get_range_strlen (tree, bitmap, strlen_range_kind, c_strlen_data *, unsigned);
|
||||
|
||||
/* Return true when DECL can be referenced from current unit.
|
||||
FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
|
||||
|
@ -1525,7 +1525,7 @@ 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, bitmap *visited, strlen_range_kind rkind,
|
||||
get_range_strlen_tree (tree arg, bitmap visited, strlen_range_kind rkind,
|
||||
c_strlen_data *pdata, unsigned eltsize)
|
||||
{
|
||||
gcc_assert (TREE_CODE (arg) != SSA_NAME);
|
||||
|
@ -1849,7 +1849,7 @@ get_range_strlen_tree (tree arg, bitmap *visited, strlen_range_kind rkind,
|
|||
Return true if *PDATA was successfully populated and false otherwise. */
|
||||
|
||||
static bool
|
||||
get_range_strlen (tree arg, bitmap *visited,
|
||||
get_range_strlen (tree arg, bitmap visited,
|
||||
strlen_range_kind rkind,
|
||||
c_strlen_data *pdata, unsigned eltsize)
|
||||
{
|
||||
|
@ -1863,9 +1863,7 @@ get_range_strlen (tree arg, bitmap *visited,
|
|||
return false;
|
||||
|
||||
/* If we were already here, break the infinite cycle. */
|
||||
if (!*visited)
|
||||
*visited = BITMAP_ALLOC (NULL);
|
||||
if (!bitmap_set_bit (*visited, SSA_NAME_VERSION (arg)))
|
||||
if (!bitmap_set_bit (visited, SSA_NAME_VERSION (arg)))
|
||||
return true;
|
||||
|
||||
tree var = arg;
|
||||
|
@ -1962,10 +1960,10 @@ get_range_strlen (tree arg, bitmap *visited,
|
|||
bool
|
||||
get_range_strlen (tree arg, c_strlen_data *pdata, unsigned eltsize)
|
||||
{
|
||||
bitmap visited = NULL;
|
||||
auto_bitmap visited;
|
||||
tree maxbound = pdata->maxbound;
|
||||
|
||||
if (!get_range_strlen (arg, &visited, SRK_LENRANGE, pdata, eltsize))
|
||||
if (!get_range_strlen (arg, visited, SRK_LENRANGE, pdata, eltsize))
|
||||
{
|
||||
/* On failure extend the length range to an impossible maximum
|
||||
(a valid MAXLEN must be less than PTRDIFF_MAX - 1). Other
|
||||
|
@ -1981,9 +1979,6 @@ get_range_strlen (tree arg, c_strlen_data *pdata, unsigned eltsize)
|
|||
if (maxbound && pdata->maxbound == maxbound)
|
||||
pdata->maxbound = build_all_ones_cst (size_type_node);
|
||||
|
||||
if (visited)
|
||||
BITMAP_FREE (visited);
|
||||
|
||||
return !integer_all_onesp (pdata->maxlen);
|
||||
}
|
||||
|
||||
|
@ -2005,19 +2000,16 @@ get_maxval_strlen (tree arg, strlen_range_kind rkind, tree *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;
|
||||
auto_bitmap visited;
|
||||
|
||||
/* Reset DATA.MAXLEN if the call fails or when DATA.MAXLEN
|
||||
is unbounded. */
|
||||
c_strlen_data lendata = { };
|
||||
if (!get_range_strlen (arg, &visited, rkind, &lendata, /* eltsize = */1))
|
||||
if (!get_range_strlen (arg, visited, rkind, &lendata, /* eltsize = */1))
|
||||
lendata.maxlen = NULL_TREE;
|
||||
else if (lendata.maxlen && integer_all_onesp (lendata.maxlen))
|
||||
lendata.maxlen = NULL_TREE;
|
||||
|
||||
if (visited)
|
||||
BITMAP_FREE (visited);
|
||||
|
||||
if (nonstr)
|
||||
{
|
||||
/* For callers prepared to handle unterminated arrays set
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/* PR middle-end/102960 - ICE: in sign_mask, at wide-int.h:855 in GCC 10.3.0
|
||||
{ dg-do compile }
|
||||
{ dg-options "-Og -Wall" } */
|
||||
|
||||
void f (int i)
|
||||
{
|
||||
const char *s;
|
||||
if (i)
|
||||
s = &"abcd"[i];
|
||||
|
||||
__builtin_printf ("%s", s);
|
||||
}
|
||||
|
||||
/* The use of s in the call to sprintf should result in:
|
||||
{ dg-prune-output "-Wmaybe-uninitialized" } */
|
|
@ -193,6 +193,8 @@ struct laststmt_struct
|
|||
} laststmt;
|
||||
|
||||
static int get_stridx_plus_constant (strinfo *, unsigned HOST_WIDE_INT, tree);
|
||||
static bool get_range_strlen_dynamic (tree, gimple *s, c_strlen_data *,
|
||||
bitmap, range_query *, unsigned *);
|
||||
|
||||
/* Sets MINMAX to either the constant value or the range VAL is in
|
||||
and returns either the constant value or VAL on success or null
|
||||
|
@ -1087,6 +1089,76 @@ dump_strlen_info (FILE *fp, gimple *stmt, range_query *rvals)
|
|||
}
|
||||
}
|
||||
|
||||
/* Helper of get_range_strlen_dynamic(). See below. */
|
||||
|
||||
static bool
|
||||
get_range_strlen_phi (tree src, gphi *phi,
|
||||
c_strlen_data *pdata, bitmap visited,
|
||||
range_query *rvals, unsigned *pssa_def_max)
|
||||
{
|
||||
if (!bitmap_set_bit (visited, SSA_NAME_VERSION (src)))
|
||||
return true;
|
||||
|
||||
if (*pssa_def_max == 0)
|
||||
return false;
|
||||
|
||||
--*pssa_def_max;
|
||||
|
||||
/* Iterate over the PHI arguments and determine the minimum and maximum
|
||||
length/size of each and incorporate them into the overall result. */
|
||||
for (unsigned i = 0; i != gimple_phi_num_args (phi); ++i)
|
||||
{
|
||||
tree arg = gimple_phi_arg_def (phi, i);
|
||||
if (arg == gimple_phi_result (phi))
|
||||
continue;
|
||||
|
||||
c_strlen_data argdata = { };
|
||||
if (!get_range_strlen_dynamic (arg, phi, &argdata, visited, rvals,
|
||||
pssa_def_max))
|
||||
{
|
||||
pdata->maxlen = build_all_ones_cst (size_type_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Set the DECL of an unterminated array this argument refers to
|
||||
if one hasn't been found yet. */
|
||||
if (!pdata->decl && argdata.decl)
|
||||
pdata->decl = argdata.decl;
|
||||
|
||||
if (!argdata.minlen
|
||||
|| (integer_zerop (argdata.minlen)
|
||||
&& (!argdata.maxbound
|
||||
|| integer_all_onesp (argdata.maxbound))
|
||||
&& integer_all_onesp (argdata.maxlen)))
|
||||
{
|
||||
/* Set the upper bound of the length to unbounded. */
|
||||
pdata->maxlen = build_all_ones_cst (size_type_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Adjust the minimum and maximum length determined so far and
|
||||
the upper bound on the array size. */
|
||||
if (!pdata->minlen
|
||||
|| tree_int_cst_lt (argdata.minlen, pdata->minlen))
|
||||
pdata->minlen = argdata.minlen;
|
||||
|
||||
if (!pdata->maxlen
|
||||
|| (argdata.maxlen
|
||||
&& TREE_CODE (argdata.maxlen) == INTEGER_CST
|
||||
&& tree_int_cst_lt (pdata->maxlen, argdata.maxlen)))
|
||||
pdata->maxlen = argdata.maxlen;
|
||||
|
||||
if (!pdata->maxbound
|
||||
|| TREE_CODE (pdata->maxbound) != INTEGER_CST
|
||||
|| (argdata.maxbound
|
||||
&& tree_int_cst_lt (pdata->maxbound, argdata.maxbound)
|
||||
&& !integer_all_onesp (argdata.maxbound)))
|
||||
pdata->maxbound = argdata.maxbound;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Attempt to determine the length of the string SRC. On success, store
|
||||
the length in *PDATA and return true. Otherwise, return false.
|
||||
VISITED is a bitmap of visited PHI nodes. RVALS points to the valuation
|
||||
|
@ -1095,7 +1167,7 @@ dump_strlen_info (FILE *fp, gimple *stmt, range_query *rvals)
|
|||
|
||||
static bool
|
||||
get_range_strlen_dynamic (tree src, gimple *stmt,
|
||||
c_strlen_data *pdata, bitmap *visited,
|
||||
c_strlen_data *pdata, bitmap visited,
|
||||
range_query *rvals, unsigned *pssa_def_max)
|
||||
{
|
||||
int idx = get_stridx (src, stmt);
|
||||
|
@ -1104,72 +1176,9 @@ get_range_strlen_dynamic (tree src, gimple *stmt,
|
|||
if (TREE_CODE (src) == SSA_NAME)
|
||||
{
|
||||
gimple *def_stmt = SSA_NAME_DEF_STMT (src);
|
||||
if (gimple_code (def_stmt) == GIMPLE_PHI)
|
||||
{
|
||||
if (!*visited)
|
||||
*visited = BITMAP_ALLOC (NULL);
|
||||
|
||||
if (!bitmap_set_bit (*visited, SSA_NAME_VERSION (src)))
|
||||
return true;
|
||||
|
||||
if (*pssa_def_max == 0)
|
||||
return false;
|
||||
|
||||
--*pssa_def_max;
|
||||
|
||||
/* Iterate over the PHI arguments and determine the minimum
|
||||
and maximum length/size of each and incorporate them into
|
||||
the overall result. */
|
||||
gphi *phi = as_a <gphi *> (def_stmt);
|
||||
for (unsigned i = 0; i != gimple_phi_num_args (phi); ++i)
|
||||
{
|
||||
tree arg = gimple_phi_arg_def (phi, i);
|
||||
if (arg == gimple_phi_result (def_stmt))
|
||||
continue;
|
||||
|
||||
c_strlen_data argdata = { };
|
||||
if (get_range_strlen_dynamic (arg, phi, &argdata, visited,
|
||||
rvals, pssa_def_max))
|
||||
{
|
||||
/* Set the DECL of an unterminated array this argument
|
||||
refers to if one hasn't been found yet. */
|
||||
if (!pdata->decl && argdata.decl)
|
||||
pdata->decl = argdata.decl;
|
||||
|
||||
if (!argdata.minlen
|
||||
|| (integer_zerop (argdata.minlen)
|
||||
&& (!argdata.maxbound
|
||||
|| integer_all_onesp (argdata.maxbound))
|
||||
&& integer_all_onesp (argdata.maxlen)))
|
||||
{
|
||||
/* Set the upper bound of the length to unbounded. */
|
||||
pdata->maxlen = build_all_ones_cst (size_type_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Adjust the minimum and maximum length determined
|
||||
so far and the upper bound on the array size. */
|
||||
if (!pdata->minlen
|
||||
|| tree_int_cst_lt (argdata.minlen, pdata->minlen))
|
||||
pdata->minlen = argdata.minlen;
|
||||
if (!pdata->maxlen
|
||||
|| (argdata.maxlen
|
||||
&& tree_int_cst_lt (pdata->maxlen, argdata.maxlen)))
|
||||
pdata->maxlen = argdata.maxlen;
|
||||
if (!pdata->maxbound
|
||||
|| TREE_CODE (pdata->maxbound) != INTEGER_CST
|
||||
|| (argdata.maxbound
|
||||
&& tree_int_cst_lt (pdata->maxbound,
|
||||
argdata.maxbound)
|
||||
&& !integer_all_onesp (argdata.maxbound)))
|
||||
pdata->maxbound = argdata.maxbound;
|
||||
}
|
||||
else
|
||||
pdata->maxlen = build_all_ones_cst (size_type_node);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
if (gphi *phi = dyn_cast<gphi *>(def_stmt))
|
||||
return get_range_strlen_phi (src, phi, pdata, visited, rvals,
|
||||
pssa_def_max);
|
||||
}
|
||||
|
||||
/* Return success regardless of the result and handle *PDATA
|
||||
|
@ -1286,11 +1295,11 @@ void
|
|||
get_range_strlen_dynamic (tree src, gimple *stmt, c_strlen_data *pdata,
|
||||
range_query *rvals)
|
||||
{
|
||||
bitmap visited = NULL;
|
||||
auto_bitmap visited;
|
||||
tree maxbound = pdata->maxbound;
|
||||
|
||||
unsigned limit = param_ssa_name_def_chain_limit;
|
||||
if (!get_range_strlen_dynamic (src, stmt, pdata, &visited, rvals, &limit))
|
||||
if (!get_range_strlen_dynamic (src, stmt, pdata, visited, rvals, &limit))
|
||||
{
|
||||
/* On failure extend the length range to an impossible maximum
|
||||
(a valid MAXLEN must be less than PTRDIFF_MAX - 1). Other
|
||||
|
@ -1305,9 +1314,6 @@ get_range_strlen_dynamic (tree src, gimple *stmt, c_strlen_data *pdata,
|
|||
MAXBOUND to SIZE_MAX. Otherwise leave it null (if it is null). */
|
||||
if (maxbound && pdata->maxbound == maxbound)
|
||||
pdata->maxbound = build_all_ones_cst (size_type_node);
|
||||
|
||||
if (visited)
|
||||
BITMAP_FREE (visited);
|
||||
}
|
||||
|
||||
/* Invalidate string length information for strings whose length might
|
||||
|
@ -5831,7 +5837,7 @@ printf_strlen_execute (function *fun, bool warn_only)
|
|||
walker.walk (ENTRY_BLOCK_PTR_FOR_FN (fun));
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
walker.ptr_qry.dump (dump_file);
|
||||
walker.ptr_qry.dump (dump_file, true);
|
||||
|
||||
ssa_ver_to_stridx.release ();
|
||||
strinfo_pool.release ();
|
||||
|
|
Loading…
Reference in New Issue