Hi!

The recent change to clear TREE_SIDE_EFFECTS on STATEMENT_LIST containing
DEBUG_BEGIN_STMTs and a single other statement without TREE_SIDE_EFFECTS on
it breaks the C stmt expr handling.  The problem is that it assumes if
TREE_SIDE_EFFECTS is clear on a STATEMENT_LIST then that means the
STATEMENT_LIST is empty, i.e. ({ }), which is no longer the case.

Fixed by skipping over DEBUG_BEGIN_STMTs from the tail to find the last
non-DEBUG_BEGIN_STMT stmt (if any, and if none, treat it like ({ }) ),
and also not processing the last non-DEBUG_BEGIN_STMT for -Wunused-value
if it is followed by DEBUG_BEGIN_STMTs.

In addition to this, the patch includes a fix from my earlier patch, where
alloc_stmt_list TREE_SIDE_EFFECTS bit is inconsistent, depending on whether
it is reused from the cache (then TREE_SIDE_EFFECTS was clear), or newly
allocated (then it was set).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2017-12-22  Jakub Jelinek  <ja...@redhat.com>

        PR debug/83547
        * tree-iterator.c (alloc_stmt_list): Start with cleared
        TREE_SIDE_EFFECTS regardless whether a new STATEMENT_LIST is allocated
        or old one reused.
c/
        * c-typeck.c (c_finish_stmt_expr): Ignore !TREE_SIDE_EFFECTS as
        indicator of ({ }), instead skip all trailing DEBUG_BEGIN_STMTs first,
        and consider empty ones if there are no other stmts.  For
        -Wunused-value walk all statements before the one only followed by
        DEBUG_BEGIN_STMTs.
testsuite/
        * gcc.c-torture/compile/pr83547.c: New test.

--- gcc/tree-iterator.c.jj      2017-12-18 14:57:11.000000000 +0100
+++ gcc/tree-iterator.c 2017-12-22 12:18:49.017432720 +0100
@@ -41,7 +41,10 @@ alloc_stmt_list (void)
       TREE_SET_CODE (list, STATEMENT_LIST);
     }
   else
-    list = make_node (STATEMENT_LIST);
+    {
+      list = make_node (STATEMENT_LIST);
+      TREE_SIDE_EFFECTS (list) = 0;
+    }
   TREE_TYPE (list) = void_type_node;
   return list;
 }
--- gcc/c/c-typeck.c.jj 2017-12-19 18:09:05.000000000 +0100
+++ gcc/c/c-typeck.c    2017-12-22 12:29:01.213576464 +0100
@@ -10751,17 +10751,21 @@ c_finish_stmt_expr (location_t loc, tree
  continue_searching:
   if (TREE_CODE (last) == STATEMENT_LIST)
     {
-      tree_stmt_iterator i;
+      tree_stmt_iterator l = tsi_last (last);
+
+      while (!tsi_end_p (l) && TREE_CODE (tsi_stmt (l)) == DEBUG_BEGIN_STMT)
+       tsi_prev (&l);
 
       /* This can happen with degenerate cases like ({ }).  No value.  */
-      if (!TREE_SIDE_EFFECTS (last))
+      if (tsi_end_p (l))
        return body;
 
       /* If we're supposed to generate side effects warnings, process
         all of the statements except the last.  */
       if (warn_unused_value)
        {
-         for (i = tsi_start (last); !tsi_one_before_end_p (i); tsi_next (&i))
+         for (tree_stmt_iterator i = tsi_start (last);
+              tsi_stmt (i) != tsi_stmt (l); tsi_next (&i))
            {
              location_t tloc;
              tree t = tsi_stmt (i);
@@ -10770,13 +10774,7 @@ c_finish_stmt_expr (location_t loc, tree
              emit_side_effect_warnings (tloc, t);
            }
        }
-      else
-       i = tsi_last (last);
-      if (TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
-       do
-         tsi_prev (&i);
-       while (TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT);
-      last_p = tsi_stmt_ptr (i);
+      last_p = tsi_stmt_ptr (l);
       last = *last_p;
     }
 
--- gcc/testsuite/gcc.c-torture/compile/pr83547.c.jj    2017-12-22 
12:36:06.503125477 +0100
+++ gcc/testsuite/gcc.c-torture/compile/pr83547.c       2017-12-22 
12:35:45.000000000 +0100
@@ -0,0 +1,16 @@
+/* PR debug/83547 */
+
+void
+foo (void)
+{
+  if (({ 0; }))
+    ;
+  if (({ 0; 0; }))
+    ;
+  if (({ }))           /* { dg-error "void value not ignored as it ought to 
be" } */
+    ;
+  if (({ 0; { 0; } })) /* { dg-error "void value not ignored as it ought to 
be" } */
+    ;
+  if (({ 0; {} }))     /* { dg-error "void value not ignored as it ought to 
be" } */
+    ;
+}

        Jakub

Reply via email to