aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-strlen.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2018-06-25 20:33:28 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2018-06-25 14:33:28 -0600
commiteec5f615cbad2de5ff10fbaa8c92f68cc5c6be00 (patch)
tree6d97fc1ae9f1316ba96cf9579500332267bb075a /gcc/tree-ssa-strlen.c
parent2bcd87a7b5bf793a00e99a5d7fdef4277afa7dc6 (diff)
downloadgcc-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.c84
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))
{