aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-strlen.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2017-12-18 22:49:57 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2017-12-18 15:49:57 -0700
commit06199618c1c047366fdafd2b0fafdace1fb44abc (patch)
treea0d1d0ffb97b3a497c587d6dd9e1ecfd092a08ec /gcc/tree-ssa-strlen.c
parentadaefe2a50b56505b9745955da5231cd87ce9d8a (diff)
downloadgcc-06199618c1c047366fdafd2b0fafdace1fb44abc.zip
gcc-06199618c1c047366fdafd2b0fafdace1fb44abc.tar.gz
gcc-06199618c1c047366fdafd2b0fafdace1fb44abc.tar.bz2
PR middle-end/83373 - False positive reported by -Wstringop-overflow
PR middle-end/83373 - False positive reported by -Wstringop-overflow PR tree-optimization/78450 - strlen(s) return value can be assumed to be less than the size of s gcc/ChangeLog: PR middle-end/83373 PR tree-optimization/78450 * tree-ssa-strlen.c (maybe_set_strlen_range): New function. (handle_builtin_strlen): Call it. gcc/testsuite/ChangeLog: PR middle-end/83373 PR tree-optimization/78450 * gcc.dg/pr83373.c: New test. * gcc.dg/strlenopt-36.c: New test. * gcc.dg/strlenopt-37.c: New test. From-SVN: r255790
Diffstat (limited to 'gcc/tree-ssa-strlen.c')
-rw-r--r--gcc/tree-ssa-strlen.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index e75d133..0386883 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -1152,6 +1152,44 @@ adjust_last_stmt (strinfo *si, gimple *stmt, bool is_strcat)
update_stmt (last.stmt);
}
+/* For an LHS that is an SSA_NAME and for strlen() argument SRC, set
+ LHS range info to [0, N] if SRC refers to a character array A[N]
+ with unknown length bounded by N. */
+
+static void
+maybe_set_strlen_range (tree lhs, tree src)
+{
+ if (TREE_CODE (lhs) != SSA_NAME)
+ return;
+
+ if (TREE_CODE (src) == SSA_NAME)
+ {
+ gimple *def = SSA_NAME_DEF_STMT (src);
+ if (is_gimple_assign (def)
+ && gimple_assign_rhs_code (def) == ADDR_EXPR)
+ src = gimple_assign_rhs1 (def);
+ }
+
+ if (TREE_CODE (src) != ADDR_EXPR)
+ return;
+
+ /* The last array member of a struct can be bigger than its size
+ suggests if it's treated as a poor-man's flexible array member. */
+ src = TREE_OPERAND (src, 0);
+ if (TREE_CODE (TREE_TYPE (src)) != ARRAY_TYPE
+ || array_at_struct_end_p (src))
+ return;
+
+ tree type = TREE_TYPE (src);
+ if (tree dom = TYPE_DOMAIN (type))
+ if (tree maxval = TYPE_MAX_VALUE (dom))
+ {
+ wide_int max = wi::to_wide (maxval);
+ wide_int min = wi::zero (max.get_precision ());
+ set_range_info (lhs, VR_RANGE, min, max);
+ }
+}
+
/* Handle a strlen call. If strlen of the argument is known, replace
the strlen call with the known value, otherwise remember that strlen
of the argument is stored in the lhs SSA_NAME. */
@@ -1262,6 +1300,10 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
set_strinfo (idx, si);
find_equal_ptrs (src, idx);
+ /* For SRC that is an array of N elements, set LHS's range
+ to [0, N]. */
+ maybe_set_strlen_range (lhs, src);
+
if (strlen_to_stridx)
{
location_t loc = gimple_location (stmt);