c++: 'mutable' member within constexpr [PR92505]

This patch permits accessing 'mutable' members of local objects during
constexpr evaluation, while continuing to reject it for global objects
(as in the last line of cpp0x/constexpr-mutable1.C).  To distinguish
between the two cases, it looks like it suffices to just check
CONSTRUCTOR_MUTABLE_POSION in cxx_eval_component_reference before
deciding to reject a DECL_MUTABLE_P member access.

	PR c++/92505

gcc/cp/ChangeLog:

	* constexpr.cc (cxx_eval_component_reference): Check non_constant_p
	sooner.  In C++14 or later, reject a DECL_MUTABLE_P member access
	only if CONSTRUCTOR_MUTABLE_POISION is also set.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp0x/constexpr-mutable3.C: New test.
	* g++.dg/cpp1y/constexpr-mutable1.C: New test.
This commit is contained in:
Patrick Palka 2022-09-16 11:10:43 -04:00
parent b6adc6255f
commit 7107ea6fb9
3 changed files with 32 additions and 4 deletions

View File

@ -4088,6 +4088,8 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t,
tree whole = cxx_eval_constant_expression (ctx, orig_whole,
lval,
non_constant_p, overflow_p);
if (*non_constant_p)
return t;
if (INDIRECT_REF_P (whole)
&& integer_zerop (TREE_OPERAND (whole, 0)))
{
@ -4108,20 +4110,21 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t,
whole, part, NULL_TREE);
/* Don't VERIFY_CONSTANT here; we only want to check that we got a
CONSTRUCTOR. */
if (!*non_constant_p && TREE_CODE (whole) != CONSTRUCTOR)
if (TREE_CODE (whole) != CONSTRUCTOR)
{
if (!ctx->quiet)
error ("%qE is not a constant expression", orig_whole);
*non_constant_p = true;
return t;
}
if (DECL_MUTABLE_P (part))
if ((cxx_dialect < cxx14 || CONSTRUCTOR_MUTABLE_POISON (whole))
&& DECL_MUTABLE_P (part))
{
if (!ctx->quiet)
error ("mutable %qD is not usable in a constant expression", part);
*non_constant_p = true;
return t;
}
if (*non_constant_p)
return t;
bool pmf = TYPE_PTRMEMFUNC_P (TREE_TYPE (whole));
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value)
{

View File

@ -0,0 +1,9 @@
// PR c++/92505
// { dg-do compile { target c++11 } }
struct A { mutable int m; };
constexpr int f(A a) { return a.m; }
static_assert(f({42}) == 42, "");
// { dg-error "non-constant|mutable" "" { target c++11_only } .-1 }

View File

@ -0,0 +1,16 @@
// PR c++/92505
// { dg-do compile { target c++14 } }
struct S { mutable int m; };
static_assert(S{42}.m == 42, "");
constexpr int f() {
S s = {40};
s.m++;
const auto& cs = s;
++cs.m;
return cs.m;
}
static_assert(f() == 42, "");