}
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 '%'. */
/* 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
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. */
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
/* 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;
/* 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;
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;
/* 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. */
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;
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)
/* 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
{
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);
}
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
vsprinf). */
static fmtresult
-format_character (const directive &dir, tree arg)
+format_character (const directive &dir, tree arg, vr_values *vr_values)
{
fmtresult res;
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)
{
vsprinf). */
static fmtresult
-format_string (const directive &dir, tree arg)
+format_string (const directive &dir, tree arg, vr_values *)
{
fmtresult res;
/* 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;
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. */
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
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;
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]
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]
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