On Fri, Mar 13, 2015 at 3:40 PM, Marek Polacek <pola...@redhat.com> wrote: > 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?
It's "correct" for constexpr folding but not correct to hand s[1] down to the middle-end IL (both cases). Well, in the particular case with in-array-bound constant and a non-pointer base it's good enough at least. Richard. > 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