https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127219
Bug ID: 127219
Summary: <format>: make __valid_types_for_check_dynamic_spec
static so check_dynamic_spec<Ts...> works with clang
and EDG
Product: gcc
Version: 16.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: stevensudit at gmail dot com
Target Milestone: ---
Host: x86_64-linux-gnu
Target: x86_64-linux-gnu
Build: x86_64-linux-gnu
Created attachment 65507
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65507&action=edit
test: user formatter calling check_dynamic_spec
In C++26 mode a user formatter that calls
basic_format_parse_context::check_dynamic_spec<Ts...>(id) does not
compile with clang or EDG on top of libstdc++ (attached
format_check_dynamic_spec.cc):
$ clang++ -std=c++26 -fsyntax-only format_check_dynamic_spec.cc
format:343:18: error: static assertion expression is not an integral
constant expression
format_check_dynamic_spec.cc:28:10: note: in instantiation of function
template specialization 'std::basic_format_parse_context<char>::
check_dynamic_spec<int, unsigned int>' requested here
format:343:18: note: implicit use of 'this' pointer is only allowed
within the evaluation of a call to a 'constexpr' member function
EDG 6.9 (Compiler Explorer, --c++26 with the gcc 16.1 headers) says the
same thing at the same line: "expression must have a constant value",
"the value of *this cannot be used as a constant". g++ 16.2 and trunk
accept the file. Reproduced with clang 20.1, 21.1, 22.1, 23.1 and trunk
against libstdc++ 15.2, 16.2 and trunk.
The line is
static_assert(__valid_types_for_check_dynamic_spec<_Ts...>(), ...);
in check_dynamic_spec (format:343). __valid_types_for_check_dynamic_spec
is a non-static consteval member, so the call is
(*this).__valid_types_for_check_dynamic_spec<_Ts...>(), evaluated by the
static_assert rather than as part of a call to a constexpr member
function, and everything hinges on `this` being usable there. After
P2280R4 ([expr.const]/5.1.2: `this` as the postfix-expression of an
implicit or explicit class member access) it is, and the function never
reads through the pointer. So the header is correct and gcc is right to
accept it. clang (llvm/llvm-project issue 191104, open) and EDG have not
caught up with that part of P2280R4; MSVC has. The attached
reduce_b_implicit_this.cc has the same shape without <format>: gcc trunk
and MSVC 19 accept it, clang trunk and EDG 6.9 reject it.
Since libstdc++ supports being used from clang, it seems worth stepping
around. __valid_types_for_check_dynamic_spec uses no non-static member,
so declaring it static removes the `this` and changes nothing else. The
one-word patch against trunk is attached; clang 23.1 and trunk g++ then
both accept the test against the trunk headers. The diagnosis was made
with LLM assistance (Claude, Anthropic), which I am noting per
https://gcc.gnu.org/ai-policy.html. I can send the patch to libstdc++@
with a ChangeLog and Assisted-by tag if that is useful, though it is
probably quicker for you to just make the change.
testsuite/std/format/parse_ctx.cc already exercises
check_dynamic_spec<Ts...>, so no new test seems needed; the testsuite
runs under g++, which accepts either spelling.