Hi! Apparently we can end up trying to store into a pointer-to-member that has a PTRMEM_CST as its current value. Later code in cxx_eval_store_expression is upset that it isn't a CONSTRUCTOR when the type is actually aggregate.
The following patch fixes that, bootstrapped/regtested on x86_64-linux and i686-linux, though I admit I'm not really sure if this is the best fix. 2017-02-21 Jakub Jelinek <ja...@redhat.com> PR c++/79639 * constexpr.c (cxx_eval_store_expression): If *valp is a PTRMEM_CST, call cplus_expand_constant on it first. * g++.dg/cpp1y/constexpr-79639.C: New test. --- gcc/cp/constexpr.c.jj 2017-02-21 13:49:06.000000000 +0100 +++ gcc/cp/constexpr.c 2017-02-21 14:57:30.290440638 +0100 @@ -3518,11 +3518,12 @@ cxx_eval_store_expression (const constex wants to modify it. */ if (*valp == NULL_TREE) { - *valp = new_ctx.ctor = build_constructor (type, NULL); - CONSTRUCTOR_NO_IMPLICIT_ZERO (new_ctx.ctor) = no_zero_init; + *valp = build_constructor (type, NULL); + CONSTRUCTOR_NO_IMPLICIT_ZERO (*valp) = no_zero_init; } - else - new_ctx.ctor = *valp; + else if (TREE_CODE (*valp) == PTRMEM_CST) + *valp = cplus_expand_constant (*valp); + new_ctx.ctor = *valp; new_ctx.object = target; } --- gcc/testsuite/g++.dg/cpp1y/constexpr-79639.C.jj 2017-02-21 15:06:42.625475572 +0100 +++ gcc/testsuite/g++.dg/cpp1y/constexpr-79639.C 2017-02-21 15:06:07.000000000 +0100 @@ -0,0 +1,27 @@ +// PR c++/79639 +// { dg-do compile { target c++14 } } + +struct A +{ + void foo () {} + void bar () {} +}; +typedef void (A::*T) (); + +constexpr T +foo (T f) +{ + f = 0; + return f; +} + +constexpr T +bar (T f) +{ + f = &A::bar; + return f; +} + +constexpr T a = foo (&A::foo); +constexpr T b = foo (&A::foo); +static_assert (a == nullptr, ""); Jakub