diff options
author | Martin Sebor <msebor@redhat.com> | 2018-06-25 20:33:28 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2018-06-25 14:33:28 -0600 |
commit | eec5f615cbad2de5ff10fbaa8c92f68cc5c6be00 (patch) | |
tree | 6d97fc1ae9f1316ba96cf9579500332267bb075a /gcc/tree-ssa-strlen.c | |
parent | 2bcd87a7b5bf793a00e99a5d7fdef4277afa7dc6 (diff) | |
download | gcc-eec5f615cbad2de5ff10fbaa8c92f68cc5c6be00.zip gcc-eec5f615cbad2de5ff10fbaa8c92f68cc5c6be00.tar.gz gcc-eec5f615cbad2de5ff10fbaa8c92f68cc5c6be00.tar.bz2 |
PR tree-optimization/85700 - Spurious -Wstringop-truncation warning with strncat
gcc/ChangeLog:
PR tree-optimization/85700
* gimple-fold.c (gimple_fold_builtin_strncat): Adjust comment.
* tree-ssa-strlen.c (is_strlen_related_p): Handle integer subtraction.
(maybe_diag_stxncpy_trunc): Distinguish strncat from strncpy.
gcc/testsuite/ChangeLog:
PR tree-optimization/85700
* gcc.dg/Wstringop-truncation-4.c: New test.
From-SVN: r262110
Diffstat (limited to 'gcc/tree-ssa-strlen.c')
-rw-r--r-- | gcc/tree-ssa-strlen.c | 84 |
1 files changed, 47 insertions, 37 deletions
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index 92545b9..2da82a8 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -2014,6 +2014,12 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt) gcall *call = as_a <gcall *> (stmt); + /* Set to true for strncat whose bound is derived from the length + of the destination (the expected usage pattern). */ + bool cat_dstlen_bounded = false; + if (DECL_FUNCTION_CODE (func) == BUILT_IN_STRNCAT) + cat_dstlen_bounded = is_strlen_related_p (dst, cnt); + if (lenrange[0] == cntrange[1] && cntrange[0] == cntrange[1]) return warning_n (callloc, OPT_Wstringop_truncation, cntrange[0].to_uhwi (), @@ -2024,46 +2030,50 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt) "copying %E bytes from a string of the same " "length", call, func, cnt); - else if (wi::geu_p (lenrange[0], cntrange[1])) - { - /* The shortest string is longer than the upper bound of - the count so the truncation is certain. */ - if (cntrange[0] == cntrange[1]) - return warning_n (callloc, OPT_Wstringop_truncation, - cntrange[0].to_uhwi (), - "%G%qD output truncated copying %E byte " - "from a string of length %wu", - "%G%qD output truncated copying %E bytes " - "from a string of length %wu", - call, func, cnt, lenrange[0].to_uhwi ()); - - return warning_at (callloc, OPT_Wstringop_truncation, - "%G%qD output truncated copying between %wu " - "and %wu bytes from a string of length %wu", - call, func, cntrange[0].to_uhwi (), - cntrange[1].to_uhwi (), lenrange[0].to_uhwi ()); - } - else if (wi::geu_p (lenrange[1], cntrange[1])) + else if (!cat_dstlen_bounded) { - /* The longest string is longer than the upper bound of - the count so the truncation is possible. */ - if (cntrange[0] == cntrange[1]) - return warning_n (callloc, OPT_Wstringop_truncation, - cntrange[0].to_uhwi (), - "%G%qD output may be truncated copying %E " - "byte from a string of length %wu", - "%G%qD output may be truncated copying %E " - "bytes from a string of length %wu", - call, func, cnt, lenrange[1].to_uhwi ()); - - return warning_at (callloc, OPT_Wstringop_truncation, - "%G%qD output may be truncated copying between %wu " - "and %wu bytes from a string of length %wu", - call, func, cntrange[0].to_uhwi (), - cntrange[1].to_uhwi (), lenrange[1].to_uhwi ()); + if (wi::geu_p (lenrange[0], cntrange[1])) + { + /* The shortest string is longer than the upper bound of + the count so the truncation is certain. */ + if (cntrange[0] == cntrange[1]) + return warning_n (callloc, OPT_Wstringop_truncation, + cntrange[0].to_uhwi (), + "%G%qD output truncated copying %E byte " + "from a string of length %wu", + "%G%qD output truncated copying %E bytes " + "from a string of length %wu", + call, func, cnt, lenrange[0].to_uhwi ()); + + return warning_at (callloc, OPT_Wstringop_truncation, + "%G%qD output truncated copying between %wu " + "and %wu bytes from a string of length %wu", + call, func, cntrange[0].to_uhwi (), + cntrange[1].to_uhwi (), lenrange[0].to_uhwi ()); + } + else if (wi::geu_p (lenrange[1], cntrange[1])) + { + /* The longest string is longer than the upper bound of + the count so the truncation is possible. */ + if (cntrange[0] == cntrange[1]) + return warning_n (callloc, OPT_Wstringop_truncation, + cntrange[0].to_uhwi (), + "%G%qD output may be truncated copying %E " + "byte from a string of length %wu", + "%G%qD output may be truncated copying %E " + "bytes from a string of length %wu", + call, func, cnt, lenrange[1].to_uhwi ()); + + return warning_at (callloc, OPT_Wstringop_truncation, + "%G%qD output may be truncated copying between " + "%wu and %wu bytes from a string of length %wu", + call, func, cntrange[0].to_uhwi (), + cntrange[1].to_uhwi (), lenrange[1].to_uhwi ()); + } } - if (cntrange[0] != cntrange[1] + if (!cat_dstlen_bounded + && cntrange[0] != cntrange[1] && wi::leu_p (cntrange[0], lenrange[0]) && wi::leu_p (cntrange[1], lenrange[0] + 1)) { |