The middle-end doesn't like when I give it a PLUS_EXPR with pointer type.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 98e8254b2e89e1e34521a7cf9f027bd78eddd3ab Author: Jason Merrill <ja...@redhat.com> Date: Tue Nov 18 13:36:46 2014 -0500 PR c++/63925 * constexpr.c (cxx_eval_increment_expression): Use POINTER_PLUS_EXPR. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 4325caa..5abea14 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -2566,8 +2566,17 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, /* The modified value. */ bool inc = (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR); - tree mod = fold_build2 (inc ? PLUS_EXPR : MINUS_EXPR, - type, val, offset); + tree mod; + if (POINTER_TYPE_P (type)) + { + /* The middle end requires pointers to use POINTER_PLUS_EXPR. */ + offset = convert_to_ptrofftype (offset); + if (!inc) + offset = fold_build1 (NEGATE_EXPR, TREE_TYPE (offset), offset); + mod = fold_build2 (POINTER_PLUS_EXPR, type, val, offset); + } + else + mod = fold_build2 (inc ? PLUS_EXPR : MINUS_EXPR, type, val, offset); VERIFY_CONSTANT (mod); /* Storing the modified value. */ diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-incr1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-incr1.C index 2b099c8..ecd7c04 100644 --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-incr1.C +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-incr1.C @@ -1,4 +1,5 @@ // { dg-do compile { target c++14 } } +#define SA(X) static_assert((X),#X) constexpr int f (int i) { @@ -8,6 +9,15 @@ constexpr int f (int i) return x; } +constexpr int* g (int* p) +{ + ++p; + return p; +} + constexpr int i = f(42); -#define SA(X) static_assert((X),#X) SA(i==44); + +int array[4]; +constexpr int* p = g(array); +SA(p == &array[1]);