summaryrefslogtreecommitdiff
path: root/gcc/gimple-ssa-sprintf.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2017-02-03 22:47:35 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2017-02-03 15:47:35 -0700
commitf589a1ce25d8320f4dc552b91949181edd616b64 (patch)
tree1461f1a2bcdcc21ca51798e6997b3e9b269b555f /gcc/gimple-ssa-sprintf.c
parent77095a6ab13996a38b0a360d8ef9fc6cc6bc5234 (diff)
downloadgcc-f589a1ce25d8320f4dc552b91949181edd616b64.tar.gz
PR tree-optimization/79327 - wrong code at -O2 and -fprintf-return-value
PR tree-optimization/79327 - wrong code at -O2 and -fprintf-return-value gcc/ChangeLog: * gimple-ssa-sprintf.c (tree_digits): Avoid adding the base prefix when precision has resulted in leading zeros. (format_integer): Adjust the likely counter to assume an unknown argument that may be zero is non-zero. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Adjust. * gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-13.c: New test. * gcc/testsuite/gcc.dg/tree-ssa/pr79327-2.c: Ditto. From-SVN: r245173
Diffstat (limited to 'gcc/gimple-ssa-sprintf.c')
-rw-r--r--gcc/gimple-ssa-sprintf.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index ac4e959ed3c..e6cc31d1c48 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -762,7 +762,9 @@ tree_digits (tree x, int base, HOST_WIDE_INT prec, bool plus, bool prefix)
res += prec < ndigs ? ndigs : prec;
- if (prefix && absval)
+ /* Adjust a non-zero value for the base prefix, either hexadecimal,
+ or, unless precision has resulted in a leading zero, also octal. */
+ if (prefix && absval && (base == 16 || prec <= ndigs))
{
if (base == 8)
res += 1;
@@ -1230,6 +1232,10 @@ format_integer (const directive &dir, tree arg)
of the format string by returning [-1, -1]. */
return fmtresult ();
+ /* True if the LIKELY counter should be adjusted upward from the MIN
+ counter to account for arguments with unknown values. */
+ bool likely_adjust = false;
+
fmtresult res;
/* Using either the range the non-constant argument is in, or its
@@ -1259,6 +1265,14 @@ 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 (wi::le_p (min, wzero, SIGNED)
+ && !wi::neg_p (max))
+ likely_adjust = true;
}
else if (range_type == VR_ANTI_RANGE)
{
@@ -1293,6 +1307,11 @@ format_integer (const directive &dir, tree arg)
if (!argmin)
{
+ /* Set the adjustment for an argument whose range includes
+ zero since that doesn't include the octal or hexadecimal
+ base prefix. */
+ likely_adjust = true;
+
if (TREE_CODE (argtype) == POINTER_TYPE)
{
argmin = build_int_cst (pointer_sized_int_node, 0);
@@ -1345,7 +1364,24 @@ format_integer (const directive &dir, tree arg)
res.range.max = MAX (max1, max2);
}
- res.range.likely = res.knownrange ? res.range.max : res.range.min;
+ /* Add the adjustment for an argument whose range includes zero
+ since it doesn't include the octal or hexadecimal base prefix. */
+ if (res.knownrange)
+ res.range.likely = res.range.max;
+ else
+ {
+ res.range.likely = res.range.min;
+ if (likely_adjust && maybebase && base != 10)
+ {
+ if (res.range.min == 1)
+ res.range.likely += base == 8 ? 1 : 2;
+ else if (res.range.min == 2
+ && base == 16
+ && (dir.width[0] == 2 || dir.prec[0] == 2))
+ ++res.range.likely;
+ }
+ }
+
res.range.unlikely = res.range.max;
res.adjust_for_width_or_precision (dir.width, dirtype, base,
(sign | maybebase) + (base == 16));