re PR middle-end/82123 (spurious -Wformat-overflow warning for converted vars)
PR middle-end/82123 PR tree-optimization/81592 PR middle-end/79257 * gimple-ssa-sprintf.c (get_int_range): Accept vr_values parameter pass it to children as needed. (struct directive::fmtresult): Similarly. (struct directive::set_width): Similarly. (struct directive::set_precision): Similarly. (format_integer, format_directive, parse_directive): Similarly. (format_none): Accept unnamed vr_values parameter. (format_percent, format_floating, format_character): Similarly. (format_string, format_plain): Similarly. From-SVN: r257854
This commit is contained in:
parent
c368450674
commit
bbe2e114ef
2 changed files with 50 additions and 31 deletions
|
@ -3,6 +3,15 @@
|
|||
PR middle-end/82123
|
||||
PR tree-optimization/81592
|
||||
PR middle-end/79257
|
||||
* gimple-ssa-sprintf.c (get_int_range): Accept vr_values parameter
|
||||
pass it to children as needed.
|
||||
(struct directive::fmtresult): Similarly.
|
||||
(struct directive::set_width): Similarly.
|
||||
(struct directive::set_precision): Similarly.
|
||||
(format_integer, format_directive, parse_directive): Similarly.
|
||||
(format_none): Accept unnamed vr_values parameter.
|
||||
(format_percent, format_floating, format_character): Similarly.
|
||||
(format_string, format_plain): Similarly.
|
||||
* gimple-ssa-sprintf.c (sprintf_dom_walker::handle_gimple_call): Query
|
||||
the EVRP range analyzer for range data rather than using global data.
|
||||
* gimple-ssa-sprintf.c: Include alloc-pool.h, vr-values.h and
|
||||
|
|
|
@ -771,7 +771,8 @@ fmtresult::type_max_digits (tree type, int base)
|
|||
}
|
||||
|
||||
static bool
|
||||
get_int_range (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, bool, HOST_WIDE_INT);
|
||||
get_int_range (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, bool, HOST_WIDE_INT,
|
||||
class vr_values *vr_values);
|
||||
|
||||
/* Description of a format directive. A directive is either a plain
|
||||
string or a conversion specification that starts with '%'. */
|
||||
|
@ -806,7 +807,7 @@ struct directive
|
|||
|
||||
/* Format conversion function that given a directive and an argument
|
||||
returns the formatting result. */
|
||||
fmtresult (*fmtfunc) (const directive &, tree);
|
||||
fmtresult (*fmtfunc) (const directive &, tree, vr_values *);
|
||||
|
||||
/* Return True when a the format flag CHR has been used. */
|
||||
bool get_flag (char chr) const
|
||||
|
@ -843,9 +844,9 @@ struct directive
|
|||
or 0, whichever is greater. For a non-constant ARG in some range
|
||||
set width to its range adjusting each bound to -1 if it's less.
|
||||
For an indeterminate ARG set width to [0, INT_MAX]. */
|
||||
void set_width (tree arg)
|
||||
void set_width (tree arg, vr_values *vr_values)
|
||||
{
|
||||
get_int_range (arg, width, width + 1, true, 0);
|
||||
get_int_range (arg, width, width + 1, true, 0, vr_values);
|
||||
}
|
||||
|
||||
/* Set both bounds of the precision range to VAL. */
|
||||
|
@ -859,9 +860,9 @@ struct directive
|
|||
or -1 whichever is greater. For a non-constant ARG in some range
|
||||
set precision to its range adjusting each bound to -1 if it's less.
|
||||
For an indeterminate ARG set precision to [-1, INT_MAX]. */
|
||||
void set_precision (tree arg)
|
||||
void set_precision (tree arg, vr_values *vr_values)
|
||||
{
|
||||
get_int_range (arg, prec, prec + 1, false, -1);
|
||||
get_int_range (arg, prec, prec + 1, false, -1, vr_values);
|
||||
}
|
||||
|
||||
/* Return true if both width and precision are known to be
|
||||
|
@ -1042,7 +1043,7 @@ struct sprintf_dom_walker::call_info
|
|||
/* Return the result of formatting a no-op directive (such as '%n'). */
|
||||
|
||||
static fmtresult
|
||||
format_none (const directive &, tree)
|
||||
format_none (const directive &, tree, vr_values *)
|
||||
{
|
||||
fmtresult res (0);
|
||||
return res;
|
||||
|
@ -1051,7 +1052,7 @@ format_none (const directive &, tree)
|
|||
/* Return the result of formatting the '%%' directive. */
|
||||
|
||||
static fmtresult
|
||||
format_percent (const directive &, tree)
|
||||
format_percent (const directive &, tree, vr_values *)
|
||||
{
|
||||
fmtresult res (1);
|
||||
return res;
|
||||
|
@ -1108,7 +1109,8 @@ build_intmax_type_nodes (tree *pintmax, tree *puintmax)
|
|||
|
||||
static bool
|
||||
get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax,
|
||||
bool absolute, HOST_WIDE_INT negbound)
|
||||
bool absolute, HOST_WIDE_INT negbound,
|
||||
class vr_values *vr_values)
|
||||
{
|
||||
/* The type of the result. */
|
||||
const_tree type = integer_type_node;
|
||||
|
@ -1179,7 +1181,8 @@ get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax,
|
|||
/* Handle an argument with an unknown range as if none had been
|
||||
provided. */
|
||||
if (unknown)
|
||||
return get_int_range (NULL_TREE, pmin, pmax, absolute, negbound);
|
||||
return get_int_range (NULL_TREE, pmin, pmax, absolute,
|
||||
negbound, vr_values);
|
||||
}
|
||||
|
||||
/* Adjust each bound as specified by ABSOLUTE and NEGBOUND. */
|
||||
|
@ -1264,7 +1267,7 @@ adjust_range_for_overflow (tree dirtype, tree *argmin, tree *argmax)
|
|||
used when the directive argument or its value isn't known. */
|
||||
|
||||
static fmtresult
|
||||
format_integer (const directive &dir, tree arg)
|
||||
format_integer (const directive &dir, tree arg, vr_values *vr_values)
|
||||
{
|
||||
tree intmax_type_node;
|
||||
tree uintmax_type_node;
|
||||
|
@ -1482,7 +1485,7 @@ format_integer (const directive &dir, tree arg)
|
|||
if (code == INTEGER_CST)
|
||||
{
|
||||
arg = gimple_assign_rhs1 (def);
|
||||
return format_integer (dir, arg);
|
||||
return format_integer (dir, arg, vr_values);
|
||||
}
|
||||
|
||||
if (code == NOP_EXPR)
|
||||
|
@ -1527,16 +1530,16 @@ format_integer (const directive &dir, tree arg)
|
|||
/* For unsigned conversions/directives or signed when
|
||||
the minimum is positive, use the minimum and maximum to compute
|
||||
the shortest and longest output, respectively. */
|
||||
res.range.min = format_integer (dir, argmin).range.min;
|
||||
res.range.max = format_integer (dir, argmax).range.max;
|
||||
res.range.min = format_integer (dir, argmin, vr_values).range.min;
|
||||
res.range.max = format_integer (dir, argmax, vr_values).range.max;
|
||||
}
|
||||
else if (tree_int_cst_sgn (argmax) < 0)
|
||||
{
|
||||
/* For signed conversions/directives if maximum is negative,
|
||||
use the minimum as the longest output and maximum as the
|
||||
shortest output. */
|
||||
res.range.min = format_integer (dir, argmax).range.min;
|
||||
res.range.max = format_integer (dir, argmin).range.max;
|
||||
res.range.min = format_integer (dir, argmax, vr_values).range.min;
|
||||
res.range.max = format_integer (dir, argmin, vr_values).range.max;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1544,9 +1547,12 @@ format_integer (const directive &dir, tree arg)
|
|||
as the shortest output and for the longest output compute the
|
||||
length of the output of both minimum and maximum and pick the
|
||||
longer. */
|
||||
unsigned HOST_WIDE_INT max1 = format_integer (dir, argmin).range.max;
|
||||
unsigned HOST_WIDE_INT max2 = format_integer (dir, argmax).range.max;
|
||||
res.range.min = format_integer (dir, integer_zero_node).range.min;
|
||||
unsigned HOST_WIDE_INT max1
|
||||
= format_integer (dir, argmin, vr_values).range.max;
|
||||
unsigned HOST_WIDE_INT max2
|
||||
= format_integer (dir, argmax, vr_values).range.max;
|
||||
res.range.min
|
||||
= format_integer (dir, integer_zero_node, vr_values).range.min;
|
||||
res.range.max = MAX (max1, max2);
|
||||
}
|
||||
|
||||
|
@ -1887,7 +1893,7 @@ format_floating (const directive &dir, const HOST_WIDE_INT prec[2])
|
|||
ARG. */
|
||||
|
||||
static fmtresult
|
||||
format_floating (const directive &dir, tree arg)
|
||||
format_floating (const directive &dir, tree arg, vr_values *)
|
||||
{
|
||||
HOST_WIDE_INT prec[] = { dir.prec[0], dir.prec[1] };
|
||||
tree type = (dir.modifier == FMT_LEN_L || dir.modifier == FMT_LEN_ll
|
||||
|
@ -2127,7 +2133,7 @@ get_string_length (tree str)
|
|||
vsprinf). */
|
||||
|
||||
static fmtresult
|
||||
format_character (const directive &dir, tree arg)
|
||||
format_character (const directive &dir, tree arg, vr_values *vr_values)
|
||||
{
|
||||
fmtresult res;
|
||||
|
||||
|
@ -2139,7 +2145,7 @@ format_character (const directive &dir, tree arg)
|
|||
res.range.min = 0;
|
||||
|
||||
HOST_WIDE_INT min, max;
|
||||
if (get_int_range (arg, &min, &max, false, 0))
|
||||
if (get_int_range (arg, &min, &max, false, 0, vr_values))
|
||||
{
|
||||
if (min == 0 && max == 0)
|
||||
{
|
||||
|
@ -2192,7 +2198,7 @@ format_character (const directive &dir, tree arg)
|
|||
vsprinf). */
|
||||
|
||||
static fmtresult
|
||||
format_string (const directive &dir, tree arg)
|
||||
format_string (const directive &dir, tree arg, vr_values *)
|
||||
{
|
||||
fmtresult res;
|
||||
|
||||
|
@ -2353,7 +2359,7 @@ format_string (const directive &dir, tree arg)
|
|||
/* Format plain string (part of the format string itself). */
|
||||
|
||||
static fmtresult
|
||||
format_plain (const directive &dir, tree)
|
||||
format_plain (const directive &dir, tree, vr_values *)
|
||||
{
|
||||
fmtresult res (dir.len);
|
||||
return res;
|
||||
|
@ -2734,7 +2740,8 @@ maybe_warn (substring_loc &dirloc, location_t argloc,
|
|||
|
||||
static bool
|
||||
format_directive (const sprintf_dom_walker::call_info &info,
|
||||
format_result *res, const directive &dir)
|
||||
format_result *res, const directive &dir,
|
||||
class vr_values *vr_values)
|
||||
{
|
||||
/* Offset of the beginning of the directive from the beginning
|
||||
of the format string. */
|
||||
|
@ -2759,7 +2766,7 @@ format_directive (const sprintf_dom_walker::call_info &info,
|
|||
return false;
|
||||
|
||||
/* Compute the range of lengths of the formatted output. */
|
||||
fmtresult fmtres = dir.fmtfunc (dir, dir.arg);
|
||||
fmtresult fmtres = dir.fmtfunc (dir, dir.arg, vr_values);
|
||||
|
||||
/* Record whether the output of all directives is known to be
|
||||
bounded by some maximum, implying that their arguments are
|
||||
|
@ -3025,7 +3032,8 @@ format_directive (const sprintf_dom_walker::call_info &info,
|
|||
static size_t
|
||||
parse_directive (sprintf_dom_walker::call_info &info,
|
||||
directive &dir, format_result *res,
|
||||
const char *str, unsigned *argno)
|
||||
const char *str, unsigned *argno,
|
||||
vr_values *vr_values)
|
||||
{
|
||||
const char *pcnt = strchr (str, target_percent);
|
||||
dir.beg = str;
|
||||
|
@ -3343,7 +3351,7 @@ parse_directive (sprintf_dom_walker::call_info &info,
|
|||
if (star_width)
|
||||
{
|
||||
if (INTEGRAL_TYPE_P (TREE_TYPE (star_width)))
|
||||
dir.set_width (star_width);
|
||||
dir.set_width (star_width, vr_values);
|
||||
else
|
||||
{
|
||||
/* Width specified by a va_list takes on the range [0, -INT_MIN]
|
||||
|
@ -3376,7 +3384,7 @@ parse_directive (sprintf_dom_walker::call_info &info,
|
|||
if (star_precision)
|
||||
{
|
||||
if (INTEGRAL_TYPE_P (TREE_TYPE (star_precision)))
|
||||
dir.set_precision (star_precision);
|
||||
dir.set_precision (star_precision, vr_values);
|
||||
else
|
||||
{
|
||||
/* Precision specified by a va_list takes on the range [-1, INT_MAX]
|
||||
|
@ -3498,10 +3506,12 @@ sprintf_dom_walker::compute_format_length (call_info &info,
|
|||
directive dir = directive ();
|
||||
dir.dirno = dirno;
|
||||
|
||||
size_t n = parse_directive (info, dir, res, pf, &argno);
|
||||
size_t n = parse_directive (info, dir, res, pf, &argno,
|
||||
evrp_range_analyzer.get_vr_values ());
|
||||
|
||||
/* Return failure if the format function fails. */
|
||||
if (!format_directive (info, res, dir))
|
||||
if (!format_directive (info, res, dir,
|
||||
evrp_range_analyzer.get_vr_values ()))
|
||||
return false;
|
||||
|
||||
/* Return success the directive is zero bytes long and it's
|
||||
|
|
Loading…
Add table
Reference in a new issue