Hi!

The following testcase ICEs in 4.8/4.9.  The problem is that we don't fold
NON_LVALUE_EXPR of INTEGER_CST into the INTEGER_CST, but it seems huge
amount of fold-const.c code has the assumption that if
argN = opN;
...
STRIP_NOPS (argN);
...
if (TREE_CODE (argN) == INTEGER_CST)

then argN == opN, so passes e.g. argN instead of opN, assuming that
argN must have type already.  Eric has fixed this for 5+ already
by dropping the NON_LVALUE_EXPR if the argument is isn't a possible lvalue.

Bootstrapped/regtested on x86_64-linux and i686-linux on both 4.9 and 4.8
branches with --enable-checking=yes,rtl, ok for those branches?
Is the testcase alone ok for 5.2/trunk?

A safer alternative would be just to fold NON_LVALUE_EXPR of INTEGER_CST
into the INTEGER_CST.

2015-06-12  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/63608
        * gcc.c-torture/compile/pr63608.c: New test.

        Backported from mainline
        2014-05-16  Eric Botcazou  <ebotca...@adacore.com>

        * fold-const (fold_unary_loc) <NON_LVALUE_EXPR>: New case.
        <CASE_CONVERT>: Pass arg0 instead of op0 to fold_convert_const.

--- gcc/fold-const.c    (revision 210517)
+++ gcc/fold-const.c    (revision 210518)
@@ -7850,6 +7850,11 @@ fold_unary_loc (location_t loc, enum tre
        return fold_convert_loc (loc, type, op0);
       return NULL_TREE;
 
+    case NON_LVALUE_EXPR:
+      if (!maybe_lvalue_p (op0))
+       return fold_convert_loc (loc, type, op0);
+      return NULL_TREE;
+
     CASE_CONVERT:
     case FLOAT_EXPR:
     case FIX_TRUNC_EXPR:
@@ -8113,7 +8118,7 @@ fold_unary_loc (location_t loc, enum tre
            }
        }
 
-      tem = fold_convert_const (code, type, op0);
+      tem = fold_convert_const (code, type, arg0);
       return tem ? tem : NULL_TREE;
 
     case ADDR_SPACE_CONVERT_EXPR:
--- gcc/testsuite/gcc.c-torture/compile/pr63608.c.jj    2015-06-12 
10:55:16.484746890 +0200
+++ gcc/testsuite/gcc.c-torture/compile/pr63608.c       2015-06-12 
10:53:58.000000000 +0200
@@ -0,0 +1,14 @@
+/* PR middle-end/63608 */
+
+typedef long T;
+typedef unsigned long U;
+unsigned long a;
+
+unsigned long
+foo (int b)
+{
+  T c = 0;
+  const U d = 2248593032UL;
+  a = (c = +d) | (~4L & ~b);
+  return c;
+}

        Jakub

Reply via email to