From 337815c8bbd0fb5034223ad0e7899d1493e958a2 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 11 Dec 2024 17:28:47 +0100 Subject: [PATCH] c++: allow stores to anon union vars to change current union member in constexpr [PR117614] Since r14-4771 the FE tries to differentiate between cases where the lhs of a store allows changing the current union member and cases where it doesn't, and cases where it doesn't includes everything that has gone through the cxx_eval_constant_expression path on the lhs. As the testcase shows, DECL_ANON_UNION_VAR_P vars were handled like that too, even when stores to them are the only way how to change the current union member in the sources. So, the following patch just handles that case manually without calling cxx_eval_constant_expression and without setting evaluated to true. 2024-12-11 Jakub Jelinek PR c++/117614 * constexpr.cc (cxx_eval_store_expression): For stores to DECL_ANON_UNION_VAR_P vars just continue with DECL_VALUE_EXPR of it, without setting evaluated to true or full cxx_eval_constant_expression. * g++.dg/cpp2a/constexpr-union8.C: New test. --- gcc/cp/constexpr.cc | 8 +++++ gcc/testsuite/g++.dg/cpp2a/constexpr-union8.C | 31 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-union8.C diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 08765c9caa6..c16597dfaec 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -6418,6 +6418,14 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, object = probe; else { + tree pvar = tree_strip_any_location_wrapper (probe); + if (VAR_P (pvar) && DECL_ANON_UNION_VAR_P (pvar)) + { + /* Stores to DECL_ANON_UNION_VAR_P var are allowed to change + active union member. */ + probe = DECL_VALUE_EXPR (pvar); + break; + } probe = cxx_eval_constant_expression (ctx, probe, vc_glvalue, non_constant_p, overflow_p); evaluated = true; diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-union8.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-union8.C new file mode 100644 index 00000000000..1e51857b3df --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-union8.C @@ -0,0 +1,31 @@ +// PR c++/117614 +// { dg-do compile { target c++20 } } + +constexpr int +foo () +{ + union { + int x{0}; + char y; + }; + y = 1; + return y; +} + +constexpr int +bar () +{ + union { + union { + int x{0}; + char y; + }; + long long z; + }; + y = 1; + z = 2; + return z; +} + +static_assert (foo () == 1); +static_assert (bar () == 2);