GCC trunk does not accept this well-formed program in -std=c++2a mode: constexpr int f() { struct { mutable int i = 41; } s; auto const& cs = s; return ++cs.i; } int main() { constexpr int i = f(); return 42 - i; } Diagnosing (https://godbolt.org/z/n259tb): <source>: In function 'int main()': <source>:10:24: in 'constexpr' expansion of 'f()' <source>:10:25: error: mutable 'f()::<unnamed struct>::i' is not usable in a constant expression 10 | constexpr int i = f(); | ^ Compiler returned: 1 AFAICS this is well-formed back to C++14 since it applies lvalue-to-rvalue conversion to "a non-volatile glvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of e;".
Looks like this never worked.
cxx_eval_component_reference has: 2967 if (DECL_MUTABLE_P (part)) 2968 { 2969 if (!ctx->quiet) 2970 error ("mutable %qD is not usable in a constant expression", part); 2971 *non_constant_p = true; 2972 } Added in https://gcc.gnu.org/ml/gcc-patches/2011-10/msg02593.html I will need to do a bit of archeology on the isocpp mailing list to see the discussions.
Gentle ping, this has started to cause issues in the libc++ GCC CI for ranges.
Confirmed; the test case can be as simple as // https://godbolt.org/z/M9rf31qqq struct S { mutable int m; }; static_assert(S{42}.m == 42); (Removing the "mutable" keyword makes GCC happy.)
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>: https://gcc.gnu.org/g:7107ea6fb933f1e928593c7e92edfd64ccf0df63 commit r13-2701-g7107ea6fb933f1e928593c7e92edfd64ccf0df63 Author: Patrick Palka <ppalka@redhat.com> Date: Fri Sep 16 11:10:43 2022 -0400 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.
Fixed for GCC 13.