diff options
author | Martin Sebor <msebor@redhat.com> | 2017-12-18 22:49:57 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2017-12-18 15:49:57 -0700 |
commit | 06199618c1c047366fdafd2b0fafdace1fb44abc (patch) | |
tree | a0d1d0ffb97b3a497c587d6dd9e1ecfd092a08ec /gcc/tree-ssa-strlen.c | |
parent | adaefe2a50b56505b9745955da5231cd87ce9d8a (diff) | |
download | gcc-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.c | 42 |
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); |