Hi! I've added the asserts that probe == target because {REAL,IMAG}PART_EXPR always implies a scalar type and so applying ARRAY_REF/COMPONENT_REF etc. on it further doesn't make sense and the later code relies on it to be the last one in refs array. But as the following testcase shows, we can fail those assertions in case there is a reference or pointer to the __real__ or __imag__ part, in that case we just evaluate the constant expression and so probe won't be the same as target. That case doesn't push anything into the refs array though.
The following patch changes those asserts to verify that refs is still empty, which fixes it. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2025-02-27 Jakub Jelinek <ja...@redhat.com> PR c++/119045 * constexpr.cc (cxx_eval_store_expression) <case REALPART_EXPR>: Assert that refs->is_empty () rather than probe == target. (cxx_eval_store_expression) <case IMAGPART_EXPR>: Likewise. * g++.dg/cpp1y/constexpr-complex2.C: New test. --- gcc/cp/constexpr.cc.jj 2025-02-24 00:06:25.652734218 +0100 +++ gcc/cp/constexpr.cc 2025-02-27 16:59:23.966507094 +0100 @@ -6415,7 +6415,7 @@ cxx_eval_store_expression (const constex break; case REALPART_EXPR: - gcc_assert (probe == target); + gcc_assert (refs->is_empty ()); vec_safe_push (refs, NULL_TREE); vec_safe_push (refs, probe); vec_safe_push (refs, TREE_TYPE (probe)); @@ -6423,7 +6423,7 @@ cxx_eval_store_expression (const constex break; case IMAGPART_EXPR: - gcc_assert (probe == target); + gcc_assert (refs->is_empty ()); vec_safe_push (refs, NULL_TREE); vec_safe_push (refs, probe); vec_safe_push (refs, TREE_TYPE (probe)); --- gcc/testsuite/g++.dg/cpp1y/constexpr-complex2.C.jj 2025-02-27 17:01:18.613919510 +0100 +++ gcc/testsuite/g++.dg/cpp1y/constexpr-complex2.C 2025-02-27 17:01:47.631517685 +0100 @@ -0,0 +1,18 @@ +// PR c++/119045 +// { dg-do compile { target c++14 } } + +constexpr float +foo () +{ + __complex__ float f {1, 2}; + float s = __real__ f + __imag__ f; + float &r = __real__ f; + float &i = __imag__ f; + r = 42; + s += __real__ f; + i = 3; + s += __imag__ f; + return s; +} + +static_assert (foo () == 48.0f, ""); Jakub