diff options
author | Martin Sebor <msebor@redhat.com> | 2017-01-08 23:42:09 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2017-01-08 16:42:09 -0700 |
commit | efcc8d387f52f995a6e41bc78a76cc77e4bb6ee8 (patch) | |
tree | f91cdc7136d16f3e039d0ea98daf535a9c7c6f30 /gcc/gimple-ssa-sprintf.c | |
parent | 1243c42d6457fd2b09917b5789c8c42dd13437ec (diff) | |
download | gcc-efcc8d387f52f995a6e41bc78a76cc77e4bb6ee8.zip gcc-efcc8d387f52f995a6e41bc78a76cc77e4bb6ee8.tar.gz gcc-efcc8d387f52f995a6e41bc78a76cc77e4bb6ee8.tar.bz2 |
PR tree-optimization/78913 - Probably misleading error reported by -Wformat-length
PR tree-optimization/78913 - Probably misleading error reported by -Wformat-length
PR middle-end/77708 - -Wformat-length %s warns for snprintf
gcc/ChangeLog:
PR middle-end/77708
* doc/invoke.texi (Warning Options): Document -Wformat-truncation.
* gimple-ssa-sprintf.c (call_info::reval_used, call_info::warnopt):
New member functions.
(format_directive): Used them.
(add_bytes): Same.
(pass_sprintf_length::handle_gimple_call): Same.
* graphite-sese-to-poly.c (tree_int_to_gmp): Increase buffer size
to avoid truncation for any argument.
(extract_affine_mul): Same.
* tree.c (get_file_function_name): Same.
gcc/c-family/ChangeLog:
PR middle-end/77708
* c.opt (-Wformat-truncation): New option.
gcc/fortran/ChangeLog:
PR tree-optimization/78913
PR middle-end/77708
* trans-common.c (build_equiv_decl): Increase buffer size to avoid
truncation for any argument.
* trans-types.c (gfc_build_logical_type): Same.
gcc/testsuite/ChangeLog:
PR middle-end/77708
* gcc.dg/tree-ssa/builtin-snprintf-warn-1.c: New test.
* gcc.dg/tree-ssa/builtin-snprintf-warn-2.c: New test.
* gcc.dg/tree-ssa/builtin-sprintf-warn-6.c: XFAIL test cases failing
due to bug 78969.
* gcc.dg/format/pr78569.c: Adjust.
From-SVN: r244210
Diffstat (limited to 'gcc/gimple-ssa-sprintf.c')
-rw-r--r-- | gcc/gimple-ssa-sprintf.c | 81 |
1 files changed, 50 insertions, 31 deletions
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c index 6a9f679..166b34b 100644 --- a/gcc/gimple-ssa-sprintf.c +++ b/gcc/gimple-ssa-sprintf.c @@ -718,6 +718,18 @@ struct pass_sprintf_length::call_info writing any. NOWRITE is cleared in response to the %n directive which has side-effects similar to writing output. */ bool nowrite; + + /* Return true if the called function's return value is used. */ + bool retval_used () const + { + return gimple_get_lhs (callstmt); + } + + /* Return the warning option corresponding to the called function. */ + int warnopt () const + { + return bounded ? OPT_Wformat_truncation_ : OPT_Wformat_length_; + } }; /* Return the result of formatting the '%%' directive. */ @@ -1950,8 +1962,7 @@ format_directive (const pass_sprintf_length::call_info &info, if (fmtres.nullp) { - fmtwarn (dirloc, pargrange, NULL, - OPT_Wformat_length_, + fmtwarn (dirloc, pargrange, NULL, info.warnopt (), "%<%.*s%> directive argument is null", (int)cvtlen, cvtbeg); @@ -1986,8 +1997,8 @@ format_directive (const pass_sprintf_length::call_info &info, "%wu bytes into a region of size %wu") : G_("%<%.*s%> directive writing %wu bytes " "into a region of size %wu")); - warned = fmtwarn (dirloc, pargrange, NULL, - OPT_Wformat_length_, fmtstr, + warned = fmtwarn (dirloc, pargrange, NULL, info.warnopt (), + fmtstr, (int)cvtlen, cvtbeg, fmtres.range.min, navail); } @@ -2001,7 +2012,7 @@ format_directive (const pass_sprintf_length::call_info &info, : G_("%<%.*s%> directive writing between %wu and " "%wu bytes into a region of size %wu")); warned = fmtwarn (dirloc, pargrange, NULL, - OPT_Wformat_length_, fmtstr, + info.warnopt (), fmtstr, (int)cvtlen, cvtbeg, fmtres.range.min, fmtres.range.max, navail); } @@ -2014,16 +2025,20 @@ format_directive (const pass_sprintf_length::call_info &info, : G_("%<%.*s%> directive writing %wu or more bytes " "into a region of size %wu")); warned = fmtwarn (dirloc, pargrange, NULL, - OPT_Wformat_length_, fmtstr, + info.warnopt (), fmtstr, (int)cvtlen, cvtbeg, fmtres.range.min, navail); } } else if (navail < fmtres.range.max - && (((spec.specifier == 's' - && fmtres.range.max < HOST_WIDE_INT_MAX) - /* && (spec.precision || spec.star_precision) */) - || 1 < warn_format_length)) + && (spec.specifier != 's' + || fmtres.range.max < HOST_WIDE_INT_MAX) + && ((info.bounded + && (!info.retval_used () + || warn_format_trunc > 1)) + || (!info.bounded + && (spec.specifier == 's' + || 1 < warn_format_length)))) { /* The maximum directive output is longer than there is room in the destination and the output length is either @@ -2038,7 +2053,7 @@ format_directive (const pass_sprintf_length::call_info &info, : G_("%<%.*s%> directive writing %wu or more bytes " "into a region of size %wu")); warned = fmtwarn (dirloc, pargrange, NULL, - OPT_Wformat_length_, fmtstr, + info.warnopt (), fmtstr, (int)cvtlen, cvtbeg, fmtres.range.min, navail); } @@ -2052,7 +2067,7 @@ format_directive (const pass_sprintf_length::call_info &info, : G_("%<%.*s%> directive writing between %wu and %wu " "bytes into a region of size %wu")); warned = fmtwarn (dirloc, pargrange, NULL, - OPT_Wformat_length_, fmtstr, + info.warnopt (), fmtstr, (int)cvtlen, cvtbeg, fmtres.range.min, fmtres.range.max, navail); @@ -2086,7 +2101,7 @@ format_directive (const pass_sprintf_length::call_info &info, "into a region of size %wu"))); warned = fmtwarn (dirloc, pargrange, NULL, - OPT_Wformat_length_, fmtstr, + info.warnopt (), fmtstr, (int)cvtlen, cvtbeg, fmtres.range.min, navail); } @@ -2111,7 +2126,7 @@ format_directive (const pass_sprintf_length::call_info &info, if (fmtres.range.min == fmtres.range.max) warned = fmtwarn (dirloc, pargrange, NULL, - OPT_Wformat_length_, + info.warnopt (), "%<%.*s%> directive output of %wu bytes exceeds " "minimum required size of 4095", (int)cvtlen, cvtbeg, fmtres.range.min); @@ -2125,7 +2140,7 @@ format_directive (const pass_sprintf_length::call_info &info, "bytes exceeds minimum required size of 4095")); warned = fmtwarn (dirloc, pargrange, NULL, - OPT_Wformat_length_, fmtstr, + info.warnopt (), fmtstr, (int)cvtlen, cvtbeg, fmtres.range.min, fmtres.range.max); } @@ -2143,8 +2158,7 @@ format_directive (const pass_sprintf_length::call_info &info, to exceed INT_MAX bytes. */ if (fmtres.range.min == fmtres.range.max) - warned = fmtwarn (dirloc, pargrange, NULL, - OPT_Wformat_length_, + warned = fmtwarn (dirloc, pargrange, NULL, info.warnopt (), "%<%.*s%> directive output of %wu bytes causes " "result to exceed %<INT_MAX%>", (int)cvtlen, cvtbeg, fmtres.range.min); @@ -2157,7 +2171,7 @@ format_directive (const pass_sprintf_length::call_info &info, : G_ ("%<%.*s%> directive output between %wu and %wu " "bytes may cause result to exceed %<INT_MAX%>")); warned = fmtwarn (dirloc, pargrange, NULL, - OPT_Wformat_length_, fmtstr, + info.warnopt (), fmtstr, (int)cvtlen, cvtbeg, fmtres.range.min, fmtres.range.max); } @@ -2265,7 +2279,11 @@ add_bytes (const pass_sprintf_length::call_info &info, : G_("writing a terminating nul past the end " "of the destination"))); - res->warned = fmtwarn (loc, NULL, NULL, OPT_Wformat_length_, text); + if (!info.bounded + || !boundrange + || !info.retval_used () + || warn_format_trunc > 1) + res->warned = fmtwarn (loc, NULL, NULL, info.warnopt (), text); } else { @@ -2283,8 +2301,12 @@ add_bytes (const pass_sprintf_length::call_info &info, : G_("writing format character %#qc at offset %wu past " "the end of the destination"))); - res->warned = fmtwarn (loc, NULL, NULL, OPT_Wformat_length_, - text, info.fmtstr[off], off); + if (!info.bounded + || !boundrange + || !info.retval_used () + || warn_format_trunc > 1) + res->warned = fmtwarn (loc, NULL, NULL, info.warnopt (), + text, info.fmtstr[off], off); } } @@ -2351,8 +2373,7 @@ add_bytes (const pass_sprintf_length::call_info &info, off + len - !!len); if (res->number_chars_min == res->number_chars_max) - res->warned = fmtwarn (loc, NULL, NULL, - OPT_Wformat_length_, + res->warned = fmtwarn (loc, NULL, NULL, info.warnopt (), "output of %wu bytes causes " "result to exceed %<INT_MAX%>", res->number_chars_min - !end); @@ -2364,8 +2385,7 @@ add_bytes (const pass_sprintf_length::call_info &info, "result to exceed %<INT_MAX%>") : G_ ("output between %wu and %wu bytes may cause " "result to exceed %<INT_MAX%>")); - res->warned = fmtwarn (loc, NULL, NULL, OPT_Wformat_length_, - text, + res->warned = fmtwarn (loc, NULL, NULL, info.warnopt (), text, res->number_chars_min - !end, res->number_chars_max - !end); } @@ -2970,14 +2990,13 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi) checking built-ins. */ if ((idx_objsize == HOST_WIDE_INT_M1U || !warn_stringop_overflow)) - warning_at (gimple_location (info.callstmt), - OPT_Wformat_length_, + warning_at (gimple_location (info.callstmt), info.warnopt (), "specified bound %wu exceeds maximum object size " "%wu", dstsize, target_size_max () / 2); } else if (dstsize > target_int_max ()) - warning_at (gimple_location (info.callstmt), OPT_Wformat_length_, + warning_at (gimple_location (info.callstmt), info.warnopt (), "specified bound %wu exceeds %<INT_MAX %>", dstsize); } @@ -3028,7 +3047,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi) is not constant. */ location_t loc = gimple_location (info.callstmt); warning_at (EXPR_LOC_OR_LOC (dstptr, loc), - OPT_Wformat_length_, "null destination pointer"); + info.warnopt (), "null destination pointer"); return; } @@ -3044,7 +3063,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi) && (idx_objsize == HOST_WIDE_INT_M1U || !warn_stringop_overflow)) { - warning_at (gimple_location (info.callstmt), OPT_Wformat_length_, + warning_at (gimple_location (info.callstmt), info.warnopt (), "specified bound %wu exceeds the size %wu " "of the destination object", dstsize, objsize); } @@ -3057,7 +3076,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi) is not constant. */ location_t loc = gimple_location (info.callstmt); warning_at (EXPR_LOC_OR_LOC (info.format, loc), - OPT_Wformat_length_, "null format string"); + info.warnopt (), "null format string"); return; } |