Hi!

The various routines propagate to the caller whether
      if (check_and_optimize_stmt (&gsi, &cleanup_eh, evrp.get_vr_values ()))
        gsi_next (&gsi);
should do gsi_next or not (return false if e.g. gsi_remove is done, thus
gsi is already moved to the next stmt).
handle_printf_call returns that too, though with the values swapped,
but since the move of handle_printf_call (then called handle_gimple_call)
from the separate sprintf pass to strlen pass, the return value is ignored,
while it must not be.  In some cases it means the following statement is not
processed by the strlen pass, which can e.g. mean wrong-code because some
strlen information is not invalidated when it should, or in other cases like
in this testcase where the sprintf call that was removed was at the end of a bb
it means an ICE, because gsi_next when gsi is already at the end of bb is
invalid.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

2019-11-27  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/92691
        * tree-ssa-strlen.c (handle_store): Clarify return value meaning
        in function comment.
        (strlen_check_and_optimize_call): Likewise.  For handle_printf_call
        calls, return !handle_printf_call rather than always returning true.
        (check_and_optimize_stmt): Describe return value meaning in function
        comment.  Formatting fix.

        * gcc.dg/tree-ssa/builtin-snprintf-10.c: New test.

--- gcc/tree-ssa-strlen.c.jj    2019-11-22 19:11:54.901951408 +0100
+++ gcc/tree-ssa-strlen.c       2019-11-27 12:25:14.778564388 +0100
@@ -4300,7 +4300,8 @@ count_nonzero_bytes (tree exp, unsigned
 /* Handle a single or multibyte store other than by a built-in function,
    either via a single character assignment or by multi-byte assignment
    either via MEM_REF or via a type other than char (such as in
-   '*(int*)a = 12345').  Return true when handled.  */
+   '*(int*)a = 12345').  Return true to let the caller advance *GSI to
+   the next statement in the basic block and false otherwise.  */
 
 static bool
 handle_store (gimple_stmt_iterator *gsi, bool *zero_write, const vr_values 
*rvals)
@@ -4728,8 +4729,8 @@ is_char_type (tree type)
 }
 
 /* Check the built-in call at GSI for validity and optimize it.
-   Return true to let the caller advance *GSI to the statement
-   in the CFG and false otherwise.  */
+   Return true to let the caller advance *GSI to the next statement
+   in the basic block and false otherwise.  */
 
 static bool
 strlen_check_and_optimize_call (gimple_stmt_iterator *gsi,
@@ -4738,16 +4739,13 @@ strlen_check_and_optimize_call (gimple_s
 {
   gimple *stmt = gsi_stmt (*gsi);
 
+  /* When not optimizing we must be checking printf calls which
+     we do even for user-defined functions when they are declared
+     with attribute format.  */
   if (!flag_optimize_strlen
       || !strlen_optimize
       || !valid_builtin_call (stmt))
-    {
-      /* When not optimizing we must be checking printf calls which
-        we do even for user-defined functions when they are declared
-        with attribute format.  */
-      handle_printf_call (gsi, rvals);
-      return true;
-    }
+    return !handle_printf_call (gsi, rvals);
 
   tree callee = gimple_call_fndecl (stmt);
   switch (DECL_FUNCTION_CODE (callee))
@@ -4806,7 +4804,8 @@ strlen_check_and_optimize_call (gimple_s
        return false;
       break;
     default:
-      handle_printf_call (gsi, rvals);
+      if (handle_printf_call (gsi, rvals))
+       return false;
       break;
     }
 
@@ -4932,7 +4931,8 @@ handle_integral_assign (gimple_stmt_iter
 /* Attempt to check for validity of the performed access a single statement
    at *GSI using string length knowledge, and to optimize it.
    If the given basic block needs clean-up of EH, CLEANUP_EH is set to
-   true.  */
+   true.  Return true to let the caller advance *GSI to the next statement
+   in the basic block and false otherwise.  */
 
 static bool
 check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh,
@@ -4973,32 +4973,32 @@ check_and_optimize_stmt (gimple_stmt_ite
        /* Handle assignment to a character.  */
        handle_integral_assign (gsi, cleanup_eh);
       else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
-      {
-       tree type = TREE_TYPE (lhs);
-       if (TREE_CODE (type) == ARRAY_TYPE)
-         type = TREE_TYPE (type);
-
-       bool is_char_store = is_char_type (type);
-       if (!is_char_store && TREE_CODE (lhs) == MEM_REF)
-         {
-           /* To consider stores into char objects via integer types
-              other than char but not those to non-character objects,
-              determine the type of the destination rather than just
-              the type of the access.  */
-           tree ref = TREE_OPERAND (lhs, 0);
-           type = TREE_TYPE (ref);
-           if (TREE_CODE (type) == POINTER_TYPE)
-             type = TREE_TYPE (type);
-           if (TREE_CODE (type) == ARRAY_TYPE)
-             type = TREE_TYPE (type);
-           if (is_char_type (type))
-             is_char_store = true;
-         }
-
-       /* Handle a single or multibyte assignment.  */
-       if (is_char_store && !handle_store (gsi, &zero_write, rvals))
-         return false;
-      }
+       {
+         tree type = TREE_TYPE (lhs);
+         if (TREE_CODE (type) == ARRAY_TYPE)
+           type = TREE_TYPE (type);
+
+         bool is_char_store = is_char_type (type);
+         if (!is_char_store && TREE_CODE (lhs) == MEM_REF)
+           {
+             /* To consider stores into char objects via integer types
+                other than char but not those to non-character objects,
+                determine the type of the destination rather than just
+                the type of the access.  */
+             tree ref = TREE_OPERAND (lhs, 0);
+             type = TREE_TYPE (ref);
+             if (TREE_CODE (type) == POINTER_TYPE)
+               type = TREE_TYPE (type);
+             if (TREE_CODE (type) == ARRAY_TYPE)
+               type = TREE_TYPE (type);
+             if (is_char_type (type))
+               is_char_store = true;
+           }
+
+         /* Handle a single or multibyte assignment.  */
+         if (is_char_store && !handle_store (gsi, &zero_write, rvals))
+           return false;
+       }
     }
   else if (gcond *cond = dyn_cast<gcond *> (stmt))
     {
--- gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-10.c.jj      2019-11-27 
12:23:19.180349031 +0100
+++ gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-10.c 2019-11-27 
12:23:48.070903012 +0100
@@ -0,0 +1,10 @@
+/* PR tree-optimization/92691 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+void
+foo (int x, char *y)
+{
+  if (x != 0)
+    __builtin_snprintf (y, 0, "foo");
+}

        Jakub

Reply via email to