Hi! REALPART_EXPR and IMAGPART_EXPR are handled like unary expressions, even though they are references. For !lval that makes no difference, but for lval it means we can get ADDR_EXPR of INTEGER_CST etc., or trying to store into an INTEGER_CST.
Fixed by doing roughly what we do for other references like COMPONENT_REF, ARRAY_REF etc. in that case. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/6.2? 2016-07-11 Jakub Jelinek <ja...@redhat.com> PR c++/71828 * constexpr.c (cxx_eval_constant_expression) <case REALPART_EXPR>: For lval don't use cxx_eval_unary_expression and instead recurse and if needed rebuild the reference. * g++.dg/cpp0x/constexpr-71828.C: New test. --- gcc/cp/constexpr.c.jj 2016-07-11 11:14:28.000000000 +0200 +++ gcc/cp/constexpr.c 2016-07-11 13:30:17.333065119 +0200 @@ -3790,6 +3790,19 @@ cxx_eval_constant_expression (const cons case REALPART_EXPR: case IMAGPART_EXPR: + if (lval) + { + r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, + non_constant_p, overflow_p); + if (r == error_mark_node) + ; + else if (r == TREE_OPERAND (t, 0)) + r = t; + else + r = fold_build1 (TREE_CODE (t), TREE_TYPE (t), r); + break; + } + /* FALLTHRU */ case CONJ_EXPR: case FIX_TRUNC_EXPR: case FLOAT_EXPR: --- gcc/testsuite/g++.dg/cpp0x/constexpr-71828.C.jj 2016-07-11 13:39:31.635423827 +0200 +++ gcc/testsuite/g++.dg/cpp0x/constexpr-71828.C 2016-07-11 13:39:02.000000000 +0200 @@ -0,0 +1,5 @@ +// PR c++/71828 +// { dg-do compile { target c++11 } } + +constexpr _Complex int a { 1, 2 }; +static_assert (& __imag a != &__real a, ""); Jakub