We started to reject this (IMHO valid) testcase with r214941 that did away with
try_move_mult_to_index -- meaning that we are no longer able to fold *(&s[0] + 
1)
into s[1], while we are able to fold *(s + 1) into s[1].

I suppose cxx_fold_indirect_ref ought to be able to handle both cases, so I 
added
some code to that effect, it should handle now at least the simple cases...
Or should that be handled in the middle end?

I have also tried:

constexpr char s[] = "abc";
constexpr int i = 0;
constexpr char c = *(&s[0] + i);

and that is accepted even without this patch.

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

2015-03-13  Marek Polacek  <pola...@redhat.com>

        PR c++/65398
        * constexpr.c (cxx_fold_indirect_ref): Transform *(&A[i] p+ j) into
        A[i + j].

        * g++.dg/cpp0x/pr65398.C: New test.

diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
index 1b5f50c..18f4d8c 100644
--- gcc/cp/constexpr.c
+++ gcc/cp/constexpr.c
@@ -2427,6 +2427,17 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree 
op0, bool *empty_base)
                    break;
                  }
            }
+         /* *(&A[i] p+ j) => A[i + j] */
+         else if (TREE_CODE (op00) == ARRAY_REF
+                  && TREE_CODE (TREE_OPERAND (op00, 1)) == INTEGER_CST
+                  && TREE_CODE (op01) == INTEGER_CST)
+           {
+             tree t = fold_convert_loc (loc, TREE_TYPE (op01),
+                                        TREE_OPERAND (op00, 1));
+             t = size_binop_loc (loc, PLUS_EXPR, op01, t);
+             return build4_loc (loc, ARRAY_REF, type, TREE_OPERAND (op00, 0),
+                                t, NULL_TREE, NULL_TREE);
+           }
        }
     }
   /* *(foo *)fooarrptr => (*fooarrptr)[0] */
diff --git gcc/testsuite/g++.dg/cpp0x/pr65398.C 
gcc/testsuite/g++.dg/cpp0x/pr65398.C
index e69de29..dc22d27 100644
--- gcc/testsuite/g++.dg/cpp0x/pr65398.C
+++ gcc/testsuite/g++.dg/cpp0x/pr65398.C
@@ -0,0 +1,19 @@
+// PR c++/65398
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+constexpr char s[] = "abc";
+constexpr char c1 = *(&s[0] + 0);
+constexpr char c2 = *(&s[0] + 1);
+constexpr char c3 = *(&s[1] + 0);
+constexpr char c4 = *(&s[1] + 1);
+constexpr char c5 = *(&s[2] + 0);
+constexpr char c6 = *(&s[0] + 2);
+
+SA (c1 == 'a');
+SA (c2 == 'b');
+SA (c3 == 'b');
+SA (c4 == 'c');
+SA (c5 == 'c');
+SA (c6 == 'c');

        Marek

Reply via email to