From f589a1ce25d8320f4dc552b91949181edd616b64 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Fri, 3 Feb 2017 22:47:35 +0000 Subject: 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 --- gcc/gimple-ssa-sprintf.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) (limited to 'gcc/gimple-ssa-sprintf.c') 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)); -- cgit v1.2.1