https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101663
--- Comment #3 from CVS Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Patrick Palka <ppa...@gcc.gnu.org>: https://gcc.gnu.org/g:21fd62e5ca9967bba8f97fd6244a8c6a564c2146 commit r12-2868-g21fd62e5ca9967bba8f97fd6244a8c6a564c2146 Author: Patrick Palka <ppa...@redhat.com> Date: Wed Aug 11 20:59:53 2021 -0400 c++: constexpr std::construct_at on empty field [PR101663] Here during constexpr evaluation of std::construct_at(&a._M_value) we find ourselves in cxx_eval_store_expression where the target object is 'a._M_value' and the initializer is {}. Since _M_value is an empty [[no_unique_address]] member we don't create a sub-CONSTRUCTOR for it, so we end up in the early exit code path for empty stores with mismatched types and trip over the assert therein gcc_assert (is_empty_class (TREE_TYPE (init)) && !lval); because lval is true. The reason it's true is because the INIT_EXPR in question is the LHS of a COMPOUND_EXPR, and evaluation of the LHS is always performed with lval=true (to indicate there's no lvalue-to-rvalue conversion). This patch makes the code path in question handle the lval=true case appropriately rather than asserting. In passing, it also consolidates the duplicate implementations of std::construct_at/destroy_at in some of the C++20 constexpr tests into a common header file. PR c++/101663 gcc/cp/ChangeLog: * constexpr.c (cxx_eval_store_expression): Handle the lval=true case in the early exit code path for empty stores with mismatched types. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/construct_at.h: New convenience header file that defines minimal implementations of std::construct_at/destroy_at, split out from ... * g++.dg/cpp2a/constexpr-new5.C: ... here. * g++.dg/cpp2a/constexpr-new6.C: Use the header. * g++.dg/cpp2a/constexpr-new14.C: Likewise. * g++.dg/cpp2a/constexpr-new20.C: New test.