On Thu, Feb 02, 2017 at 05:31:19PM -0700, Martin Sebor wrote:
> index 9e099f0..84dd3671 100644
> --- a/gcc/gimple-ssa-sprintf.c
> +++ b/gcc/gimple-ssa-sprintf.c
> @@ -1242,6 +1242,10 @@ format_integer (const directive &dir, tree arg)
> of the format string by returning [-1, -1]. */
> return fmtresult ();
>
> + /* The adjustment to add to the MIN counter when computing the LIKELY
> + counter for arguments with unknown values. */
> + unsigned likely_adjust = 0;
> +
> fmtresult res;
>
> /* Using either the range the non-constant argument is in, or its
> @@ -1273,6 +1277,15 @@ format_integer (const directive &dir, tree arg)
>
> res.argmin = argmin;
> res.argmax = argmax;
> +
> + /* Set the adjustment for an argument whose range includes
> + zero since that doesn't include the octal or hexadecimal
> + base prefix. */
> + wide_int wzero = wi::zero (wi::get_precision (min));
> + if (maybebase
> + && wi::le_p (min, wzero, SIGNED)
> + && wi::le_p (wzero, max, SIGNED))
> + likely_adjust = base == 8 ? 1 : base == 16 ? 2 : 0;
> }
> else if (range_type == VR_ANTI_RANGE)
> {
> @@ -1311,11 +1324,14 @@ format_integer (const directive &dir, tree arg)
> or one whose value range cannot be determined, create a T_MIN
> constant if the argument's type is signed and T_MAX otherwise,
> and use those to compute the range of bytes that the directive
> - can output. When precision may be zero, use zero as the minimum
> - since it results in no bytes on output (unless width is specified
> - to be greater than 0). */
> - bool zero = dir.prec[0] <= 0 && dir.prec[1] >= 0;
> - argmin = build_int_cst (argtype, !zero);
> + can output. */
> + argmin = integer_zero_node;
> +
> + /* Set the adjustment for an argument whose range includes
> + zero since that doesn't include the octal or hexadecimal
> + base prefix. */
> + if (maybebase)
> + likely_adjust = base == 8 ? 1 : base == 16 ? 2 : 0;
This is another sign why the patch I've posted is desirable. Now you have
to tweak several places, with the patch just one, you have a final range
and you can check whether it includes zero or not.
wi::le_p (wzero, max, SIGNED) is !wi::neg_p (max) I think.
That said, adding something to res.range.min looks wrong to me, you don't
know without more analysis whether actually the length for 0 and length for
say 1 or -1 isn't the same.
Consider %#x where indeed 0 is 2 byte shorter than 1, but say %#3x where
it is the same length, so if you still add your likely_adjust of 2 to that,
the res.range.likely value will be suddenly 5 instead of correct 3.
Easier would be to see if 0 is in the range, see if 1 is also in the range
and set res.range.likely to the length of 1, or, if 0 is in the range, 1
is not but -1 is, to that of -1 or something like that.
Jakub