Hi!

get_range_strlen fails to tell the caller that array_at_struct_end_p has
been involved in cases like (&ptr->arr[0]), while it handles
(ptr->arr).  Fixed thusly, bootstrapped/regtested on x86_64-linux and
i686-linux, ok for trunk?
2018-02-12  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/84339
        * gimple-fold.c (get_range_strlen): Set *FLEXP to true when handling
        ARRAY_REF where first operand is array_at_struct_end_p COMPONENT_REF.
        Formatting fixes.

        * gcc.c-torture/execute/pr84339.c: New test.

--- gcc/gimple-fold.c.jj        2018-01-11 19:01:07.259442879 +0100
+++ gcc/gimple-fold.c   2018-02-12 15:44:41.350214335 +0100
@@ -1380,9 +1380,15 @@ get_range_strlen (tree arg, tree length[
              /* Set the minimum size to zero since the string in
                 the array could have zero length.  */
              *minlen = ssize_int (0);
+
+             if (TREE_CODE (TREE_OPERAND (arg, 0)) == COMPONENT_REF
+                 && type == TREE_TYPE (TREE_OPERAND (arg, 0))
+                 && array_at_struct_end_p (TREE_OPERAND (arg, 0)))
+               *flexp = true;
            }
          else if (TREE_CODE (arg) == COMPONENT_REF
-             && TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 1))) == ARRAY_TYPE)
+                  && (TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 1)))
+                      == ARRAY_TYPE))
            {
              /* Use the type of the member array to determine the upper
                 bound on the length of the array.  This may be overly
@@ -1428,7 +1434,7 @@ get_range_strlen (tree arg, tree length[
                      || integer_zerop (val))
                    return false;
                  val = wide_int_to_tree (TREE_TYPE (val),
-                                         wi::sub(wi::to_wide (val), 1));
+                                         wi::sub (wi::to_wide (val), 1));
                  /* Set the minimum size to zero since the string in
                     the array could have zero length.  */
                  *minlen = ssize_int (0);
--- gcc/testsuite/gcc.c-torture/execute/pr84339.c.jj    2018-02-12 
15:47:04.167243039 +0100
+++ gcc/testsuite/gcc.c-torture/execute/pr84339.c       2018-02-12 
15:46:48.363239868 +0100
@@ -0,0 +1,30 @@
+/* PR tree-optimization/84339 */
+
+struct S { int a; char b[1]; };
+
+__attribute__((noipa)) int
+foo (struct S *p)
+{
+  return __builtin_strlen (&p->b[0]);
+}
+
+__attribute__((noipa)) int
+bar (struct S *p)
+{
+  return __builtin_strlen (p->b);
+}
+
+int
+main ()
+{
+  struct S *p = __builtin_malloc (sizeof (struct S) + 16);
+  if (p)
+    {
+      p->a = 1;
+      __builtin_strcpy (p->b, "abcdefg");
+      if (foo (p) != 7 || bar (p) != 7)
+       __builtin_abort ();
+      __builtin_free (p);
+    }
+  return 0;
+}

        Jakub

Reply via email to