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