Hi!

Seems since delayed C++ folding fold_* can sometimes be called with
operand(s) that are NOP_EXPR of INTEGER_CST.  Unfortunately the folder
is heavily unprepared to deal with that, I think it is not dozens but
hundreds of places where it assumes that if argN (result of STRIP_NOPS)
is INTEGER_CST then argN == opN and there is no need to fold_convert it
to type.  So it seems easier to make sure we don't do that again.
The problem is in cp_fold, where it folded both arguments, but if
any of them for COMPOUND_EXPR or MODIFY_EXPR has side effects, it
throws the folded arguments on the floor and keeps using the old thing.
While it is (probably) inappropriate to fold the whole COMPOUND_EXPR or
MODIFY_EXPR in that case, we should at least build a new COMPOUND_EXPR
or MODIFY_EXPR and stick the folded argument(s) into it.

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

2016-01-11  Jakub Jelinek  <ja...@redhat.com>

        PR c++/69211
        * cp-gimplify.c (cp_fold): If COMPOUND_EXPR or MODIFY_EXPR
        folded operands have side-effects, but folding changed any of them,
        build a new tree with the folded operands instead of returning the
        unfolded tree.

        * g++.dg/opt/pr69211.C: New test.

--- gcc/cp/cp-gimplify.c.jj     2016-01-11 13:22:36.000000000 +0100
+++ gcc/cp/cp-gimplify.c        2016-01-11 15:26:46.898802115 +0100
@@ -2089,7 +2089,11 @@ cp_fold (tree x)
       if ((code == COMPOUND_EXPR || code == MODIFY_EXPR)
          && ((op1 && TREE_SIDE_EFFECTS (op1))
               || (op0 && TREE_SIDE_EFFECTS (op0))))
-       break;
+       {
+         if (op0 != TREE_OPERAND (x, 0) || op1 != TREE_OPERAND (x, 1))
+           x = build2_loc (loc, code, TREE_TYPE (x), op0, op1);
+         break;
+       }
       if (TREE_CODE (x) == COMPOUND_EXPR && !op0)
        op0 = build_empty_stmt (loc);
 
--- gcc/testsuite/g++.dg/opt/pr69211.C.jj       2016-01-11 15:27:58.283816511 
+0100
+++ gcc/testsuite/g++.dg/opt/pr69211.C  2016-01-11 15:27:41.000000000 +0100
@@ -0,0 +1,10 @@
+// PR c++/69211
+// { dg-do compile }
+
+int a, b;
+
+int
+foo ()
+{
+  return (a & 5UL | (b = 4, 4L)) > 4;
+}

        Jakub

Reply via email to