Commit bbe2e114 by Jeff Law Committed by Jeff Law

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