summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-strlen.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-strlen.c')
-rw-r--r--gcc/tree-ssa-strlen.c75
1 files changed, 47 insertions, 28 deletions
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 94ed2bedc03..71ed0ff1b45 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see
#include "domwalk.h"
#include "tree-ssa-alias.h"
#include "tree-ssa-propagate.h"
+#include "tree-ssa-strlen.h"
#include "params.h"
#include "ipa-chkp.h"
#include "tree-hash-traits.h"
@@ -1780,11 +1781,12 @@ is_strlen_related_p (tree src, tree len)
return false;
}
-/* A helper of handle_builtin_stxncpy. Check to see if the specified
- bound is a) equal to the size of the destination DST and if so, b)
- if it's immediately followed by DST[CNT - 1] = '\0'. If a) holds
- and b) does not, warn. Otherwise, do nothing. Return true if
- diagnostic has been issued.
+/* Called by handle_builtin_stxncpy and by gimple_fold_builtin_strncpy
+ in gimple-fold.c.
+ Check to see if the specified bound is a) equal to the size of
+ the destination DST and if so, b) if it's immediately followed by
+ DST[CNT - 1] = '\0'. If a) holds and b) does not, warn. Otherwise,
+ do nothing. Return true if diagnostic has been issued.
The purpose is to diagnose calls to strncpy and stpncpy that do
not nul-terminate the copy while allowing for the idiom where
@@ -1795,7 +1797,7 @@ is_strlen_related_p (tree src, tree len)
a[sizeof a - 1] = '\0';
*/
-static bool
+bool
maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
{
gimple *stmt = gsi_stmt (gsi);
@@ -1831,8 +1833,11 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
return false;
/* Negative value is the constant string length. If it's less than
- the lower bound there is no truncation. */
- int sidx = get_stridx (src);
+ the lower bound there is no truncation. Avoid calling get_stridx()
+ when ssa_ver_to_stridx is empty. That implies the caller isn't
+ running under the control of this pass and ssa_ver_to_stridx hasn't
+ been created yet. */
+ int sidx = ssa_ver_to_stridx.length () ? get_stridx (src) : 0;
if (sidx < 0 && wi::gtu_p (cntrange[0], ~sidx))
return false;
@@ -1878,6 +1883,7 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
poly_int64 lhsoff;
tree lhsbase = get_addr_base_and_unit_offset (lhs, &lhsoff);
if (lhsbase
+ && dstbase
&& known_eq (dstoff, lhsoff)
&& operand_equal_p (dstbase, lhsbase, 0))
return false;
@@ -1934,23 +1940,35 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
lenrange[0] = wi::shwi (0, prec);
}
- if (wi::geu_p (lenrange[0], cntrange[1]))
+ gcall *call = as_a <gcall *> (stmt);
+
+ if (lenrange[0] == cntrange[1] && cntrange[0] == cntrange[1])
+ return warning_at (callloc, OPT_Wstringop_truncation,
+ (integer_onep (cnt)
+ ? G_("%G%qD output truncated before terminating "
+ "nul copying %E byte from a string of the "
+ "same length")
+ : G_("%G%qD output truncated before terminating nul "
+ "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_at (callloc, OPT_Wstringop_truncation,
integer_onep (cnt)
- ? G_("%qD output truncated copying %E byte "
+ ? G_("%G%qD output truncated copying %E byte "
"from a string of length %wu")
- : G_("%qD output truncated copying %E bytes "
+ : G_("%G%qD output truncated copying %E bytes "
"from a string of length %wu"),
- func, cnt, lenrange[0].to_uhwi ());
+ call, func, cnt, lenrange[0].to_uhwi ());
return warning_at (callloc, OPT_Wstringop_truncation,
- "%qD output truncated copying between %wu "
+ "%G%qD output truncated copying between %wu "
"and %wu bytes from a string of length %wu",
- func, cntrange[0].to_uhwi (),
+ call, func, cntrange[0].to_uhwi (),
cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
}
else if (wi::geu_p (lenrange[1], cntrange[1]))
@@ -1960,16 +1978,16 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
if (cntrange[0] == cntrange[1])
return warning_at (callloc, OPT_Wstringop_truncation,
integer_onep (cnt)
- ? G_("%qD output may be truncated copying %E "
+ ? G_("%G%qD output may be truncated copying %E "
"byte from a string of length %wu")
- : G_("%qD output may be truncated copying %E "
+ : G_("%G%qD output may be truncated copying %E "
"bytes from a string of length %wu"),
- func, cnt, lenrange[1].to_uhwi ());
+ call, func, cnt, lenrange[1].to_uhwi ());
return warning_at (callloc, OPT_Wstringop_truncation,
- "%qD output may be truncated copying between %wu "
+ "%G%qD output may be truncated copying between %wu "
"and %wu bytes from a string of length %wu",
- func, cntrange[0].to_uhwi (),
+ call, func, cntrange[0].to_uhwi (),
cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
}
@@ -1981,9 +1999,9 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
the lower bound of the specified count but shorter than the
upper bound the copy may (but need not) be truncated. */
return warning_at (callloc, OPT_Wstringop_truncation,
- "%qD output may be truncated copying between %wu "
- "and %wu bytes from a string of length %wu",
- func, cntrange[0].to_uhwi (),
+ "%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[0].to_uhwi ());
}
}
@@ -2002,8 +2020,8 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
if (cntrange[0] == cntrange[1])
return warning_at (callloc, OPT_Wstringop_truncation,
- "%qD specified bound %E equals destination size",
- func, cnt);
+ "%G%qD specified bound %E equals destination size",
+ as_a <gcall *> (stmt), func, cnt);
}
return false;
@@ -2102,14 +2120,15 @@ handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi)
if (sisrc == silen
&& is_strlen_related_p (src, len)
&& warning_at (callloc, OPT_Wstringop_truncation,
- "%qD output truncated before terminating nul "
+ "%G%qD output truncated before terminating nul "
"copying as many bytes from a string as its length",
- func))
+ as_a <gcall *>(stmt), func))
warned = true;
else if (silen && is_strlen_related_p (src, silen->ptr))
warned = warning_at (callloc, OPT_Wstringop_overflow_,
- "%qD specified bound depends on the length "
- "of the source argument", func);
+ "%G%qD specified bound depends on the length "
+ "of the source argument",
+ as_a <gcall *>(stmt), func);
if (warned)
{
location_t strlenloc = pss->second;