diff options
author | Martin Sebor <msebor@redhat.com> | 2017-02-03 22:47:35 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2017-02-03 15:47:35 -0700 |
commit | f589a1ce25d8320f4dc552b91949181edd616b64 (patch) | |
tree | 1461f1a2bcdcc21ca51798e6997b3e9b269b555f /gcc/gimple-ssa-sprintf.c | |
parent | 77095a6ab13996a38b0a360d8ef9fc6cc6bc5234 (diff) | |
download | gcc-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.c | 40 |
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)); |