Hi! The recent match.pd changes can generate a MEM_REF which can be seen by the C FE folding routines. Unlike the C++ FE, they weren't expected in the C FE yet. MEM_REF should be handled like INDIRECT_REF, except that it has two operands rather than just one and that we should preserve the type of the second operand. Given that it already has to be an INTEGER_CST with pointer type, I think we are fine, the recursive call should return the INTEGER_CST unmodified and STRIP_TYPE_NOPS will not strip anything.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2020-03-16 Jakub Jelinek <ja...@redhat.com> PR c/94179 * c-fold.c (c_fully_fold_internal): Handle MEM_REF. * gcc.c-torture/compile/pr94179.c: New test. --- gcc/c/c-fold.c.jj 2020-01-12 11:54:36.208416501 +0100 +++ gcc/c/c-fold.c 2020-03-15 17:26:42.863491563 +0100 @@ -346,6 +346,7 @@ c_fully_fold_internal (tree expr, bool i case UNGT_EXPR: case UNGE_EXPR: case UNEQ_EXPR: + case MEM_REF: /* Binary operations evaluating both arguments (increment and decrement are binary internally in GCC). */ orig_op0 = op0 = TREE_OPERAND (expr, 0); @@ -435,6 +436,14 @@ c_fully_fold_internal (tree expr, bool i || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE) && TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE) warn_for_div_by_zero (loc, op1); + if (code == MEM_REF + && ret != expr + && TREE_CODE (ret) == MEM_REF) + { + TREE_READONLY (ret) = TREE_READONLY (expr); + TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr); + TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr); + } goto out; case ADDR_EXPR: --- gcc/testsuite/gcc.c-torture/compile/pr94179.c.jj 2020-03-15 17:14:20.782511288 +0100 +++ gcc/testsuite/gcc.c-torture/compile/pr94179.c 2020-03-15 17:13:48.913984847 +0100 @@ -0,0 +1,9 @@ +/* PR c/94179 */ + +struct S { char c, d, e[64]; } a; + +unsigned char * +foo (int b) +{ + return (unsigned char *)((char *)&a.e[b != 0] - (char *)&((struct S *)0)->d); +} Jakub