aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2018-08-29 17:17:08 +0000
committerJeff Law <law@gcc.gnu.org>2018-08-29 11:17:08 -0600
commite84bf0ef66aa72228299dd92d342c4de3a37c55c (patch)
treefa06d2fdd65f07a2e2f5dc933d8166e57ae93a5e /gcc/expr.c
parentb9a0baa9f941537de5ea2c431830a8da33692d88 (diff)
downloadgcc-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.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 2645c25..cd5cf12 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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;