https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105550
--- Comment #3 from CVS Commits <cvs-commit at gcc dot gnu.org> --- The trunk branch has been updated by Marek Polacek <mpola...@gcc.gnu.org>: https://gcc.gnu.org/g:ecd11acacd6be57af930fa617d7c31ecb40e7f74 commit r13-1397-gecd11acacd6be57af930fa617d7c31ecb40e7f74 Author: Marek Polacek <pola...@redhat.com> Date: Wed May 25 18:11:31 2022 -0400 c++: fix broken copy elision with nested TARGET_EXPRs [PR105550] In this problem, we are failing to properly perform copy elision with a conditional operator, so this: constexpr A a = true ? A{} : A{}; fails with: error: 'A{((const A*)(&<anonymous>))}' is not a constant expression The whole initializer is TARGET_EXPR <D.2395, 1 ? TARGET_EXPR <D.2393, {.p=(const struct A *) &<PLACEHOLDER_EXPR struct A>}> : TARGET_EXPR <D.2394, {.p=(const struct A *) &<PLACEHOLDER_EXPR struct A>}>> where the outermost TARGET_EXPR is elided, but not the nested ones. Then we end up replacing the PLACEHOLDER_EXPRs with the temporaries the TARGET_EXPRs represent, which is precisely what should *not* happen with copy elision. I've tried the approach of tweaking ctx->object, but I ran into gazillion problems with that. I thought that I would let cxx_eval_constant_expression /TARGET_EXPR create a new object only when ctx->object was null, then adjust setting of ctx->object in places like cxx_bind_parameters_in_call and cxx_eval_component_reference but that failed completely. Sometimes ctx->object has to be reset, sometimes it cannot be reset, 'this' needed special handling, etc. I gave up. Instead, this patch strips TARGET_EXPRs from the operands of ?: like we do in various other places in constexpr.c. PR c++/105550 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_conditional_expression): Strip TARGET_EXPRs. gcc/testsuite/ChangeLog: * g++.dg/cpp1y/nsdmi-aggr16.C: Remove FIXME. * g++.dg/cpp1y/nsdmi-aggr17.C: Remove FIXME. * g++.dg/cpp0x/constexpr-elision1.C: New test. * g++.dg/cpp1y/constexpr-elision1.C: New test.