diff options
author | Martin Sebor <msebor@redhat.com> | 2018-08-29 17:17:08 +0000 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2018-08-29 11:17:08 -0600 |
commit | e84bf0ef66aa72228299dd92d342c4de3a37c55c (patch) | |
tree | fa06d2fdd65f07a2e2f5dc933d8166e57ae93a5e /gcc/expr.c | |
parent | b9a0baa9f941537de5ea2c431830a8da33692d88 (diff) | |
download | gcc-e84bf0ef66aa72228299dd92d342c4de3a37c55c.zip gcc-e84bf0ef66aa72228299dd92d342c4de3a37c55c.tar.gz gcc-e84bf0ef66aa72228299dd92d342c4de3a37c55c.tar.bz2 |
re PR middle-end/86714 (tree-ssa-forwprop.c confused by too long initializer)
PR tree-optimization/86714
PR tree-optimization/86711
* builtins.c (c_strlen): Add arguments to call to string_constant.
* expr.c (string_constant): Add argument. Detect missing nul
terminator and outermost declaration it's missing in.
* expr.h (string_constant): Add argument.
* fold-const.c (read_from_constant_string): Add arguments to call to
string_constant.
(c_getstr): Likewise.
* tree-ssa-forwprop.c (simplify_builtin_call): Likewise.
to string_constant.
* tree-ssa-strlen.c (get_stridx): Likewise.
PR tree-optimization/86714
PR tree-optimization/86711
* gcc.c-torture/execute/memchr-1.c: New test.
* gcc.c-torture/execute/pr86714.c: New test.
* gcc.c-torture/execute/widechar-3.c: New test.
* gcc.dg/strlenopt-58.c: New test.
Co-Authored-By: Bernd Edlinger <bernd.edlinger@hotmail.de>
Co-Authored-By: Jeff Law <law@redhat.com>
From-SVN: r263963
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 31 |
1 files changed, 25 insertions, 6 deletions
@@ -11303,12 +11303,15 @@ is_aligning_offset (const_tree offset, const_tree exp) /* Return the tree node if an ARG corresponds to a string constant or zero if it doesn't. If we return nonzero, set *PTR_OFFSET to the (possibly non-constant) offset in bytes within the string that ARG is accessing. + If NONSTR is non-null, consider valid even sequences of characters that + aren't nul-terminated strings. In that case, if ARG refers to such + a sequence set *NONSTR to its declaration and clear it otherwise. The type of the offset is sizetype. If MEM_SIZE is non-zero the storage size of the memory is returned. If MEM_SIZE is zero, the string is only returned when it is properly zero terminated. */ tree -string_constant (tree arg, tree *ptr_offset, tree *mem_size) +string_constant (tree arg, tree *ptr_offset, tree *mem_size, tree *nonstr) { tree array; STRIP_NOPS (arg); @@ -11362,7 +11365,7 @@ string_constant (tree arg, tree *ptr_offset, tree *mem_size) return NULL_TREE; tree offset; - if (tree str = string_constant (arg0, &offset, mem_size)) + if (tree str = string_constant (arg0, &offset, mem_size, nonstr)) { /* Avoid pointers to arrays (see bug 86622). */ if (POINTER_TYPE_P (TREE_TYPE (arg)) @@ -11404,6 +11407,9 @@ string_constant (tree arg, tree *ptr_offset, tree *mem_size) *ptr_offset = fold_convert (sizetype, offset); if (mem_size) *mem_size = TYPE_SIZE_UNIT (TREE_TYPE (array)); + /* This is not strictly correct. FIXME in follow-up patch. */ + if (nonstr) + *nonstr = NULL_TREE; return array; } @@ -11450,22 +11456,35 @@ string_constant (tree arg, tree *ptr_offset, tree *mem_size) if (!array_size || TREE_CODE (array_size) != INTEGER_CST) return NULL_TREE; - /* Avoid returning a string that doesn't fit in the array - it is stored in, like + /* Avoid returning an array that is unterminated because it lacks + a terminating nul, like const char a[4] = "abcde"; - but do handle those that fit even if they have excess + but do handle those that are strings even if they have excess initializers, such as in const char a[4] = "abc\000\000"; The excess elements contribute to TREE_STRING_LENGTH() but not to strlen(). */ unsigned HOST_WIDE_INT charsize = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (init)))); + /* Compute the lower bound number of elements (not bytes) in the array + that the string is used to initialize. The actual size of the array + may be greater if the string is shorter, but the the important + data point is whether the literal, inlcuding the terminating nul, + fits the array. */ + unsigned HOST_WIDE_INT array_elts + = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (init))) / charsize; + + /* Compute the string length in (wide) characters. */ unsigned HOST_WIDE_INT length = TREE_STRING_LENGTH (init); length = string_length (TREE_STRING_POINTER (init), charsize, length / charsize); if (mem_size) *mem_size = TYPE_SIZE_UNIT (TREE_TYPE (init)); - else if (compare_tree_int (array_size, length + 1) < 0) + if (nonstr) + *nonstr = array_elts > length ? NULL_TREE : array; + + if ((!mem_size && !nonstr) + && array_elts <= length) return NULL_TREE; *ptr_offset = offset; |