aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-43.c15
-rw-r--r--gcc/tree-ssa-strlen.c28
4 files changed, 43 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a65cac1..d37cc78 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2018-01-26 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/83896
+ * tree-ssa-strlen.c (get_string_len): Rename...
+ (get_string_cst_length): ...to this. Return HOST_WIDE_INT.
+ Avoid assuming length is constant.
+ (handle_char_store): Use HOST_WIDE_INT for string length.
+
2018-01-26 Uros Bizjak <ubizjak@gmail.com>
PR target/81763
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index adf8c01..63bae36 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2018-01-26 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/83896
+ * gcc.dg/strlenopt-43.c: New.
+
2018-01-26 Will Schmidt <will_schmidt@vnet.ibm.com>
* gcc.target/powerpc/fold-vec-abs-int.c: Remove scan-assembler stanzas.
diff --git a/gcc/testsuite/gcc.dg/strlenopt-43.c b/gcc/testsuite/gcc.dg/strlenopt-43.c
new file mode 100644
index 0000000..13539fc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-43.c
@@ -0,0 +1,15 @@
+/* PR tree-optimization/83896 - ice in get_string_len on a call to strlen
+ with non-constant length
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+#include "strlenopt.h"
+
+extern char a[5];
+extern char b[];
+
+void f (void)
+{
+ if (strlen (b) != 4)
+ memcpy (a, b, sizeof a);
+}
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 4e36327..c3cf432 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -2772,16 +2772,20 @@ handle_pointer_plus (gimple_stmt_iterator *gsi)
}
}
-/* Check if RHS is string_cst possibly wrapped by mem_ref. */
-static int
-get_string_len (tree rhs)
+/* If RHS, either directly or indirectly, refers to a string of constant
+ length, return it. Otherwise return a negative value. */
+
+static HOST_WIDE_INT
+get_string_cst_length (tree rhs)
{
if (TREE_CODE (rhs) == MEM_REF
&& integer_zerop (TREE_OPERAND (rhs, 1)))
{
- tree rhs_addr = rhs = TREE_OPERAND (rhs, 0);
+ rhs = TREE_OPERAND (rhs, 0);
if (TREE_CODE (rhs) == ADDR_EXPR)
{
+ tree rhs_addr = rhs;
+
rhs = TREE_OPERAND (rhs, 0);
if (TREE_CODE (rhs) != STRING_CST)
{
@@ -2789,7 +2793,9 @@ get_string_len (tree rhs)
if (idx > 0)
{
strinfo *si = get_strinfo (idx);
- if (si && si->full_string_p)
+ if (si
+ && si->full_string_p
+ && tree_fits_shwi_p (si->nonzero_chars))
return tree_to_shwi (si->nonzero_chars);
}
}
@@ -2801,10 +2807,7 @@ get_string_len (tree rhs)
rhs = DECL_INITIAL (rhs);
if (rhs && TREE_CODE (rhs) == STRING_CST)
- {
- unsigned HOST_WIDE_INT ilen = strlen (TREE_STRING_POINTER (rhs));
- return ilen <= INT_MAX ? ilen : -1;
- }
+ return strlen (TREE_STRING_POINTER (rhs));
return -1;
}
@@ -2821,9 +2824,6 @@ handle_char_store (gimple_stmt_iterator *gsi)
tree rhs = gimple_assign_rhs1 (stmt);
unsigned HOST_WIDE_INT offset = 0;
- /* Set to the length of the string being assigned if known. */
- int rhslen;
-
if (TREE_CODE (lhs) == MEM_REF
&& TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME)
{
@@ -2854,6 +2854,8 @@ handle_char_store (gimple_stmt_iterator *gsi)
bool storing_nonzero_p = (!storing_zero_p
&& TREE_CODE (rhs) == INTEGER_CST
&& integer_nonzerop (rhs));
+ /* Set to the length of the string being assigned if known. */
+ HOST_WIDE_INT rhslen;
if (si != NULL)
{
@@ -2967,7 +2969,7 @@ handle_char_store (gimple_stmt_iterator *gsi)
}
}
else if (idx == 0
- && (rhslen = get_string_len (gimple_assign_rhs1 (stmt))) >= 0
+ && (rhslen = get_string_cst_length (gimple_assign_rhs1 (stmt))) >= 0
&& ssaname == NULL_TREE
&& TREE_CODE (TREE_TYPE (lhs)) == ARRAY_TYPE)
{