aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2021-08-11 20:59:53 -0400
committerPatrick Palka <ppalka@redhat.com>2021-08-11 20:59:53 -0400
commit21fd62e5ca9967bba8f97fd6244a8c6a564c2146 (patch)
tree80d182ca1748b98e17fe080b965816a359436027 /gcc/cp
parent58f87503427e27bb069bd1841100f3c53440d51a (diff)
downloadgcc-21fd62e5ca9967bba8f97fd6244a8c6a564c2146.zip
gcc-21fd62e5ca9967bba8f97fd6244a8c6a564c2146.tar.gz
gcc-21fd62e5ca9967bba8f97fd6244a8c6a564c2146.tar.bz2
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.
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/constexpr.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 1af365d..25d84a3 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -5588,8 +5588,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
argument, which has the derived type rather than the base type. In
this situation, just evaluate the initializer and return, since
there's no actual data to store. */
- gcc_assert (is_empty_class (TREE_TYPE (init)) && !lval);
- return init;
+ gcc_assert (is_empty_class (TREE_TYPE (init)));
+ return lval ? target : init;
}
CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init);
TREE_CONSTANT (*valp) = TREE_CONSTANT (init);