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
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.