[PATCH] libstdc++: implement constexpr std::format

Tomasz Kaminski tkaminsk@redhat.com
Mon Mar 2 14:43:45 GMT 2026


On Mon, Mar 2, 2026 at 3:34 PM Ivan Lazaric <ivan.lazaric1@gmail.com> wrote:

> > However, the standard says that the format_string constructor should be
> ill-formed, beause it is consteval function, that is not core-constant
> expression.
> see this case https://eel.is/c++draft/format#fmt.string-3.
>
> Do you think this is worth bringing up as an LWG issue, or otherwise
> confirming intent with WG21?
> Both constexpr exceptions and constexpr formatting are recently added
> features,
> and I wonder if this clause was just missed.
>
I think that this is expected design, you program should not compile if it
contains errors.
Call with an invalid format string. Allowing an exception to exit, would
mean that the
program would compile unless you actually call the format during
compile-time calls.
I.e. I think the intent remain for:
std::format("{sd}", 10)
to be ill-formed, and not produce a recoverable error, i.e. exception you
can catch
at compile time.

On the other topic, we cosntexpr string are not supported for `cow_string`
(pre-C++11),
so the constexpr_format need to have depend on constexpr string, we can
achieve this by
using extra_cond and defining a feature test macro.

Also, in test we need to guad the constepxr check with constexpr_format
(__glibcxx_constexpr_format
for now), contrary to what I previously said.


>
> On Thu, Feb 26, 2026 at 4:48 PM Tomasz Kaminski <tkaminsk@redhat.com>
> wrote:
>
>>
>>
>> On Thu, Feb 26, 2026 at 3:55 PM Ivan Lazaric <ivan.lazaric1@gmail.com>
>> wrote:
>>
>>> libstdc++: partially implement constexpr std::format
>>>
>>> This patch partially implements constexpr formatting from P3391R2,
>>> as such it does not define the __cpp_lib_constexpr_format feature-test
>>> macro.
>>>
>>> This patch mostly adds `_GLIBCXX26_CONSTEXPR` to functions.
>>>
>>> Add `__format::__toupper` function that work in constexpr.
>>> It is not fully general, but `<format>` doesn't need all uppercasing.
>>>
>>> Avoid using `_Ptr_sink` in constexpr in `__do_vformat_to`,
>>> since it is a bit non-trivial to get it to work, and it is just an
>>> optimization.
>>>
>>> Update some formatting tests to test constexpr as well,
>>> and introduce a dedicated smoke test for constexpr formatting.
>>>
>>> This patch is missing:
>>> * wide constexpr formatting
>>> * constexpr to_{,w}string
>>> * more constexpr tests
>>>
>>> libstdc++-v3/ChangeLog:
>>>
>>>         * include/std/format:
>>>         Pepper in _GLIBCXX26_CONSTEXPR, replace memcpy with ranges::copy.
>>>         (__format::__toupper): Define.
>>>         (__format::__do_vformat_to):
>>>         Avoid using _Ptr_sink in constexpr.
>>>         * testsuite/std/format/constexpr.cc: New test.
>>>         * testsuite/std/format/debug.cc: Constexpr testing.
>>>         * testsuite/std/format/functions/format.cc: Constexpr testing.
>>>         * testsuite/std/format/functions/format_to.cc: Constexpr testing.
>>>         * testsuite/std/format/functions/size.cc: Constexpr testing.
>>>         * testsuite/std/format/ranges/format_kind.cc: Constexpr testing.
>>>         * testsuite/std/format/ranges/formatter.cc: Constexpr testing.
>>>         * testsuite/std/format/ranges/sequence.cc: Constexpr testing.
>>>         * testsuite/std/format/runtime_format.cc: Constexpr testing.
>>>         * testsuite/std/format/string.cc: Constexpr testing.
>>>         * testsuite/std/format/tuple.cc: Constexpr testing.
>>>
>>> Signed-off-by: Ivan Lazaric <ivan.lazaric1@gmail.com>
>>> ---
>>>
>> Only comments on update, will do full review later.
>>
>>
>>> Updates to patch:
>>> Replaced __memcpy with ranges::copy
>>> Simplified __toupper as a switch
>>>
>> I would rename it to __toupper_numeric, so it will be clear that
>> it is not general purpose, and add handling of 'x' from prefix,
>> if we ever use it on prefix value.
>>
>>> if (not) consteval replaced with std::is_constant_evaluated()
>>> Rebased on top of your _M_access patch
>>> Removed the version.{def,h} since this doesn't implement full paper
>>>
>> Please use no_stdname instad, that defines internal
>> glibcxx_constexxpr_format,
>> but not __cpp_lib one. That is the preferred approach in such a case.
>>
>> Cleaned up tests as suggested
>>> Added a constexpr.cc test with c++26 target
>>> Killed Counting_constexpr_sink, just going through _Ptr_sink
>>>
>>> Regarding formatting of nullptr:
>>> basic_format_arg(nullptr) will store a `const void*` ,
>>> so `format(nullptr)` will actually go through `formatter<const void*>`.
>>>
>> Makes sense, thanks.
>>
>>>
>>> I've been testing with GLIBCXX_TESTSUITE_STDS=20,23,26,
>>> two tests are failing in 26 now, both are testing compilation errors:
>>> std/format/arguments/args_neg.cc
>>>
>> Haven't looked at this one yet.
>>
>>> std/time/format/data_not_present_neg.cc
>>>
>> The second one is something we need to find way to address, as now
>> we can evaluate following at compile time:
>>   std::format("{:bad}", 10);
>> And in the test we use global variables:
>> auto ym1 = std::format("{:%d}", 2024y/March); // { dg-error "call to
>> consteval function" }
>> For global variables we have try constexpr evaluation, so
>> try to evaluate whole format call at compile time, and because
>> it is constexpr now we try to do it. And that exception end up being
>> propagated.
>>
>> However, the standard says that the format_string constructor should be
>> ill-formed, beause it is consteval function, that is not core-constant
>> expression.
>> see this case https://eel.is/c++draft/format#fmt.string-3. Ie. following
>> should
>> not be able to work;
>>
>> consteval foo() {
>>   try {
>>     // should be ill-formed and not emit exception
>>     std::format("{:bad}", 10);
>>   }
>>   catch (std::format_error)
>>   { }
>> }
>>
>> We could do try-catch inside cosntructor, but that way we will miss the
>> actual
>> content of the error. I was wondering about making the cosntructor simply
>> noexcept
>> so we will hit noexcept boundary at compile time. That should still print
>> content
>> of the error.
>>
>> Haven't yet investigated.
>>>
>>>
>>>  libstdc++-v3/include/std/format               | 388 +++++++++++-------
>>>  .../testsuite/std/format/constexpr.cc         | 126 ++++++
>>>  libstdc++-v3/testsuite/std/format/debug.cc    | 105 +++--
>>>  .../testsuite/std/format/functions/format.cc  | 265 +++++++-----
>>>  .../std/format/functions/format_to.cc         |  63 ++-
>>>  .../testsuite/std/format/functions/size.cc    |  24 +-
>>>  .../std/format/ranges/format_kind.cc          |  15 +-
>>>  .../testsuite/std/format/ranges/formatter.cc  |  45 +-
>>>  .../testsuite/std/format/ranges/sequence.cc   |  73 +++-
>>>  .../testsuite/std/format/runtime_format.cc    |  18 +-
>>>  libstdc++-v3/testsuite/std/format/string.cc   | 230 +++++++----
>>>  libstdc++-v3/testsuite/std/format/tuple.cc    |  78 +++-
>>>  12 files changed, 967 insertions(+), 463 deletions(-)
>>>  create mode 100644 libstdc++-v3/testsuite/std/format/constexpr.cc
>>>
>>> diff --git a/libstdc++-v3/include/std/format
>>> b/libstdc++-v3/include/std/format
>>> index 4f0b0f377c6..b5670d0ec32 100644
>>> --- a/libstdc++-v3/include/std/format
>>> +++ b/libstdc++-v3/include/std/format
>>> @@ -128,6 +128,7 @@ namespace __format
>>>      struct _Runtime_format_string
>>>      {
>>>        [[__gnu__::__always_inline__]]
>>> +      _GLIBCXX26_CONSTEXPR
>>>        _Runtime_format_string(basic_string_view<_CharT> __s) noexcept
>>>        : _M_str(__s) { }
>>>
>>> @@ -173,6 +174,7 @@ namespace __format
>>>         basic_format_string(const _Tp& __s);
>>>
>>>        [[__gnu__::__always_inline__]]
>>> +      _GLIBCXX26_CONSTEXPR
>>>        basic_format_string(__format::_Runtime_format_string<_CharT> __s)
>>> noexcept
>>>        : _M_str(__s._M_str)
>>>        { }
>>> @@ -197,13 +199,13 @@ namespace __format
>>>
>>>  #if __cpp_lib_format >= 202311L // >= C++26
>>>    [[__gnu__::__always_inline__]]
>>> -  inline __format::_Runtime_format_string<char>
>>> +  inline _GLIBCXX26_CONSTEXPR __format::_Runtime_format_string<char>
>>>    runtime_format(string_view __fmt) noexcept
>>>    { return __fmt; }
>>>
>>>  #ifdef _GLIBCXX_USE_WCHAR_T
>>>    [[__gnu__::__always_inline__]]
>>> -  inline __format::_Runtime_format_string<wchar_t>
>>> +  inline _GLIBCXX26_CONSTEXPR __format::_Runtime_format_string<wchar_t>
>>>    runtime_format(wstring_view __fmt) noexcept
>>>    { return __fmt; }
>>>  #endif
>>> @@ -238,7 +240,7 @@ namespace __format
>>>
>>>    /// @cond undocumented
>>>    [[noreturn]]
>>> -  inline void
>>> +  inline _GLIBCXX26_CONSTEXPR void
>>>    __throw_format_error(const char* __what)
>>>    { _GLIBCXX_THROW_OR_ABORT(format_error(__what)); }
>>>
>>> @@ -249,27 +251,27 @@ namespace __format
>>>    // XXX use named functions for each constexpr error?
>>>
>>>    [[noreturn]]
>>> -  inline void
>>> +  inline _GLIBCXX26_CONSTEXPR void
>>>    __unmatched_left_brace_in_format_string()
>>>    { __throw_format_error("format error: unmatched '{' in format
>>> string"); }
>>>
>>>    [[noreturn]]
>>> -  inline void
>>> +  inline _GLIBCXX26_CONSTEXPR void
>>>    __unmatched_right_brace_in_format_string()
>>>    { __throw_format_error("format error: unmatched '}' in format
>>> string"); }
>>>
>>>    [[noreturn]]
>>> -  inline void
>>> +  inline _GLIBCXX26_CONSTEXPR void
>>>    __conflicting_indexing_in_format_string()
>>>    { __throw_format_error("format error: conflicting indexing style in
>>> format string"); }
>>>
>>>    [[noreturn]]
>>> -  inline void
>>> +  inline _GLIBCXX26_CONSTEXPR void
>>>    __invalid_arg_id_in_format_string()
>>>    { __throw_format_error("format error: invalid arg-id in format
>>> string"); }
>>>
>>>    [[noreturn]]
>>> -  inline void
>>> +  inline _GLIBCXX26_CONSTEXPR void
>>>    __failed_to_parse_format_spec()
>>>    { __throw_format_error("format error: failed to parse format-spec"); }
>>>
>>> @@ -517,7 +519,7 @@ namespace __format
>>>    using enum _WidthPrec;
>>>
>>>    template<typename _Context>
>>> -    size_t
>>> +    _GLIBCXX26_CONSTEXPR size_t
>>>      __int_from_arg(const basic_format_arg<_Context>& __arg);
>>>
>>>    constexpr bool __is_digit(char __c)
>>> @@ -750,7 +752,7 @@ namespace __format
>>>        }
>>>
>>>        template<typename _Context>
>>> -       size_t
>>> +       _GLIBCXX26_CONSTEXPR size_t
>>>         _M_get_width(_Context& __ctx) const
>>>         {
>>>           size_t __width = 0;
>>> @@ -762,7 +764,7 @@ namespace __format
>>>         }
>>>
>>>        template<typename _Context>
>>> -       size_t
>>> +       _GLIBCXX26_CONSTEXPR size_t
>>>         _M_get_precision(_Context& __ctx) const
>>>         {
>>>           size_t __prec = -1;
>>> @@ -775,7 +777,7 @@ namespace __format
>>>      };
>>>
>>>    template<typename _Int>
>>> -    inline char*
>>> +    inline _GLIBCXX26_CONSTEXPR char*
>>>      __put_sign(_Int __i, _Sign __sign, char* __dest) noexcept
>>>      {
>>>        if (__i < 0)
>>> @@ -792,7 +794,7 @@ namespace __format
>>>    // Write STR to OUT (and do so efficiently if OUT is a _Sink_iter).
>>>    template<typename _Out, typename _CharT>
>>>      requires output_iterator<_Out, const _CharT&>
>>> -    inline _Out
>>> +    inline _GLIBCXX26_CONSTEXPR _Out
>>>      __write(_Out __out, basic_string_view<_CharT> __str)
>>>      {
>>>        if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
>>> @@ -809,7 +811,7 @@ namespace __format
>>>    // Write STR to OUT with NFILL copies of FILL_CHAR specified by ALIGN.
>>>    // pre: __align != _Align_default
>>>    template<typename _Out, typename _CharT>
>>> -    _Out
>>> +    _GLIBCXX26_CONSTEXPR _Out
>>>      __write_padded(_Out __out, basic_string_view<_CharT> __str,
>>>                    _Align __align, size_t __nfill, char32_t __fill_char)
>>>      {
>>> @@ -883,7 +885,7 @@ namespace __format
>>>    // Write STR to OUT, with alignment and padding as determined by SPEC.
>>>    // pre: __spec._M_align != _Align_default || __align != _Align_default
>>>    template<typename _CharT, typename _Out>
>>> -    _Out
>>> +    _GLIBCXX26_CONSTEXPR _Out
>>>      __write_padded_as_spec(basic_string_view<type_identity_t<_CharT>>
>>> __str,
>>>                            size_t __estimated_width,
>>>                            basic_format_context<_Out, _CharT>& __fc,
>>> @@ -905,7 +907,7 @@ namespace __format
>>>      }
>>>
>>>     template<typename _CharT>
>>> -     size_t
>>> +     _GLIBCXX26_CONSTEXPR size_t
>>>       __truncate(basic_string_view<_CharT>& __s, size_t __prec)
>>>       {
>>>         if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
>>> @@ -1049,7 +1051,7 @@ namespace __format
>>>
>>>    using uint_least32_t = __UINT_LEAST32_TYPE__;
>>>    template<typename _Out, typename _CharT>
>>> -    _Out
>>> +    _GLIBCXX26_CONSTEXPR _Out
>>>      __write_escape_seq(_Out __out, uint_least32_t __val,
>>>                        basic_string_view<_CharT> __prefix)
>>>      {
>>> @@ -1079,7 +1081,7 @@ namespace __format
>>>      }
>>>
>>>    template<typename _Out, typename _CharT>
>>> -    _Out
>>> +    _GLIBCXX26_CONSTEXPR _Out
>>>      __write_escape_seqs(_Out __out, basic_string_view<_CharT> __units)
>>>      {
>>>        using _UChar = make_unsigned_t<_CharT>;
>>> @@ -1090,7 +1092,7 @@ namespace __format
>>>      }
>>>
>>>    template<typename _Out, typename _CharT>
>>> -    _Out
>>> +    _GLIBCXX26_CONSTEXPR _Out
>>>      __write_escaped_char(_Out __out, _CharT __c)
>>>      {
>>>        using _UChar = make_unsigned_t<_CharT>;
>>> @@ -1116,7 +1118,7 @@ namespace __format
>>>      }
>>>
>>>    template<typename _CharT, typename _Out>
>>> -    _Out
>>> +    _GLIBCXX26_CONSTEXPR _Out
>>>      __write_escaped_ascii(_Out __out,
>>>                           basic_string_view<_CharT> __str,
>>>                           _Term_char __term)
>>> @@ -1146,7 +1148,7 @@ namespace __format
>>>      }
>>>
>>>    template<typename _CharT, typename _Out>
>>> -    _Out
>>> +    _GLIBCXX26_CONSTEXPR _Out
>>>      __write_escaped_unicode_part(_Out __out, basic_string_view<_CharT>&
>>> __str,
>>>                                  bool& __prev_esc, _Term_char __term)
>>>      {
>>> @@ -1224,7 +1226,7 @@ namespace __format
>>>      }
>>>
>>>    template<typename _CharT, typename _Out>
>>> -    _Out
>>> +    _GLIBCXX26_CONSTEXPR _Out
>>>      __write_escaped_unicode(_Out __out, basic_string_view<_CharT> __str,
>>>                             _Term_char __term)
>>>      {
>>> @@ -1236,7 +1238,7 @@ namespace __format
>>>      }
>>>
>>>    template<typename _CharT, typename _Out>
>>> -    _Out
>>> +    _GLIBCXX26_CONSTEXPR _Out
>>>      __write_escaped(_Out __out,  basic_string_view<_CharT> __str,
>>> _Term_char __term)
>>>      {
>>>        __out = __format::__write(__out,
>>> _Escapes<_CharT>::_S_term(__term));
>>> @@ -1257,12 +1259,14 @@ namespace __format
>>>    struct _Optional_locale
>>>    {
>>>      [[__gnu__::__always_inline__]]
>>> +    _GLIBCXX26_CONSTEXPR
>>>      _Optional_locale() : _M_dummy(), _M_hasval(false) { }
>>>
>>>      _Optional_locale(const locale& __loc) noexcept
>>>      : _M_loc(__loc), _M_hasval(true)
>>>      { }
>>>
>>> +    _GLIBCXX26_CONSTEXPR
>>>      _Optional_locale(const _Optional_locale& __l) noexcept
>>>      : _M_dummy(), _M_hasval(__l._M_hasval)
>>>      {
>>> @@ -1270,6 +1274,7 @@ namespace __format
>>>         std::construct_at(&_M_loc, __l._M_loc);
>>>      }
>>>
>>> +    _GLIBCXX26_CONSTEXPR
>>>      _Optional_locale&
>>>      operator=(const _Optional_locale& __l) noexcept
>>>      {
>>> @@ -1291,6 +1296,7 @@ namespace __format
>>>        return *this;
>>>      }
>>>
>>> +    _GLIBCXX26_CONSTEXPR
>>>      ~_Optional_locale() { if (_M_hasval) _M_loc.~locale(); }
>>>
>>>      _Optional_locale&
>>> @@ -1317,7 +1323,8 @@ namespace __format
>>>        return _M_loc;
>>>      }
>>>
>>> -    bool has_value() const noexcept { return _M_hasval; }
>>> +    _GLIBCXX26_CONSTEXPR bool
>>> +    has_value() const noexcept { return _M_hasval; }
>>>
>>>      union {
>>>        char _M_dummy = '\0';
>>> @@ -1391,7 +1398,7 @@ namespace __format
>>>        }
>>>
>>>        template<typename _Out>
>>> -       _Out
>>> +       _GLIBCXX26_CONSTEXPR _Out
>>>         format(basic_string_view<_CharT> __s,
>>>                basic_format_context<_Out, _CharT>& __fc) const
>>>         {
>>> @@ -1408,7 +1415,7 @@ namespace __format
>>>         }
>>>
>>>        template<typename _Out>
>>> -       _Out
>>> +       _GLIBCXX26_CONSTEXPR _Out
>>>         _M_format_escaped(basic_string_view<_CharT> __s,
>>>                           basic_format_context<_Out, _CharT>& __fc) const
>>>         {
>>> @@ -1433,7 +1440,7 @@ namespace __format
>>>  #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
>>>        template<ranges::input_range _Rg, typename _Out>
>>>         requires same_as<remove_cvref_t<ranges::range_reference_t<_Rg>>,
>>> _CharT>
>>> -       _Out
>>> +       _GLIBCXX26_CONSTEXPR _Out
>>>         _M_format_range(_Rg&& __rg, basic_format_context<_Out, _CharT>&
>>> __fc) const
>>>         {
>>>           using _Range = remove_reference_t<_Rg>;
>>> @@ -1482,6 +1489,25 @@ namespace __format
>>>        _Spec<_CharT> _M_spec{};
>>>      };
>>>
>>> +  [[__gnu__::__always_inline__]]
>>> +  constexpr char
>>> +  __toupper(char __c)
>>> +  {
>>> +    switch (__c)
>>> +    {
>>> +      case 'a': return 'A';
>>> +      case 'b': return 'B';
>>> +      case 'c': return 'C';
>>> +      case 'd': return 'D';
>>> +      case 'e': return 'E';
>>> +      case 'f': return 'F';
>>> +      case 'i': return 'I';
>>> +      case 'n': return 'N';
>>> +      case 'p': return 'P';
>>> +      default: return __c;
>>> +    }
>>> +  }
>>> +
>>>    template<__char _CharT>
>>>      struct __formatter_int
>>>      {
>>> @@ -1641,6 +1667,7 @@ namespace __format
>>>         }
>>>
>>>        template<typename _Int, typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         format(_Int __i, basic_format_context<_Out, _CharT>& __fc) const
>>>         {
>>> @@ -1689,11 +1716,7 @@ namespace __format
>>>               __res = to_chars(__start, __end, __u, 16);
>>>               if (_M_spec._M_type == _Pres_X)
>>>                 for (auto __p = __start; __p != __res.ptr; ++__p)
>>> -#if __has_builtin(__builtin_toupper)
>>> -                 *__p = __builtin_toupper(*__p);
>>> -#else
>>> -                 *__p = std::toupper(*__p);
>>> -#endif
>>> +                 *__p = __format::__toupper(*__p);
>>>               break;
>>>             default:
>>>               __builtin_unreachable();
>>> @@ -1702,8 +1725,7 @@ namespace __format
>>>           if (_M_spec._M_alt && __base_prefix.size())
>>>             {
>>>               __start -= __base_prefix.size();
>>> -             __builtin_memcpy(__start, __base_prefix.data(),
>>> -                              __base_prefix.size());
>>> +             ranges::copy(__base_prefix, __start);
>>>             }
>>>           __start = __format::__put_sign(__i, _M_spec._M_sign, __start -
>>> 1);
>>>
>>> @@ -1712,6 +1734,7 @@ namespace __format
>>>         }
>>>
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         format(bool __i, basic_format_context<_Out, _CharT>& __fc) const
>>>         {
>>> @@ -1742,6 +1765,7 @@ namespace __format
>>>         }
>>>
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         _M_format_character(_CharT __c,
>>>                             basic_format_context<_Out, _CharT>& __fc)
>>> const
>>> @@ -1773,7 +1797,7 @@ namespace __format
>>>         }
>>>
>>>        template<typename _Int>
>>> -       static _CharT
>>> +       static _GLIBCXX26_CONSTEXPR _CharT
>>>         _S_to_character(_Int __i)
>>>         {
>>>           using _Traits = __gnu_cxx::__int_traits<_CharT>;
>>> @@ -1794,6 +1818,7 @@ namespace __format
>>>         }
>>>
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         _M_format_int(string_view __narrow_str, size_t __prefix_len,
>>>                       basic_format_context<_Out, _CharT>& __fc) const
>>> @@ -2068,6 +2093,7 @@ namespace __format
>>>        }
>>>
>>>        template<typename _Fp, typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         format(_Fp __v, basic_format_context<_Out, _CharT>& __fc) const
>>>         {
>>> @@ -2197,7 +2223,7 @@ namespace __format
>>>           if (__upper)
>>>             {
>>>               for (char* __p = __start; __p != __res.ptr; ++__p)
>>> -               *__p = std::toupper(*__p);
>>> +               *__p = __format::__toupper(*__p);
>>>             }
>>>
>>>           bool __have_sign = true;
>>> @@ -2502,10 +2528,15 @@ namespace __format
>>>        }
>>>
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         format(const void* __v, basic_format_context<_Out, _CharT>&
>>> __fc) const
>>>         {
>>> -         auto __u = reinterpret_cast<__UINTPTR_TYPE__>(__v);
>>> +         // Treating nullptr specially
>>> +         // to enable constexpr formatting of nullptr_t.
>>> +         auto __u = __v
>>> +           ? reinterpret_cast<__UINTPTR_TYPE__>(__v)
>>> +           : (__UINTPTR_TYPE__)0;
>>>           char __buf[2 + sizeof(__v) * 2];
>>>           auto [__ptr, __ec] = std::to_chars(__buf + 2, std::end(__buf),
>>>                                              __u, 16);
>>> @@ -2517,11 +2548,7 @@ namespace __format
>>>             {
>>>               __buf[1] = 'X';
>>>               for (auto __p = __buf + 2; __p != __ptr; ++__p)
>>> -#if __has_builtin(__builtin_toupper)
>>> -               *__p = __builtin_toupper(*__p);
>>> -#else
>>> -               *__p = std::toupper(*__p);
>>> -#endif
>>> +               *__p = __format::__toupper(*__p);
>>>             }
>>>  #endif
>>>
>>> @@ -2590,6 +2617,7 @@ namespace __format
>>>        }
>>>
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         format(_CharT __u, basic_format_context<_Out, _CharT>& __fc)
>>> const
>>>         {
>>> @@ -2628,6 +2656,7 @@ namespace __format
>>>        }
>>>
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, wchar_t>::iterator
>>>         format(char __u, basic_format_context<_Out, wchar_t>& __fc) const
>>>         {
>>> @@ -2663,6 +2692,7 @@ namespace __format
>>>
>>>        template<typename _Out>
>>>         [[__gnu__::__nonnull__]]
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         format(_CharT* __u, basic_format_context<_Out, _CharT>& __fc)
>>> const
>>>         { return _M_f.format(__u, __fc); }
>>> @@ -2692,6 +2722,7 @@ namespace __format
>>>
>>>        template<typename _Out>
>>>         [[__gnu__::__nonnull__]]
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         format(const _CharT* __u,
>>>                basic_format_context<_Out, _CharT>& __fc) const
>>> @@ -2722,6 +2753,7 @@ namespace __format
>>>        { return _M_f.parse(__pc); }
>>>
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         format(const _CharT (&__u)[_Nm],
>>>                basic_format_context<_Out, _CharT>& __fc) const
>>> @@ -2751,6 +2783,7 @@ namespace __format
>>>        { return _M_f.parse(__pc); }
>>>
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, char>::iterator
>>>         format(const basic_string<char, _Traits, _Alloc>& __u,
>>>                basic_format_context<_Out, char>& __fc) const
>>> @@ -2783,6 +2816,7 @@ namespace __format
>>>        { return _M_f.parse(__pc); }
>>>
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, wchar_t>::iterator
>>>         format(const basic_string<wchar_t, _Traits, _Alloc>& __u,
>>>                basic_format_context<_Out, wchar_t>& __fc) const
>>> @@ -2816,6 +2850,7 @@ namespace __format
>>>        { return _M_f.parse(__pc); }
>>>
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, char>::iterator
>>>         format(basic_string_view<char, _Traits> __u,
>>>                basic_format_context<_Out, char>& __fc) const
>>> @@ -2848,6 +2883,7 @@ namespace __format
>>>        { return _M_f.parse(__pc); }
>>>
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, wchar_t>::iterator
>>>         format(basic_string_view<wchar_t, _Traits> __u,
>>>                basic_format_context<_Out, wchar_t>& __fc) const
>>> @@ -2911,6 +2947,7 @@ namespace __format
>>>        }
>>>
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         format(_Tp __u, basic_format_context<_Out, _CharT>& __fc) const
>>>         { return _M_f.format(__u, __fc); }
>>> @@ -3122,6 +3159,7 @@ namespace __format
>>>        { return _M_f.parse(__pc); }
>>>
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         format(const void* __v, basic_format_context<_Out, _CharT>&
>>> __fc) const
>>>         { return _M_f.format(__v, __fc); }
>>> @@ -3147,6 +3185,7 @@ namespace __format
>>>        { return _M_f.parse(__pc); }
>>>
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         format(void* __v, basic_format_context<_Out, _CharT>& __fc) const
>>>         { return _M_f.format(__v, __fc); }
>>> @@ -3172,6 +3211,7 @@ namespace __format
>>>        { return _M_f.parse(__pc); }
>>>
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         format(nullptr_t, basic_format_context<_Out, _CharT>& __fc) const
>>>         { return _M_f.format(nullptr, __fc); }
>>> @@ -3316,11 +3356,11 @@ namespace __format
>>>        constexpr _Sink_iter
>>>        operator++(int) { return *this; }
>>>
>>> -      auto
>>> +      _GLIBCXX26_CONSTEXPR auto
>>>        _M_reserve(size_t __n) const
>>>        { return _M_sink->_M_reserve(__n); }
>>>
>>> -      bool
>>> +      _GLIBCXX26_CONSTEXPR bool
>>>        _M_discarding() const
>>>        { return _M_sink->_M_discarding(); }
>>>      };
>>> @@ -3352,7 +3392,7 @@ namespace __format
>>>
>>>        // The portion of the span that has been written to.
>>>        [[__gnu__::__always_inline__]]
>>> -      span<_CharT>
>>> +      _GLIBCXX26_CONSTEXPR span<_CharT>
>>>        _M_used() const noexcept
>>>        { return _M_span.first(_M_next - _M_span.begin()); }
>>>
>>> @@ -3369,7 +3409,7 @@ namespace __format
>>>        { _M_next = _M_span.begin(); }
>>>
>>>        // Replace the current output range.
>>> -      void
>>> +      _GLIBCXX26_CONSTEXPR void
>>>        _M_reset(span<_CharT> __s, size_t __pos = 0) noexcept
>>>        {
>>>         _M_span = __s;
>>> @@ -3409,11 +3449,14 @@ namespace __format
>>>        struct _Reservation
>>>        {
>>>         // True if the reservation was successful, false otherwise.
>>> +       _GLIBCXX26_CONSTEXPR
>>>         explicit operator bool() const noexcept { return _M_sink; }
>>>         // A pointer to write directly to the sink.
>>> -       _CharT* get() const noexcept { return
>>> _M_sink->_M_next.operator->(); }
>>> +       _GLIBCXX26_CONSTEXPR _CharT*
>>> +       get() const noexcept { return _M_sink->_M_next.operator->(); }
>>>         // Add n to the _M_next iterator for the sink.
>>> -       void _M_bump(size_t __n) { _M_sink->_M_bump(__n); }
>>> +       _GLIBCXX26_CONSTEXPR void
>>> +       _M_bump(size_t __n) { _M_sink->_M_bump(__n); }
>>>         _Sink* _M_sink;
>>>        };
>>>
>>> @@ -3421,7 +3464,7 @@ namespace __format
>>>        // If anything is written to the reservation then there must be a
>>> call
>>>        // to _M_bump(N2) before any call to another member function of
>>> *this,
>>>        // where N2 is the number of characters written.
>>> -      virtual _Reservation
>>> +      _GLIBCXX26_CONSTEXPR virtual _Reservation
>>>        _M_reserve(size_t __n)
>>>        {
>>>         if (__n <= _M_unused().size())
>>> @@ -3438,12 +3481,12 @@ namespace __format
>>>
>>>        // Update the next output position after writing directly to the
>>> sink.
>>>        // pre: no calls to _M_write or _M_overflow since _M_reserve.
>>> -      virtual void
>>> +      _GLIBCXX26_CONSTEXPR virtual void
>>>        _M_bump(size_t __n)
>>>        { _M_next += __n; }
>>>
>>>        // Returns true if the _Sink is discarding incoming characters.
>>> -      virtual bool
>>> +      _GLIBCXX26_CONSTEXPR virtual bool
>>>        _M_discarding() const
>>>        { return false; }
>>>
>>> @@ -3461,7 +3504,7 @@ namespace __format
>>>    template<typename _CharT>
>>>      class _Fixedbuf_sink final : public _Sink<_CharT>
>>>      {
>>> -      void
>>> +      _GLIBCXX26_CONSTEXPR void
>>>        _M_overflow() override
>>>        {
>>>         __glibcxx_assert(false);
>>> @@ -3509,7 +3552,7 @@ namespace __format
>>>        _Seq _M_seq;
>>>      protected:
>>>        // Transfer buffer contents to the sequence, so buffer can be
>>> refilled.
>>> -      void
>>> +      _GLIBCXX26_CONSTEXPR void
>>>        _M_overflow() override
>>>        {
>>>         auto __s = this->_M_used();
>>> @@ -3528,7 +3571,7 @@ namespace __format
>>>         this->_M_rewind();
>>>        }
>>>
>>> -      typename _Sink<_CharT>::_Reservation
>>> +      _GLIBCXX26_CONSTEXPR typename _Sink<_CharT>::_Reservation
>>>        _M_reserve(size_t __n) override
>>>        {
>>>         // We might already have n characters available in
>>> this->_M_unused(),
>>> @@ -3564,7 +3607,7 @@ namespace __format
>>>           return _Sink<_CharT>::_M_reserve(__n);
>>>        }
>>>
>>> -      void
>>> +      _GLIBCXX26_CONSTEXPR void
>>>        _M_bump(size_t __n) override
>>>        {
>>>         if constexpr (__is_specialization_of<_Seq, basic_string>
>>> @@ -3579,7 +3622,8 @@ namespace __format
>>>           }
>>>        }
>>>
>>> -      void _M_trim(span<const _CharT> __s)
>>> +      _GLIBCXX26_CONSTEXPR void
>>> +      _M_trim(span<const _CharT> __s)
>>>         requires __is_specialization_of<_Seq, basic_string>
>>>        {
>>>         _GLIBCXX_DEBUG_ASSERT(__s.data() == this->_M_buf
>>> @@ -3595,16 +3639,18 @@ namespace __format
>>>        // to _M_buf if it overflows? Or even do that for all unused
>>> capacity?
>>>
>>>        [[__gnu__::__always_inline__]]
>>> +      _GLIBCXX26_CONSTEXPR
>>>        _Seq_sink() noexcept(is_nothrow_default_constructible_v<_Seq>)
>>>        { }
>>>
>>> +      _GLIBCXX26_CONSTEXPR
>>>        _Seq_sink(_Seq&& __s)
>>> noexcept(is_nothrow_move_constructible_v<_Seq>)
>>>        : _M_seq(std::move(__s))
>>>        { }
>>>
>>>        using _Sink<_CharT>::out;
>>>
>>> -      _Seq
>>> +      _GLIBCXX26_CONSTEXPR _Seq
>>>        get() &&
>>>        {
>>>         if (this->_M_used().size() != 0)
>>> @@ -3614,7 +3660,7 @@ namespace __format
>>>
>>>        // A writable span that views everything written to the sink.
>>>        // Will be either a view over _M_seq or the used part of _M_buf.
>>> -      span<_CharT>
>>> +      _GLIBCXX26_CONSTEXPR span<_CharT>
>>>        _M_span()
>>>        {
>>>         auto __s = this->_M_used();
>>> @@ -3627,7 +3673,7 @@ namespace __format
>>>         return __s;
>>>        }
>>>
>>> -      basic_string_view<_CharT>
>>> +      _GLIBCXX26_CONSTEXPR basic_string_view<_CharT>
>>>        view()
>>>        {
>>>         auto __span = _M_span();
>>> @@ -3652,7 +3698,7 @@ namespace __format
>>>      protected:
>>>        size_t _M_count = 0;
>>>
>>> -      void
>>> +      _GLIBCXX26_CONSTEXPR void
>>>        _M_overflow() override
>>>        {
>>>         auto __s = this->_M_used();
>>> @@ -3672,7 +3718,7 @@ namespace __format
>>>         _M_count += __s.size();
>>>        }
>>>
>>> -      bool
>>> +      _GLIBCXX26_CONSTEXPR bool
>>>        _M_discarding() const override
>>>        {
>>>         // format_to_n return total number of characters, that would be
>>> written,
>>> @@ -3682,14 +3728,14 @@ namespace __format
>>>
>>>      public:
>>>        [[__gnu__::__always_inline__]]
>>> -      explicit
>>> +      _GLIBCXX26_CONSTEXPR explicit
>>>        _Iter_sink(_OutIter __out, iter_difference_t<_OutIter> __max = -1)
>>>        : _M_out(std::move(__out)), _M_max(__max)
>>>        { }
>>>
>>>        using _Sink<_CharT>::out;
>>>
>>> -      format_to_n_result<_OutIter>
>>> +      _GLIBCXX26_CONSTEXPR format_to_n_result<_OutIter>
>>>        _M_finish() &&
>>>        {
>>>         if (this->_M_used().size() != 0)
>>> @@ -3718,7 +3764,7 @@ namespace __format
>>>        _CharT _M_buf[64]; // Write here after outputting _M_max
>>> characters.
>>>
>>>      protected:
>>> -      void
>>> +      _GLIBCXX26_CONSTEXPR void
>>>        _M_overflow() override
>>>        {
>>>         if (this->_M_unused().size() != 0)
>>> @@ -3742,7 +3788,7 @@ namespace __format
>>>           }
>>>        }
>>>
>>> -      bool
>>> +      _GLIBCXX26_CONSTEXPR bool
>>>        _M_discarding() const override
>>>        {
>>>         // format_to_n return total number of characters, that would be
>>> written,
>>> @@ -3750,7 +3796,7 @@ namespace __format
>>>         return false;
>>>        }
>>>
>>> -      typename _Sink<_CharT>::_Reservation
>>> +      _GLIBCXX26_CONSTEXPR typename _Sink<_CharT>::_Reservation
>>>        _M_reserve(size_t __n) final
>>>        {
>>>         auto __avail = this->_M_unused();
>>> @@ -3767,7 +3813,7 @@ namespace __format
>>>
>>>      private:
>>>        template<typename _IterDifference>
>>> -       static size_t
>>> +       static _GLIBCXX26_CONSTEXPR size_t
>>>         _S_trim_max(_IterDifference __max)
>>>         {
>>>           if (__max < 0)
>>> @@ -3780,7 +3826,7 @@ namespace __format
>>>         }
>>>
>>>        [[__gnu__::__always_inline__]]
>>> -      void
>>> +      _GLIBCXX26_CONSTEXPR void
>>>        _M_rebuf(_CharT* __ptr, size_t __total, size_t __inuse = 0)
>>>        {
>>>         std::span<_CharT> __span(__ptr, __total);
>>> @@ -3788,7 +3834,7 @@ namespace __format
>>>        }
>>>
>>>      public:
>>> -      explicit
>>> +      _GLIBCXX26_CONSTEXPR explicit
>>>        _Ptr_sink(_CharT* __ptr, size_t __n = _S_no_limit) noexcept
>>>        : _Sink<_CharT>(_M_buf), _M_max(__n)
>>>        {
>>> @@ -3813,13 +3859,13 @@ namespace __format
>>>        }
>>>
>>>        template<contiguous_iterator _OutIter>
>>> -       explicit
>>> +       _GLIBCXX26_CONSTEXPR explicit
>>>         _Ptr_sink(_OutIter __out, iter_difference_t<_OutIter> __n = -1)
>>>         : _Ptr_sink(std::to_address(__out), _S_trim_max(__n))
>>>         { }
>>>
>>>        template<contiguous_iterator _OutIter>
>>> -       format_to_n_result<_OutIter>
>>> +       _GLIBCXX26_CONSTEXPR format_to_n_result<_OutIter>
>>>         _M_finish(_OutIter __first) const
>>>         {
>>>           auto __s = this->_M_used();
>>> @@ -3861,12 +3907,12 @@ namespace __format
>>>        size_t _M_printwidth;
>>>
>>>        [[__gnu__::__always_inline__]]
>>> -      bool
>>> +      _GLIBCXX26_CONSTEXPR bool
>>>        _M_ignoring() const
>>>        { return _M_printwidth >= _M_maxwidth; }
>>>
>>>        [[__gnu__::__always_inline__]]
>>> -      bool
>>> +      _GLIBCXX26_CONSTEXPR bool
>>>        _M_buffering() const
>>>        {
>>>         if (_M_printwidth < _M_padwidth)
>>> @@ -3876,7 +3922,7 @@ namespace __format
>>>         return false;
>>>        }
>>>
>>> -      void
>>> +      _GLIBCXX26_CONSTEXPR void
>>>        _M_sync_discarding()
>>>        {
>>>         if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
>>> @@ -3884,7 +3930,7 @@ namespace __format
>>>             _M_maxwidth = _M_printwidth;
>>>        }
>>>
>>> -      void
>>> +      _GLIBCXX26_CONSTEXPR void
>>>        _M_flush()
>>>        {
>>>         span<_CharT> __new = this->_M_used();
>>> @@ -3894,7 +3940,7 @@ namespace __format
>>>         this->_M_rewind();
>>>        }
>>>
>>> -      bool
>>> +      _GLIBCXX26_CONSTEXPR bool
>>>        _M_force_update()
>>>        {
>>>         auto __str = this->view();
>>> @@ -3922,7 +3968,7 @@ namespace __format
>>>         return false;
>>>        }
>>>
>>> -      bool
>>> +      _GLIBCXX26_CONSTEXPR bool
>>>        _M_update(size_t __new)
>>>        {
>>>         _M_printwidth += __new;
>>> @@ -3932,7 +3978,7 @@ namespace __format
>>>         return true;
>>>        }
>>>
>>> -      void
>>> +      _GLIBCXX26_CONSTEXPR void
>>>        _M_overflow() override
>>>        {
>>>         // Ignore characters in buffer, and override it.
>>> @@ -3947,11 +3993,11 @@ namespace __format
>>>           _Str_sink<_CharT>::_M_overflow();
>>>        }
>>>
>>> -      bool
>>> +      _GLIBCXX26_CONSTEXPR bool
>>>        _M_discarding() const override
>>>        { return _M_ignoring(); }
>>>
>>> -      typename _Sink<_CharT>::_Reservation
>>> +      _GLIBCXX26_CONSTEXPR typename _Sink<_CharT>::_Reservation
>>>        _M_reserve(size_t __n) override
>>>        {
>>>         // Ignore characters in buffer, if any.
>>> @@ -3970,7 +4016,7 @@ namespace __format
>>>         return _Sink<_CharT>::_M_reserve(__n);
>>>        }
>>>
>>> -      void
>>> +      _GLIBCXX26_CONSTEXPR void
>>>        _M_bump(size_t __n) override
>>>        {
>>>         // Ignore the written characters.
>>> @@ -3985,19 +4031,19 @@ namespace __format
>>>
>>>      public:
>>>        [[__gnu__::__always_inline__]]
>>> -      explicit
>>> +      _GLIBCXX26_CONSTEXPR explicit
>>>        _Padding_sink(_Out __out, size_t __padwidth, size_t __maxwidth)
>>>        : _M_padwidth(__padwidth), _M_maxwidth(__maxwidth),
>>>         _M_out(std::move(__out)), _M_printwidth(0)
>>>        { _M_sync_discarding(); }
>>>
>>>        [[__gnu__::__always_inline__]]
>>> -      explicit
>>> +      _GLIBCXX26_CONSTEXPR explicit
>>>        _Padding_sink(_Out __out, size_t __padwidth)
>>>        : _Padding_sink(std::move(__out), __padwidth, (size_t)-1)
>>>        { }
>>>
>>> -      _Out
>>> +      _GLIBCXX26_CONSTEXPR _Out
>>>        _M_finish(_Align __align, char32_t __fill_char)
>>>        {
>>>         // Handle any characters in the buffer.
>>> @@ -4036,14 +4082,14 @@ namespace __format
>>>        unsigned _M_prev_escape : 1;
>>>        unsigned _M_out_discards : 1;
>>>
>>> -      void
>>> +      _GLIBCXX26_CONSTEXPR void
>>>        _M_sync_discarding()
>>>        {
>>>         if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
>>>           _M_out_discards = _M_out._M_discarding();
>>>        }
>>>
>>> -      void
>>> +      _GLIBCXX26_CONSTEXPR void
>>>        _M_write()
>>>        {
>>>         span<_CharT> __bytes = this->_M_used();
>>> @@ -4069,7 +4115,7 @@ namespace __format
>>>         _M_sync_discarding();
>>>        }
>>>
>>> -      void
>>> +      _GLIBCXX26_CONSTEXPR void
>>>        _M_overflow() override
>>>        {
>>>         if (_M_out_discards)
>>> @@ -4078,13 +4124,13 @@ namespace __format
>>>           _M_write();
>>>        }
>>>
>>> -      bool
>>> +      _GLIBCXX26_CONSTEXPR bool
>>>        _M_discarding() const override
>>>        { return _M_out_discards; }
>>>
>>>      public:
>>>        [[__gnu__::__always_inline__]]
>>> -      explicit
>>> +      _GLIBCXX26_CONSTEXPR explicit
>>>        _Escaping_sink(_Out __out, _Term_char __term)
>>>        : _M_out(std::move(__out)), _M_term(__term),
>>>         _M_prev_escape(true), _M_out_discards(false)
>>> @@ -4093,7 +4139,7 @@ namespace __format
>>>         _M_sync_discarding();
>>>        }
>>>
>>> -      _Out
>>> +      _GLIBCXX26_CONSTEXPR _Out
>>>        _M_finish()
>>>        {
>>>         if (_M_out_discards)
>>> @@ -4141,7 +4187,7 @@ namespace __format
>>>                             const _Tp, _Tp>;
>>>
>>>        template<typename _Tq>
>>> -       static void
>>> +       static _GLIBCXX26_CONSTEXPR void
>>>         _S_format(basic_format_parse_context<_CharT>& __parse_ctx,
>>>                   _Context& __format_ctx, const void* __ptr)
>>>         {
>>> @@ -4154,7 +4200,7 @@ namespace __format
>>>
>>>        template<typename _Tp>
>>>         requires (!is_same_v<remove_cv_t<_Tp>, _Handle>)
>>> -       explicit
>>> +       _GLIBCXX26_CONSTEXPR explicit
>>>         _Handle(_Tp& __val) noexcept
>>>         : _M_ptr(__builtin_addressof(__val))
>>>         , _M_func(&_S_format<__maybe_const_t<_Tp>>)
>>> @@ -4169,7 +4215,7 @@ namespace __format
>>>        _Handle& operator=(const _Handle&) = default;
>>>
>>>        [[__gnu__::__always_inline__]]
>>> -      void
>>> +      _GLIBCXX26_CONSTEXPR void
>>>        format(basic_format_parse_context<_CharT>& __pc, _Context& __fc)
>>> const
>>>        { _M_func(__pc, __fc, this->_M_ptr); }
>>>
>>> @@ -4226,10 +4272,12 @@ namespace __format
>>>        };
>>>
>>>        [[__gnu__::__always_inline__]]
>>> +      _GLIBCXX26_CONSTEXPR
>>>        _Arg_value() : _M_none() { }
>>>
>>>  #if 0
>>>        template<typename _Tp>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         _Arg_value(in_place_type_t<_Tp>, _Tp __val)
>>>         { _S_get<_Tp>() = __val; }
>>>  #endif
>>> @@ -4238,7 +4286,7 @@ namespace __format
>>>        // Value of second argument (if provided), is assigned to that
>>> member.
>>>        template<typename _Tp, typename _Self, typename... _Value>
>>>         [[__gnu__::__always_inline__]]
>>> -       static auto&
>>> +       static _GLIBCXX26_CONSTEXPR auto&
>>>         _S_access(_Self& __u, _Value... __value) noexcept
>>>         {
>>>           static_assert(sizeof...(_Value) <= 1);
>>> @@ -4302,23 +4350,24 @@ namespace __format
>>>           else if constexpr (is_same_v<_Tp, _Handle<_Context>>)
>>>             return (__u._M_handle = ... = __value);
>>>           // Otherwise, ill-formed.
>>> +         __builtin_unreachable();
>>>         }
>>>
>>>        template<typename _Tp>
>>>         [[__gnu__::__always_inline__]]
>>> -       auto&
>>> +       _GLIBCXX26_CONSTEXPR auto&
>>>         _M_get() noexcept
>>>         { return _S_access<_Tp>(*this); }
>>>
>>>        template<typename _Tp>
>>>         [[__gnu__::__always_inline__]]
>>> -       const auto&
>>> +       _GLIBCXX26_CONSTEXPR const auto&
>>>         _M_get() const noexcept
>>>         { return _S_access<_Tp>(*this); }
>>>
>>>        template<typename _Tp>
>>>         [[__gnu__::__always_inline__]]
>>> -       void
>>> +       _GLIBCXX26_CONSTEXPR void
>>>         _M_set(_Tp __v) noexcept
>>>         {
>>>           if constexpr (is_same_v<_Tp, basic_string_view<_CharT>>)
>>> @@ -4335,7 +4384,8 @@ namespace __format
>>>      class _Arg_store;
>>>
>>>    template<typename _Visitor, typename _Ctx>
>>> -    decltype(auto) __visit_format_arg(_Visitor&&,
>>> basic_format_arg<_Ctx>);
>>> +    _GLIBCXX26_CONSTEXPR decltype(auto)
>>> +    __visit_format_arg(_Visitor&&, basic_format_arg<_Ctx>);
>>>
>>>    template<typename _Ch, typename _Tp>
>>>      consteval _Arg_t
>>> @@ -4351,20 +4401,21 @@ namespace __format
>>>      public:
>>>        using handle = __format::_Handle<_Context>;
>>>        [[__gnu__::__always_inline__]]
>>> +      _GLIBCXX26_CONSTEXPR
>>>        basic_format_arg() noexcept : _M_type(__format::_Arg_none) { }
>>>
>>>        [[nodiscard,__gnu__::__always_inline__]]
>>> -      explicit operator bool() const noexcept
>>> +      explicit _GLIBCXX26_CONSTEXPR operator bool() const noexcept
>>>        { return _M_type != __format::_Arg_none; }
>>>
>>>  #if __cpp_lib_format >= 202306L // >= C++26
>>>        template<typename _Visitor>
>>> -       decltype(auto)
>>> +       _GLIBCXX26_CONSTEXPR decltype(auto)
>>>         visit(this basic_format_arg __arg, _Visitor&& __vis)
>>>         { return __arg._M_visit_user(std::forward<_Visitor>(__vis),
>>> __arg._M_type); }
>>>
>>>        template<typename _Res, typename _Visitor>
>>> -       _Res
>>> +       _GLIBCXX26_CONSTEXPR _Res
>>>         visit(this basic_format_arg __arg, _Visitor&& __vis)
>>>         { return __arg._M_visit_user(std::forward<_Visitor>(__vis),
>>> __arg._M_type); }
>>>  #endif
>>> @@ -4541,7 +4592,7 @@ namespace __format
>>>         }
>>>
>>>        template<typename _Tp>
>>> -       void
>>> +       _GLIBCXX26_CONSTEXPR void
>>>         _M_set(_Tp __v) noexcept
>>>         {
>>>           _M_type = _S_to_enum<_Tp>();
>>> @@ -4550,7 +4601,7 @@ namespace __format
>>>
>>>        template<typename _Tp>
>>>         requires __format::__formattable_with<_Tp, _Context>
>>> -       explicit
>>> +       _GLIBCXX26_CONSTEXPR explicit
>>>         basic_format_arg(_Tp& __v) noexcept
>>>         {
>>>           using _Td = _Normalize<_Tp>;
>>> @@ -4564,15 +4615,15 @@ namespace __format
>>>         }
>>>
>>>        template<typename _Ctx, typename... _Argz>
>>> -       friend auto
>>> +       friend _GLIBCXX26_CONSTEXPR auto
>>>         make_format_args(_Argz&...) noexcept;
>>>
>>>        template<typename _Visitor, typename _Ctx>
>>> -       friend decltype(auto)
>>> +       friend _GLIBCXX26_CONSTEXPR decltype(auto)
>>>         visit_format_arg(_Visitor&& __vis, basic_format_arg<_Ctx>);
>>>
>>>        template<typename _Visitor, typename _Ctx>
>>> -       friend decltype(auto)
>>> +       friend _GLIBCXX26_CONSTEXPR decltype(auto)
>>>         __format::__visit_format_arg(_Visitor&&, basic_format_arg<_Ctx>);
>>>
>>>        template<typename _Ch, typename _Tp>
>>> @@ -4580,7 +4631,7 @@ namespace __format
>>>         __format::__to_arg_t_enum() noexcept;
>>>
>>>        template<typename _Visitor>
>>> -       decltype(auto)
>>> +       _GLIBCXX26_CONSTEXPR decltype(auto)
>>>         _M_visit(_Visitor&& __vis, __format::_Arg_t __type)
>>>         {
>>>           using namespace __format;
>>> @@ -4655,7 +4706,7 @@ namespace __format
>>>         }
>>>
>>>        template<typename _Visitor>
>>> -       decltype(auto)
>>> +       _GLIBCXX26_CONSTEXPR decltype(auto)
>>>         _M_visit_user(_Visitor&& __vis, __format::_Arg_t __type)
>>>         {
>>>           return _M_visit([&__vis]<typename _Tp>(_Tp& __val) ->
>>> decltype(auto)
>>> @@ -4679,7 +4730,7 @@ namespace __format
>>>
>>>    template<typename _Visitor, typename _Context>
>>>      _GLIBCXX26_DEPRECATED_SUGGEST("std::basic_format_arg::visit")
>>> -    inline decltype(auto)
>>> +    inline _GLIBCXX26_CONSTEXPR decltype(auto)
>>>      visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg)
>>>      {
>>>        return __arg._M_visit_user(std::forward<_Visitor>(__vis),
>>> __arg._M_type);
>>> @@ -4689,7 +4740,7 @@ namespace __format
>>>  namespace __format
>>>  {
>>>    template<typename _Visitor, typename _Ctx>
>>> -    inline decltype(auto)
>>> +    inline _GLIBCXX26_CONSTEXPR decltype(auto)
>>>      __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Ctx> __arg)
>>>      {
>>>        return __arg._M_visit(std::forward<_Visitor>(__vis),
>>> __arg._M_type);
>>> @@ -4698,7 +4749,7 @@ namespace __format
>>>    struct _WidthPrecVisitor
>>>    {
>>>      template<typename _Tp>
>>> -      size_t
>>> +      _GLIBCXX26_CONSTEXPR size_t
>>>        operator()(_Tp& __arg) const
>>>        {
>>>         if constexpr (is_same_v<_Tp, monostate>)
>>> @@ -4724,7 +4775,7 @@ namespace __format
>>>  #pragma GCC diagnostic push
>>>  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
>>>    template<typename _Context>
>>> -    inline size_t
>>> +    inline _GLIBCXX26_CONSTEXPR size_t
>>>      __int_from_arg(const basic_format_arg<_Context>& __arg)
>>>      { return __format::__visit_format_arg(_WidthPrecVisitor(), __arg); }
>>>
>>> @@ -4772,11 +4823,11 @@ namespace __format
>>>         const _Format_arg* _M_args;       // Active when _M_packed_size
>>> == 0
>>>        };
>>>
>>> -      size_t
>>> +      _GLIBCXX26_CONSTEXPR size_t
>>>        _M_size() const noexcept
>>>        { return _M_packed_size ? _M_packed_size : _M_unpacked_size; }
>>>
>>> -      typename __format::_Arg_t
>>> +      _GLIBCXX26_CONSTEXPR typename __format::_Arg_t
>>>        _M_type(size_t __i) const noexcept
>>>        {
>>>         uint64_t __t = _M_unpacked_size >> (__i * _S_packed_type_bits);
>>> @@ -4784,7 +4835,7 @@ namespace __format
>>>        }
>>>
>>>        template<typename _Ctx, typename... _Args>
>>> -       friend auto
>>> +       friend _GLIBCXX26_CONSTEXPR auto
>>>         make_format_args(_Args&...) noexcept;
>>>
>>>        // An array of _Arg_t enums corresponding to _Args...
>>> @@ -4795,10 +4846,11 @@ namespace __format
>>>
>>>      public:
>>>        template<typename... _Args>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         basic_format_args(const _Store<_Args...>& __store) noexcept;
>>>
>>>        [[nodiscard,__gnu__::__always_inline__]]
>>> -      basic_format_arg<_Context>
>>> +      _GLIBCXX26_CONSTEXPR basic_format_arg<_Context>
>>>        get(size_t __i) const noexcept
>>>        {
>>>         basic_format_arg<_Context> __arg;
>>> @@ -4820,7 +4872,7 @@ namespace __format
>>>        -> basic_format_args<_Context>;
>>>
>>>    template<typename _Context, typename... _Args>
>>> -    auto
>>> +    _GLIBCXX26_CONSTEXPR auto
>>>      make_format_args(_Args&... __fmt_args) noexcept;
>>>
>>>    // An array of type-erased formatting arguments.
>>> @@ -4830,7 +4882,7 @@ namespace __format
>>>        friend std::basic_format_args<_Context>;
>>>
>>>        template<typename _Ctx, typename... _Argz>
>>> -       friend auto std::
>>> +       friend _GLIBCXX26_CONSTEXPR auto std::
>>>  #if _GLIBCXX_INLINE_VERSION
>>>         __8:: // Needed for PR c++/59256
>>>  #endif
>>> @@ -4849,7 +4901,7 @@ namespace __format
>>>        _Element_t _M_args[sizeof...(_Args)];
>>>
>>>        template<typename _Tp>
>>> -       static _Element_t
>>> +       static _GLIBCXX26_CONSTEXPR _Element_t
>>>         _S_make_elt(_Tp& __v)
>>>         {
>>>           using _Tq = remove_const_t<_Tp>;
>>> @@ -4875,6 +4927,7 @@ namespace __format
>>>        template<typename... _Tp>
>>>         requires (sizeof...(_Tp) == sizeof...(_Args))
>>>         [[__gnu__::__always_inline__]]
>>> +       _GLIBCXX26_CONSTEXPR
>>>         _Arg_store(_Tp&... __a) noexcept
>>>         : _M_args{_S_make_elt(__a)...}
>>>         { }
>>> @@ -4886,7 +4939,7 @@ namespace __format
>>>
>>>    template<typename _Context>
>>>      template<typename... _Args>
>>> -      inline
>>> +      inline _GLIBCXX26_CONSTEXPR
>>>        basic_format_args<_Context>::
>>>        basic_format_args(const _Store<_Args...>& __store) noexcept
>>>        {
>>> @@ -4920,7 +4973,7 @@ namespace __format
>>>    /// Capture formatting arguments for use by `std::vformat`.
>>>    template<typename _Context = format_context, typename... _Args>
>>>      [[nodiscard,__gnu__::__always_inline__]]
>>> -    inline auto
>>> +    inline _GLIBCXX26_CONSTEXPR auto
>>>      make_format_args(_Args&... __fmt_args) noexcept
>>>      {
>>>        using _Fmt_arg = basic_format_arg<_Context>;
>>> @@ -4933,7 +4986,7 @@ namespace __format
>>>    /// Capture formatting arguments for use by `std::vformat` (for wide
>>> output).
>>>    template<typename... _Args>
>>>      [[nodiscard,__gnu__::__always_inline__]]
>>> -    inline auto
>>> +    inline _GLIBCXX26_CONSTEXPR auto
>>>      make_wformat_args(_Args&... __args) noexcept
>>>      { return std::make_format_args<wformat_context>(__args...); }
>>>  #endif
>>> @@ -4942,13 +4995,13 @@ namespace __format
>>>  namespace __format
>>>  {
>>>    template<typename _Out, typename _CharT, typename _Context>
>>> -    _Out
>>> +    _GLIBCXX26_CONSTEXPR _Out
>>>      __do_vformat_to(_Out, basic_string_view<_CharT>,
>>>                     const basic_format_args<_Context>&,
>>>                     const locale* = nullptr);
>>>
>>>    template<typename _Out, typename _CharT>
>>> -    format_to_n_result<_Out>
>>> +    _GLIBCXX26_CONSTEXPR format_to_n_result<_Out>
>>>      __do_vformat_to_n(_Out, iter_difference_t<_Out>,
>>>                       basic_string_view<_CharT>,
>>>                       const type_identity_t<
>>> @@ -4982,11 +5035,13 @@ namespace __format
>>>        _Out _M_out;
>>>        __format::_Optional_locale _M_loc;
>>>
>>> +      _GLIBCXX26_CONSTEXPR
>>>        basic_format_context(basic_format_args<basic_format_context>
>>> __args,
>>>                            _Out __out)
>>>        : _M_args(__args), _M_out(std::move(__out))
>>>        { }
>>>
>>> +      _GLIBCXX26_CONSTEXPR
>>>        basic_format_context(basic_format_args<basic_format_context>
>>> __args,
>>>                            _Out __out, const std::locale& __loc)
>>>        : _M_args(__args), _M_out(std::move(__out)), _M_loc(__loc)
>>> @@ -4999,7 +5054,7 @@ namespace __format
>>>        basic_format_context& operator=(const basic_format_context&) =
>>> delete;
>>>
>>>        template<typename _Out2, typename _CharT2, typename _Context2>
>>> -       friend _Out2
>>> +       friend _GLIBCXX26_CONSTEXPR _Out2
>>>         __format::__do_vformat_to(_Out2, basic_string_view<_CharT2>,
>>>                                   const basic_format_args<_Context2>&,
>>>                                   const locale*);
>>> @@ -5015,7 +5070,7 @@ namespace __format
>>>         using formatter_type = formatter<_Tp, _CharT>;
>>>
>>>        [[nodiscard]]
>>> -      basic_format_arg<basic_format_context>
>>> +      _GLIBCXX26_CONSTEXPR basic_format_arg<basic_format_context>
>>>        arg(size_t __id) const noexcept
>>>        { return _M_args.get(__id); }
>>>
>>> @@ -5023,9 +5078,11 @@ namespace __format
>>>        std::locale locale() { return _M_loc.value(); }
>>>
>>>        [[nodiscard]]
>>> -      iterator out() { return std::move(_M_out); }
>>> +      _GLIBCXX26_CONSTEXPR iterator
>>> +      out() { return std::move(_M_out); }
>>>
>>> -      void advance_to(iterator __it) { _M_out = std::move(__it); }
>>> +      _GLIBCXX26_CONSTEXPR void
>>> +      advance_to(iterator __it) { _M_out = std::move(__it); }
>>>      };
>>>
>>>
>>> @@ -5164,6 +5221,7 @@ namespace __format
>>>      class _Formatting_scanner : public _Scanner<_CharT>
>>>      {
>>>      public:
>>> +      _GLIBCXX26_CONSTEXPR
>>>        _Formatting_scanner(basic_format_context<_Out, _CharT>& __fc,
>>>                           basic_string_view<_CharT> __str)
>>>        : _Scanner<_CharT>(__str), _M_fc(__fc)
>>> @@ -5271,7 +5329,7 @@ namespace __format
>>>      };
>>>
>>>    template<typename _Out, typename _CharT, typename _Context>
>>> -    inline _Out
>>> +    inline _GLIBCXX26_CONSTEXPR _Out
>>>      __do_vformat_to(_Out __out, basic_string_view<_CharT> __fmt,
>>>                     const basic_format_args<_Context>& __args,
>>>                     const locale* __loc)
>>> @@ -5291,7 +5349,7 @@ namespace __format
>>>                       const char* __chars[] = { "false", "true" };
>>>                       if (auto __res = __out._M_reserve(__len))
>>>                         {
>>> -                         __builtin_memcpy(__res.get(), __chars[__arg],
>>> __len);
>>> +                         ranges::copy_n(__chars[__arg], __len,
>>> __res.get());
>>>                           __res._M_bump(__len);
>>>                           __done = true;
>>>                         }
>>> @@ -5329,7 +5387,7 @@ namespace __format
>>>                       string_view __sv = __arg;
>>>                       if (auto __res = __out._M_reserve(__sv.size()))
>>>                         {
>>> -                         __builtin_memcpy(__res.get(), __sv.data(),
>>> __sv.size());
>>> +                         ranges::copy(__sv, __res.get());
>>>                           __res._M_bump(__sv.size());
>>>                           __done = true;
>>>                         }
>>> @@ -5347,14 +5405,16 @@ namespace __format
>>>           __scanner._M_scan();
>>>           return __out;
>>>         }
>>> -      else if constexpr (__contiguous_char_iter<_CharT, _Out>)
>>> -       {
>>> -         _Ptr_sink<_CharT> __sink(__out);
>>> -         __format::__do_vformat_to(__sink.out(), __fmt, __args, __loc);
>>> -         return std::move(__sink)._M_finish(__out).out;
>>> -       }
>>>        else
>>>         {
>>> +         if constexpr (__contiguous_char_iter<_CharT, _Out>)
>>> +           if (!std::is_constant_evaluated())
>>> +             {
>>> +               _Ptr_sink<_CharT> __sink(__out);
>>> +               __format::__do_vformat_to(__sink.out(), __fmt, __args,
>>> __loc);
>>> +               return std::move(__sink)._M_finish(__out).out;
>>> +             }
>>> +
>>>           _Iter_sink<_CharT, _Out> __sink(std::move(__out));
>>>           __format::__do_vformat_to(__sink.out(), __fmt, __args, __loc);
>>>           return std::move(__sink)._M_finish().out;
>>> @@ -5362,7 +5422,7 @@ namespace __format
>>>      }
>>>
>>>    template<typename _Out, typename _CharT>
>>> -    format_to_n_result<_Out>
>>> +    _GLIBCXX26_CONSTEXPR format_to_n_result<_Out>
>>>      __do_vformat_to_n(_Out __out, iter_difference_t<_Out> __n,
>>>                       basic_string_view<_CharT> __fmt,
>>>                       const type_identity_t<
>>> @@ -5402,7 +5462,11 @@ namespace __format
>>>         if constexpr (sizeof...(_Ts) != 0)
>>>           {
>>>             using _Parse_ctx =
>>> __format::_Scanner<_CharT>::_Parse_context;
>>> -           auto __arg = static_cast<_Parse_ctx*>(this)->_M_types[__id];
>>> +           auto* __args = static_cast<_Parse_ctx*>(this)->_M_types;
>>> +           // formatting scanner
>>> +           if (!__args)
>>> +             return;
>>> +           auto __arg = __args[__id];
>>>             __format::_Arg_t __types[] = {
>>>               __format::__to_arg_t_enum<_CharT, _Ts>()...
>>>             };
>>> @@ -5432,14 +5496,14 @@ namespace __format
>>>
>>>    template<typename _Out> requires output_iterator<_Out, const char&>
>>>      [[__gnu__::__always_inline__]]
>>> -    inline _Out
>>> +    inline _GLIBCXX26_CONSTEXPR _Out
>>>      vformat_to(_Out __out, string_view __fmt, format_args __args)
>>>      { return __format::__do_vformat_to(std::move(__out), __fmt,
>>> __args); }
>>>
>>>  #ifdef _GLIBCXX_USE_WCHAR_T
>>>    template<typename _Out> requires output_iterator<_Out, const wchar_t&>
>>>      [[__gnu__::__always_inline__]]
>>> -    inline _Out
>>> +    inline _GLIBCXX26_CONSTEXPR _Out
>>>      vformat_to(_Out __out, wstring_view __fmt, wformat_args __args)
>>>      { return __format::__do_vformat_to(std::move(__out), __fmt,
>>> __args); }
>>>  #endif
>>> @@ -5465,7 +5529,7 @@ namespace __format
>>>  #endif
>>>
>>>    [[nodiscard]]
>>> -  inline string
>>> +  inline _GLIBCXX26_CONSTEXPR string
>>>    vformat(string_view __fmt, format_args __args)
>>>    {
>>>      __format::_Str_sink<char> __buf;
>>> @@ -5475,7 +5539,7 @@ namespace __format
>>>
>>>  #ifdef _GLIBCXX_USE_WCHAR_T
>>>    [[nodiscard]]
>>> -  inline wstring
>>> +  inline _GLIBCXX26_CONSTEXPR wstring
>>>    vformat(wstring_view __fmt, wformat_args __args)
>>>    {
>>>      __format::_Str_sink<wchar_t> __buf;
>>> @@ -5506,14 +5570,14 @@ namespace __format
>>>
>>>    template<typename... _Args>
>>>      [[nodiscard]]
>>> -    inline string
>>> +    inline _GLIBCXX26_CONSTEXPR string
>>>      format(format_string<_Args...> __fmt, _Args&&... __args)
>>>      { return std::vformat(__fmt.get(),
>>> std::make_format_args(__args...)); }
>>>
>>>  #ifdef _GLIBCXX_USE_WCHAR_T
>>>    template<typename... _Args>
>>>      [[nodiscard]]
>>> -    inline wstring
>>> +    inline _GLIBCXX26_CONSTEXPR wstring
>>>      format(wformat_string<_Args...> __fmt, _Args&&... __args)
>>>      { return std::vformat(__fmt.get(),
>>> std::make_wformat_args(__args...)); }
>>>  #endif
>>> @@ -5542,7 +5606,7 @@ namespace __format
>>>
>>>    template<typename _Out, typename... _Args>
>>>      requires output_iterator<_Out, const char&>
>>> -    inline _Out
>>> +    inline _GLIBCXX26_CONSTEXPR _Out
>>>      format_to(_Out __out, format_string<_Args...> __fmt, _Args&&...
>>> __args)
>>>      {
>>>        return std::vformat_to(std::move(__out), __fmt.get(),
>>> @@ -5552,7 +5616,7 @@ namespace __format
>>>  #ifdef _GLIBCXX_USE_WCHAR_T
>>>    template<typename _Out, typename... _Args>
>>>      requires output_iterator<_Out, const wchar_t&>
>>> -    inline _Out
>>> +    inline _GLIBCXX26_CONSTEXPR _Out
>>>      format_to(_Out __out, wformat_string<_Args...> __fmt, _Args&&...
>>> __args)
>>>      {
>>>        return std::vformat_to(std::move(__out), __fmt.get(),
>>> @@ -5584,7 +5648,7 @@ namespace __format
>>>
>>>    template<typename _Out, typename... _Args>
>>>      requires output_iterator<_Out, const char&>
>>> -    inline format_to_n_result<_Out>
>>> +    inline _GLIBCXX26_CONSTEXPR format_to_n_result<_Out>
>>>      format_to_n(_Out __out, iter_difference_t<_Out> __n,
>>>                 format_string<_Args...> __fmt, _Args&&... __args)
>>>      {
>>> @@ -5596,7 +5660,7 @@ namespace __format
>>>  #ifdef _GLIBCXX_USE_WCHAR_T
>>>    template<typename _Out, typename... _Args>
>>>      requires output_iterator<_Out, const wchar_t&>
>>> -    inline format_to_n_result<_Out>
>>> +    inline _GLIBCXX26_CONSTEXPR format_to_n_result<_Out>
>>>      format_to_n(_Out __out, iter_difference_t<_Out> __n,
>>>                 wformat_string<_Args...> __fmt, _Args&&... __args)
>>>      {
>>> @@ -5638,10 +5702,11 @@ namespace __format
>>>      class _Counting_sink final : public _Ptr_sink<_CharT>
>>>      {
>>>      public:
>>> +      _GLIBCXX26_CONSTEXPR
>>>        _Counting_sink() : _Ptr_sink<_CharT>(nullptr, 0) { }
>>>
>>>        [[__gnu__::__always_inline__]]
>>> -      size_t
>>> +      _GLIBCXX26_CONSTEXPR size_t
>>>        count() const
>>>        { return this->_M_count + this->_M_used().size(); }
>>>      };
>>> @@ -5676,7 +5741,7 @@ namespace __format
>>>
>>>    template<typename... _Args>
>>>      [[nodiscard]]
>>> -    inline size_t
>>> +    inline _GLIBCXX26_CONSTEXPR size_t
>>>      formatted_size(format_string<_Args...> __fmt, _Args&&... __args)
>>>      {
>>>        __format::_Counting_sink<char> __buf;
>>> @@ -5688,7 +5753,7 @@ namespace __format
>>>  #ifdef _GLIBCXX_USE_WCHAR_T
>>>    template<typename... _Args>
>>>      [[nodiscard]]
>>> -    inline size_t
>>> +    inline _GLIBCXX26_CONSTEXPR size_t
>>>      formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args)
>>>      {
>>>        __format::_Counting_sink<wchar_t> __buf;
>>> @@ -5759,6 +5824,7 @@ namespace __format
>>>  namespace __format
>>>  {
>>>    template<typename _CharT, typename _Out, typename _Callback>
>>> +    _GLIBCXX26_CONSTEXPR
>>>      typename basic_format_context<_Out, _CharT>::iterator
>>>      __format_padded(basic_format_context<_Out, _CharT>& __fc,
>>>                     const _Spec<_CharT>& __spec,
>>> @@ -5778,14 +5844,16 @@ namespace __format
>>>
>>>           struct _Restore_out
>>>           {
>>> +          _GLIBCXX26_CONSTEXPR
>>>            _Restore_out(basic_format_context<_Sink_iter<_CharT>,
>>> _CharT>& __fc)
>>>            : _M_ctx(std::addressof(__fc)), _M_out(__fc.out())
>>>           { }
>>>
>>> -         void
>>> +         _GLIBCXX26_CONSTEXPR void
>>>           _M_disarm()
>>>           { _M_ctx = nullptr; }
>>>
>>> +         _GLIBCXX26_CONSTEXPR
>>>           ~_Restore_out()
>>>           {
>>>             if (_M_ctx)
>>> @@ -5819,7 +5887,7 @@ namespace __format
>>>        }
>>>
>>>        template<typename _Out>
>>> -       void
>>> +       _GLIBCXX26_CONSTEXPR void
>>>         _M_format(__maybe_const<_Tp, _CharT>& __elem,
>>>                   basic_format_context<_Out, _CharT>& __fc,
>>>                   basic_string_view<_CharT> __sep) const
>>> @@ -5917,12 +5985,14 @@ namespace __format
>>>
>>>      protected:
>>>        template<typename _Tuple, typename _Out, size_t... _Ids>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         _M_format(_Tuple& __tuple, index_sequence<_Ids...>,
>>>                   basic_format_context<_Out, _CharT>& __fc) const
>>>         { return _M_format_elems(std::get<_Ids>(__tuple)..., __fc); }
>>>
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         _M_format_elems(__maybe_const<_Tps, _CharT>&... __elems,
>>>                         basic_format_context<_Out, _CharT>& __fc) const
>>> @@ -5952,7 +6022,7 @@ namespace __format
>>>           }
>>>
>>>           template<typename _Out>
>>> -           void
>>> +           _GLIBCXX26_CONSTEXPR void
>>>             _M_format(__maybe_const<_Tps, _CharT>&... __elems,
>>>                       basic_format_context<_Out, _CharT>& __fc,
>>>                       _String_view __sep) const
>>> @@ -5968,7 +6038,7 @@ namespace __format
>>>         };
>>>
>>>        template<size_t... _Ids>
>>> -       static auto
>>> +       static _GLIBCXX26_CONSTEXPR auto
>>>         _S_create_storage(index_sequence<_Ids...>)
>>>           -> __formatters_storage<_Ids...>;
>>>        using _Formatters
>>> @@ -6004,6 +6074,7 @@ namespace __format
>>>        // We deviate from standard, that declares this as template
>>> accepting
>>>        // unconstrained FormatContext type, which seems unimplementable.
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         format(__maybe_const_pair& __p,
>>>                basic_format_context<_Out, _CharT>& __fc) const
>>> @@ -6031,6 +6102,7 @@ namespace __format
>>>        // We deviate from standard, that declares this as template
>>> accepting
>>>        // unconstrained FormatContext type, which seems unimplementable.
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         format(__maybe_const_tuple& __t,
>>>                basic_format_context<_Out, _CharT>& __fc) const
>>> @@ -6194,6 +6266,7 @@ namespace __format
>>>        template<ranges::input_range _Rg, typename _Out>
>>>         requires formattable<ranges::range_reference_t<_Rg>, _CharT> &&
>>>                  same_as<remove_cvref_t<ranges::range_reference_t<_Rg>>,
>>> _Tp>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         format(_Rg&& __rg, basic_format_context<_Out, _CharT>& __fc)
>>> const
>>>         {
>>> @@ -6206,6 +6279,7 @@ namespace __format
>>>
>>>      private:
>>>        template<ranges::input_range _Rg, typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         _M_format(_Rg& __rg, basic_format_context<_Out, _CharT>& __fc)
>>> const
>>>         {
>>> @@ -6223,6 +6297,7 @@ namespace __format
>>>
>>>
>>>        template<ranges::input_range _Rg, typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         _M_format_elems(_Rg& __rg,
>>>                         basic_format_context<_Out, _CharT>& __fc) const
>>> @@ -6322,6 +6397,7 @@ namespace __format
>>>        // We deviate from standard, that declares this as template
>>> accepting
>>>        // unconstrained FormatContext type, which seems unimplementable.
>>>        template<typename _Out>
>>> +       _GLIBCXX26_CONSTEXPR
>>>         typename basic_format_context<_Out, _CharT>::iterator
>>>         format(__format::__maybe_const_range<_Rg, _CharT>& __rg,
>>>                basic_format_context<_Out, _CharT>& __fc) const
>>> diff --git a/libstdc++-v3/testsuite/std/format/constexpr.cc
>>> b/libstdc++-v3/testsuite/std/format/constexpr.cc
>>> new file mode 100644
>>> index 00000000000..675641cdbcb
>>> --- /dev/null
>>> +++ b/libstdc++-v3/testsuite/std/format/constexpr.cc
>>> @@ -0,0 +1,126 @@
>>> +// { dg-do compile { target c++26 } }
>>> +
>>> +#include <format>
>>> +#include <string>
>>> +#include <string_view>
>>> +#include <tuple>
>>> +#include <vector>
>>> +#include <testsuite_hooks.h>
>>> +
>>> +constexpr void
>>> +test_format()
>>> +{
>>> +  using namespace std;
>>> +  string res;
>>> +
>>> +  res = format("{}", 'c');
>>> +  VERIFY( res == "c" );
>>> +  res = format("{1} {0} {0}", 'a', 'b');
>>> +  VERIFY( res == "b a a" );
>>> +  res = format("{:?}", '\n');
>>> +  VERIFY( res == "'\\n'" );
>>> +  res = format("{:.^10}", "hello");
>>> +  VERIFY( res == "..hello..." );
>>> +  res = format("{:.>{}}", "world", 8);
>>> +  VERIFY( res == "...world" );
>>> +  res = format("{:+#06X}", 0xa);
>>> +  VERIFY( res == "+0X00A" );
>>> +  res = format("{:p}", nullptr);
>>> +  VERIFY( res == "0x0" );
>>> +  res = format("{:07P}", nullptr);
>>> +  VERIFY( res == "0X00000" );
>>> +  res = format("{} {}", true, false);
>>> +  VERIFY( res == "true false" );
>>> +  res = format("{:+#06b}", true);
>>> +  VERIFY( res == "+0b001" );
>>> +  res = format("{} {} {} {}", "abc", +"def", string_view("ghi"),
>>> string("jkl"));
>>> +  VERIFY( res == "abc def ghi jkl" );
>>> +  res = format("{:?}", "hello\nworld");
>>> +  VERIFY( res == "\"hello\\nworld\"" );
>>> +  res = format("{}", tuple(1, true));
>>> +  VERIFY( res == "(1, true)" );
>>> +  res = format("{:t<12m}", tuple('a', "bc"));
>>> +  VERIFY( res == "'a': \"bc\"ttt" );
>>> +  res = format("{:n}", tuple(nullptr, -1, 1));
>>> +  VERIFY( res == "0x0, -1, 1" );
>>> +  res = format("{}", vector{1, 2, 3, 4});
>>> +  VERIFY( res == "[1, 2, 3, 4]" );
>>> +  res = format("{:?s}", vector{'a', '\n', 'b'});
>>> +  VERIFY( res == "\"a\\nb\"" );
>>> +  res = format("{:n:+}", vector{1, 2, 3});
>>> +  VERIFY( res == "+1, +2, +3" );
>>> +}
>>> +
>>> +constexpr void
>>> +test_format_to()
>>> +{
>>> +  using namespace std;
>>> +  char buf[100];
>>> +  char* out;
>>> +
>>> +  out = format_to(buf, "{:.^5}", "foo");
>>> +  VERIFY( string_view(buf, out) == ".foo." );
>>> +  out = format_to(buf, "{} {}", nullptr, true);
>>> +  VERIFY( string_view(buf, out) == "0x0 true" );
>>> +}
>>> +
>>> +constexpr void
>>> +test_vformat()
>>> +{
>>> +  using namespace std;
>>> +  string res;
>>> +
>>> +  int arg1 = 1;
>>> +  char arg2 = 'a';
>>> +  bool arg3 = true;
>>> +  res = vformat("{} {:?} {}", make_format_args(arg1, arg2, arg3));
>>> +  VERIFY( res == "1 'a' true" );
>>> +}
>>> +
>>> +constexpr void
>>> +test_vformat_to()
>>> +{
>>> +  using namespace std;
>>> +  char buf[100];
>>> +  char* out;
>>> +
>>> +  nullptr_t arg1 = nullptr;
>>> +  string arg2 = "foo";
>>> +  tuple<int, int> arg3{-3, 5};
>>> +  out = vformat_to(buf, "{} {:?} {}", make_format_args(arg1, arg2,
>>> arg3));
>>> +  VERIFY( string_view(buf, out) == "0x0 \"foo\" (-3, 5)" );
>>> +}
>>> +
>>> +constexpr void
>>> +test_format_to_n()
>>> +{
>>> +  using namespace std;
>>> +  char buf[100];
>>> +  format_to_n_result<char*> out;
>>> +  int n;
>>> +
>>> +  n = 100;
>>> +  out = format_to_n(buf, n, "{:+} {:?} {}", 1, "\n\n", vector{1, 2, 3});
>>> +  VERIFY( out.size <= n );
>>> +  VERIFY( out.out - buf == out.size );
>>> +  VERIFY( string_view(buf, out.size) == "+1 \"\\n\\n\" [1, 2, 3]" );
>>> +  n = 12;
>>> +  out = format_to_n(buf, n, "{} {} {}", true, nullptr, "long string");
>>> +  VERIFY( out.size > n );
>>> +  VERIFY( out.out - buf == n );
>>> +  VERIFY( string_view(buf, out.out) == "true 0x0 lon" );
>>> +}
>>> +
>>> +constexpr bool
>>> +all_tests()
>>> +{
>>> +  test_format();
>>> +  test_format_to();
>>> +  test_vformat();
>>> +  test_vformat_to();
>>> +  test_format_to_n();
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +static_assert(all_tests());
>>> diff --git a/libstdc++-v3/testsuite/std/format/debug.cc
>>> b/libstdc++-v3/testsuite/std/format/debug.cc
>>> index 43e930c579e..c45659d0d69 100644
>>> --- a/libstdc++-v3/testsuite/std/format/debug.cc
>>> +++ b/libstdc++-v3/testsuite/std/format/debug.cc
>>> @@ -1,14 +1,20 @@
>>> -// { dg-options "-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32LE
>>> -DUNICODE_ENC" { target le } }
>>> -// { dg-options "-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32BE
>>> -DUNICODE_ENC" { target be } }
>>> +// { dg-options "-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32LE
>>> -DUNICODE_ENC -fconstexpr-ops-limit=500000000" { target le } }
>>> +// { dg-options "-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32BE
>>> -DUNICODE_ENC -fconstexpr-ops-limit=500000000" { target be } }
>>>  // { dg-do run { target c++23 } }
>>>  // { dg-require-effective-target 4byte_wchar_t }
>>>  // { dg-add-options no_pch }
>>>  // { dg-timeout-factor 2 }
>>>
>>> +#if __cplusplus >= 202400L
>>> +# define constexpr26 constexpr
>>> +#else
>>> +# define constexpr26
>>> +#endif
>>> +
>>>  #include <format>
>>>  #include <testsuite_hooks.h>
>>>
>>> -std::string
>>> +constexpr26 std::string
>>>  fdebug(char t)
>>>  { return std::format("{:?}", t); }
>>>
>>> @@ -16,7 +22,7 @@ std::wstring
>>>  fdebug(wchar_t t)
>>>  { return std::format(L"{:?}", t); }
>>>
>>> -std::string
>>> +constexpr26 std::string
>>>  fdebug(std::string_view t)
>>>  { return std::format("{:?}", t); }
>>>
>>> @@ -29,7 +35,7 @@ fdebug(std::wstring_view t)
>>>  #define WIDEN(S) WIDEN_(CharT, S)
>>>
>>>  template<typename CharT>
>>> -void
>>> +constexpr26 void
>>>  test_basic_escapes()
>>>  {
>>>    std::basic_string<CharT> res;
>>> @@ -72,7 +78,7 @@ test_basic_escapes()
>>>  }
>>>
>>>  template<typename CharT>
>>> -void
>>> +constexpr26 void
>>>  test_ascii_escapes()
>>>  {
>>>    std::basic_string<CharT> res;
>>> @@ -89,7 +95,7 @@ test_ascii_escapes()
>>>  }
>>>
>>>  template<typename CharT>
>>> -void
>>> +constexpr26 void
>>>  test_extended_ascii()
>>>  {
>>>    std::basic_string<CharT> res;
>>> @@ -117,7 +123,7 @@ test_extended_ascii()
>>>  }
>>>
>>>  template<typename CharT>
>>> -void
>>> +constexpr26 void
>>>  test_unicode_escapes()
>>>  {
>>>  #if UNICODE_ENC
>>> @@ -166,7 +172,7 @@ test_unicode_escapes()
>>>  }
>>>
>>>  template<typename CharT>
>>> -void
>>> +constexpr26 void
>>>  test_grapheme_extend()
>>>  {
>>>  #if UNICODE_ENC
>>> @@ -192,7 +198,7 @@ test_grapheme_extend()
>>>  }
>>>
>>>  template<typename CharT>
>>> -void
>>> +constexpr26 void
>>>  test_replacement_char()
>>>  {
>>>  #if UNICODE_ENC
>>> @@ -206,7 +212,7 @@ test_replacement_char()
>>>  #endif // UNICODE_ENC
>>>  }
>>>
>>> -void
>>> +constexpr26 void
>>>  test_ill_formed_utf8_seq()
>>>  {
>>>  #if UNICODE_ENC
>>> @@ -269,7 +275,7 @@ test_ill_formed_utf32()
>>>  }
>>>
>>>  template<typename CharT>
>>> -void
>>> +constexpr26 void
>>>  test_fill()
>>>  {
>>>    std::basic_string<CharT> res;
>>> @@ -315,7 +321,7 @@ test_fill()
>>>  }
>>>
>>>  template<typename CharT>
>>> -void
>>> +constexpr26 void
>>>  test_prec()
>>>  {
>>>    std::basic_string<CharT> res;
>>> @@ -341,7 +347,8 @@ test_prec()
>>>  #endif // UNICODE_ENC
>>>  }
>>>
>>> -bool strip_quote(std::string_view& v)
>>> +constexpr26 bool
>>> +strip_quote(std::string_view& v)
>>>  {
>>>    if (!v.starts_with('"'))
>>>      return false;
>>> @@ -349,7 +356,8 @@ bool strip_quote(std::string_view& v)
>>>    return true;
>>>  }
>>>
>>> -bool strip_quotes(std::string_view& v)
>>> +constexpr26 bool
>>> +strip_quotes(std::string_view& v)
>>>  {
>>>    if (!v.starts_with('"') || !v.ends_with('"'))
>>>      return false;
>>> @@ -358,7 +366,8 @@ bool strip_quotes(std::string_view& v)
>>>    return true;
>>>  }
>>>
>>> -bool strip_prefix(std::string_view& v, size_t n, char c)
>>> +constexpr26 bool
>>> +strip_prefix(std::string_view& v, size_t n, char c)
>>>  {
>>>    size_t pos = v.find_first_not_of(c);
>>>    if (pos == std::string_view::npos)
>>> @@ -369,7 +378,8 @@ bool strip_prefix(std::string_view& v, size_t n,
>>> char c)
>>>    return true;
>>>  }
>>>
>>> -void test_padding()
>>> +constexpr26 void
>>> +test_padding()
>>>  {
>>>    std::string res;
>>>    std::string_view resv;
>>> @@ -751,8 +761,9 @@ struct std::formatter<DebugWrapper<T>, CharT>
>>>    }
>>>
>>>    template<typename Out>
>>> -  Out format(DebugWrapper<T> const& t,
>>> -            std::basic_format_context<Out, CharT>& fc) const
>>> +  constexpr26 Out
>>> +  format(DebugWrapper<T> const& t,
>>> +        std::basic_format_context<Out, CharT>& fc) const
>>>    { return under.format(t.val, fc); }
>>>
>>>  private:
>>> @@ -760,7 +771,7 @@ private:
>>>  };
>>>
>>>  template<typename CharT, typename StrT>
>>> -void
>>> +constexpr26 void
>>>  test_formatter_str()
>>>  {
>>>    CharT buf[]{ 'a', 'b', 'c', 0 };
>>> @@ -770,7 +781,7 @@ test_formatter_str()
>>>  }
>>>
>>>  template<typename CharT>
>>> -void
>>> +constexpr26 void
>>>  test_formatter_arr()
>>>  {
>>>    std::basic_string<CharT> res;
>>> @@ -786,7 +797,7 @@ test_formatter_arr()
>>>  }
>>>
>>>  template<typename CharT, typename SrcT>
>>> -void
>>> +constexpr26 void
>>>  test_formatter_char()
>>>  {
>>>    DebugWrapper<SrcT> in{ 'a' };
>>> @@ -795,7 +806,7 @@ test_formatter_char()
>>>  }
>>>
>>>  template<typename CharT>
>>> -void
>>> +constexpr26 void
>>>  test_formatters()
>>>  {
>>>    test_formatter_char<CharT, CharT>();
>>> @@ -806,38 +817,60 @@ test_formatters()
>>>    test_formatter_arr<CharT>();
>>>  }
>>>
>>> -void
>>> +constexpr26 void
>>>  test_formatters_c()
>>>  {
>>>    test_formatters<char>();
>>> -  test_formatters<wchar_t>();
>>> -  test_formatter_char<wchar_t, char>();
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      test_formatters<wchar_t>();
>>> +      test_formatter_char<wchar_t, char>();
>>> +    }
>>>  }
>>>
>>> -int main()
>>> +constexpr26 bool
>>> +test_all()
>>>  {
>>>    test_basic_escapes<char>();
>>> -  test_basic_escapes<wchar_t>();
>>>    test_ascii_escapes<char>();
>>> -  test_ascii_escapes<wchar_t>();
>>>    test_extended_ascii<char>();
>>> -  test_extended_ascii<wchar_t>();
>>>
>>>    test_unicode_escapes<char>();
>>> -  test_unicode_escapes<wchar_t>();
>>>    test_grapheme_extend<char>();
>>> -  test_grapheme_extend<wchar_t>();
>>>    test_replacement_char<char>();
>>> -  test_replacement_char<wchar_t>();
>>>    test_ill_formed_utf8_seq();
>>> -  test_ill_formed_utf32();
>>>
>>>    test_fill<char>();
>>> -  test_fill<wchar_t>();
>>>    test_prec<char>();
>>> -  test_prec<wchar_t>();
>>> +
>>> +  // constexpr wide formatting not yet implemented
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      test_basic_escapes<wchar_t>();
>>> +      test_ascii_escapes<wchar_t>();
>>> +      test_extended_ascii<wchar_t>();
>>> +
>>> +      test_unicode_escapes<wchar_t>();
>>> +      test_grapheme_extend<wchar_t>();
>>> +      test_replacement_char<wchar_t>();
>>> +      test_ill_formed_utf32();
>>> +
>>> +      test_fill<wchar_t>();
>>> +      test_prec<wchar_t>();
>>> +    }
>>>
>>>    test_padding();
>>>
>>>    test_formatters_c();
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +#if __cplusplus >= 202400L
>>> +static_assert(test_all());
>>> +#endif
>>> +
>>> +int main()
>>> +{
>>> +  test_all();
>>>  }
>>> diff --git a/libstdc++-v3/testsuite/std/format/functions/format.cc
>>> b/libstdc++-v3/testsuite/std/format/functions/format.cc
>>> index d342114083e..9d921d59d5f 100644
>>> --- a/libstdc++-v3/testsuite/std/format/functions/format.cc
>>> +++ b/libstdc++-v3/testsuite/std/format/functions/format.cc
>>> @@ -3,6 +3,12 @@
>>>  // { dg-add-options no_pch }
>>>  // { dg-additional-options "-DUNICODE" { target 4byte_wchar_t } }
>>>
>>> +#if __cplusplus >= 202400L
>>> +# define constexpr26 constexpr
>>> +#else
>>> +# define constexpr26
>>> +#endif
>>> +
>>>  #include <format>
>>>
>>>  #ifndef __cpp_lib_format
>>> @@ -41,7 +47,7 @@
>>>  #include <cstdio>
>>>  #include <testsuite_hooks.h>
>>>
>>> -void
>>> +constexpr26 void
>>>  test_no_args()
>>>  {
>>>    std::string s;
>>> @@ -55,6 +61,7 @@ test_no_args()
>>>    VERIFY( s == "128bpm }" );
>>>  }
>>>
>>> +// not constexpr because of PR124145
>>>  void
>>>  test_unescaped()
>>>  {
>>> @@ -78,7 +85,7 @@ struct brit_punc : std::numpunct<char>
>>>    std::string do_falsename() const override { return "nah bruv"; }
>>>  };
>>>
>>> -void
>>> +constexpr26 void
>>>  test_std_examples()
>>>  {
>>>    using namespace std;
>>> @@ -125,10 +132,13 @@ test_std_examples()
>>>      VERIFY(s0 == "1,+1,1, 1");
>>>      string s1 = format("{0:},{0:+},{0:-},{0: }", -1);
>>>      VERIFY(s1 == "-1,-1,-1,-1");
>>> -    string s2 = format("{0:},{0:+},{0:-},{0: }", inf);
>>> -    VERIFY(s2 == "inf,+inf,inf, inf");
>>> -    string s3 = format("{0:},{0:+},{0:-},{0: }", nan);
>>> -    VERIFY(s3 == "nan,+nan,nan, nan");
>>> +    if (!std::is_constant_evaluated())
>>> +      {
>>> +       string s2 = format("{0:},{0:+},{0:-},{0: }", inf);
>>> +       VERIFY(s2 == "inf,+inf,inf, inf");
>>> +       string s3 = format("{0:},{0:+},{0:-},{0: }", nan);
>>> +       VERIFY(s3 == "nan,+nan,nan, nan");
>>> +      }
>>>    }
>>>
>>>    // alternate form and zero fill
>>> @@ -143,34 +153,35 @@ test_std_examples()
>>>    }
>>>
>>>    // integer presentation types
>>> -  {
>>> -    // Change global locale so "{:L}" adds digit separators.
>>> -    std::locale::global(std::locale({}, new brit_punc));
>>> -
>>> -    string s0 = format("{}", 42);
>>> -    VERIFY(s0 == "42");
>>> -    string s1 = format("{0:b} {0:d} {0:o} {0:x}", 42);
>>> -    VERIFY(s1 == "101010 42 52 2a");
>>> -    string s2 = format("{0:#x} {0:#X}", 42);
>>> -    VERIFY(s2 == "0x2a 0X2A");
>>> -    string s3 = format("{:L}", 1234);
>>> -    VERIFY(s3 == "1,234");
>>> -
>>> -    // Test locale's "byte-and-a-half" grouping (Imperial word?
>>> tribble?).
>>> -    string s4 = format("{:#Lx}", 0xfffff);
>>> -    VERIFY(s4 == "0xff,fff");
>>> -
>>> -    // Restore
>>> -    std::locale::global(std::locale::classic());
>>> -
>>> -    string s5 = format("{}", -100); // PR libstdc++/114325
>>> -    VERIFY(s5 == "-100");
>>> -    string s6 = format("{:d} {:d}", -123, 999);
>>> -    VERIFY(s6 == "-123 999");
>>> -  }
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      // Change global locale so "{:L}" adds digit separators.
>>> +      std::locale::global(std::locale({}, new brit_punc));
>>> +
>>> +      string s0 = format("{}", 42);
>>> +      VERIFY(s0 == "42");
>>> +      string s1 = format("{0:b} {0:d} {0:o} {0:x}", 42);
>>> +      VERIFY(s1 == "101010 42 52 2a");
>>> +      string s2 = format("{0:#x} {0:#X}", 42);
>>> +      VERIFY(s2 == "0x2a 0X2A");
>>> +      string s3 = format("{:L}", 1234);
>>> +      VERIFY(s3 == "1,234");
>>> +
>>> +      // Test locale's "byte-and-a-half" grouping (Imperial word?
>>> tribble?).
>>> +      string s4 = format("{:#Lx}", 0xfffff);
>>> +      VERIFY(s4 == "0xff,fff");
>>> +
>>> +      // Restore
>>> +      std::locale::global(std::locale::classic());
>>> +
>>> +      string s5 = format("{}", -100); // PR libstdc++/114325
>>> +      VERIFY(s5 == "-100");
>>> +      string s6 = format("{:d} {:d}", -123, 999);
>>> +      VERIFY(s6 == "-123 999");
>>> +    }
>>>  }
>>>
>>> -void
>>> +constexpr26 void
>>>  test_alternate_forms()
>>>  {
>>>    std::string s;
>>> @@ -180,23 +191,26 @@ test_alternate_forms()
>>>    s = std::format("{0:#b} {0:+#B} {0:#o} {0:#x} {0:+#X} {0: #d}", 0);
>>>    VERIFY( s == "0b0 +0B0 0 0x0 +0X0  0" );
>>>
>>> -  s = std::format("{0:+#012g} {0:+#014g} {0:+#014g}", 1234.0);
>>> -  VERIFY( s == "+00001234.00 +0000001234.00 +0000001234.00" );
>>> -  s = std::format("{0:+#0{1}g} {0:+#0{2}g} {0:+#0{2}g}", 1234.5, 12,
>>> 14);
>>> -  VERIFY( s == "+00001234.50 +0000001234.50 +0000001234.50" );
>>> -
>>> -  s = std::format("{:#.2g}", -0.0);
>>> -  VERIFY( s == "-0.0" );
>>> -
>>> -  // PR libstdc++/108046
>>> -  s = std::format("{0:#.0} {0:#.1} {0:#.0g}", 10.0);
>>> -  VERIFY( s == "1.e+01 1.e+01 1.e+01" );
>>> -
>>> -  // PR libstdc++/113512
>>> -  s = std::format("{:#.3g}", 0.025);
>>> -  VERIFY( s == "0.0250" );
>>> -  s = std::format("{:#07.3g}", 0.02);
>>> -  VERIFY( s == "00.0200" );
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      s = std::format("{0:+#012g} {0:+#014g} {0:+#014g}", 1234.0);
>>> +      VERIFY( s == "+00001234.00 +0000001234.00 +0000001234.00" );
>>> +      s = std::format("{0:+#0{1}g} {0:+#0{2}g} {0:+#0{2}g}", 1234.5,
>>> 12, 14);
>>> +      VERIFY( s == "+00001234.50 +0000001234.50 +0000001234.50" );
>>> +
>>> +      s = std::format("{:#.2g}", -0.0);
>>> +      VERIFY( s == "-0.0" );
>>> +
>>> +      // PR libstdc++/108046
>>> +      s = std::format("{0:#.0} {0:#.1} {0:#.0g}", 10.0);
>>> +      VERIFY( s == "1.e+01 1.e+01 1.e+01" );
>>> +
>>> +      // PR libstdc++/113512
>>> +      s = std::format("{:#.3g}", 0.025);
>>> +      VERIFY( s == "0.0250" );
>>> +      s = std::format("{:#07.3g}", 0.02);
>>> +      VERIFY( s == "00.0200" );
>>> +    }
>>>  }
>>>
>>>  void
>>> @@ -275,7 +289,7 @@ test_locale()
>>>    std::locale::global(cloc);
>>>  }
>>>
>>> -void
>>> +constexpr26 void
>>>  test_width()
>>>  {
>>>    std::string s;
>>> @@ -294,30 +308,34 @@ test_width()
>>>    s = std::format("DR {0:{1}}: allow width {1} from arg-id", 3721, 0);
>>>    VERIFY( s == "DR 3721: allow width 0 from arg-id" );
>>>
>>> -  try {
>>> -    s = std::format("Negative width is an error: {0:{1}}", 123, -1);
>>> -    VERIFY(false);
>>> -  } catch (const std::format_error&) {
>>> -  }
>>> -
>>> -  try {
>>> -    bool no = false, yes = true;
>>> -    auto args = std::make_format_args(no, yes);
>>> -    s = std::vformat("DR 3720: restrict type of width arg-id {0:{1}}",
>>> args);
>>> -    VERIFY(false);
>>> -  } catch (const std::format_error&) {
>>> -  }
>>> -
>>> -  try {
>>> -    char wat = '?', bang = '!';
>>> -    auto args = std::make_format_args(wat, bang);
>>> -    s = std::vformat("DR 3720: restrict type of width arg-id {0:{1}}",
>>> args);
>>> -    VERIFY(false);
>>> -  } catch (const std::format_error&) {
>>> -  }
>>> +  // not constexpr because of PR124145
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      try {
>>> +       s = std::format("Negative width is an error: {0:{1}}", 123, -1);
>>> +       VERIFY(false);
>>> +      } catch (const std::format_error&) {
>>> +      }
>>> +
>>> +      try {
>>> +       bool no = false, yes = true;
>>> +       auto args = std::make_format_args(no, yes);
>>> +       s = std::vformat("DR 3720: restrict type of width arg-id
>>> {0:{1}}", args);
>>> +       VERIFY(false);
>>> +      } catch (const std::format_error&) {
>>> +      }
>>> +
>>> +      try {
>>> +       char wat = '?', bang = '!';
>>> +       auto args = std::make_format_args(wat, bang);
>>> +       s = std::vformat("DR 3720: restrict type of width arg-id
>>> {0:{1}}", args);
>>> +       VERIFY(false);
>>> +      } catch (const std::format_error&) {
>>> +      }
>>> +    }
>>>  }
>>>
>>> -void
>>> +constexpr26 void
>>>  test_char()
>>>  {
>>>    std::string s;
>>> @@ -347,6 +365,7 @@ test_char()
>>>    VERIFY( s == "11110000 11110000 240 360 f0 F0" );
>>>  }
>>>
>>> +// constexpr wide formatting not yet implemented
>>>  void
>>>  test_wchar()
>>>  {
>>> @@ -395,7 +414,7 @@ test_wchar()
>>>    VERIFY( ws == L"0.5" );
>>>  }
>>>
>>> -void
>>> +constexpr26 void
>>>  test_minmax()
>>>  {
>>>    auto check = []<typename T, typename U = std::make_unsigned_t<T>>(T,
>>> U = 0) {
>>> @@ -422,7 +441,7 @@ test_minmax()
>>>  #endif
>>>  }
>>>
>>> -void
>>> +constexpr26 void
>>>  test_p1652r1() // printf corner cases in std::format
>>>  {
>>>    std::string s;
>>> @@ -436,27 +455,33 @@ test_p1652r1() // printf corner cases in
>>> std::format
>>>    s = std::format("{:c}", c);
>>>    VERIFY( s == "A" );
>>>
>>> -  // Problem 3: "-000nan" is not a floating point value
>>> -  double nan = std::numeric_limits<double>::quiet_NaN();
>>> -  try {
>>> -    s = std::vformat("{:0=6}", std::make_format_args(nan));
>>> -    VERIFY( false );
>>> -  } catch (const std::format_error&) {
>>> -  }
>>> -
>>> -  s = std::format("{:06}", nan);
>>> -  VERIFY( s == "   nan" );
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      // Problem 3: "-000nan" is not a floating point value
>>> +      double nan = std::numeric_limits<double>::quiet_NaN();
>>> +      try {
>>> +       s = std::vformat("{:0=6}", std::make_format_args(nan));
>>> +       VERIFY( false );
>>> +      } catch (const std::format_error&) {
>>> +      }
>>> +
>>> +      s = std::format("{:06}", nan);
>>> +      VERIFY( s == "   nan" );
>>> +    }
>>>
>>>    // Problem 4: bool needs a type format specifier
>>>    s = std::format("{:s}", true);
>>>    VERIFY( s == "true" );
>>>
>>> -  // Problem 5: double does not roundtrip float
>>> -  s = std::format("{}", 3.31f);
>>> -  VERIFY( s == "3.31" );
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      // Problem 5: double does not roundtrip float
>>> +      s = std::format("{}", 3.31f);
>>> +      VERIFY( s == "3.31" );
>>> +    }
>>>  }
>>>
>>> -void
>>> +constexpr26 void
>>>  test_pointer()
>>>  {
>>>    void* p = nullptr;
>>> @@ -477,28 +502,31 @@ test_pointer()
>>>    s = std::format("{:o<4},{:o>5},{:o^7}", p, pc, nullptr); //
>>> fill+align+width
>>>    VERIFY( s == "0x0o,oo0x0,oo0x0oo" );
>>>
>>> -  pc = p = &s;
>>> -  str_int = std::format("{:#x}", reinterpret_cast<std::uintptr_t>(p));
>>> -  s = std::format("{} {} {}", p, pc, nullptr);
>>> -  VERIFY( s == (str_int + ' ' + str_int + " 0x0") );
>>> -  str_int = std::format("{:#20x}", reinterpret_cast<std::uintptr_t>(p));
>>> -  s = std::format("{:20} {:20p}", p, pc);
>>> -  VERIFY( s == (str_int + ' ' + str_int) );
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      pc = p = &s;
>>> +      str_int = std::format("{:#x}",
>>> reinterpret_cast<std::uintptr_t>(p));
>>> +      s = std::format("{} {} {}", p, pc, nullptr);
>>> +      VERIFY( s == (str_int + ' ' + str_int + " 0x0") );
>>> +      str_int = std::format("{:#20x}",
>>> reinterpret_cast<std::uintptr_t>(p));
>>> +      s = std::format("{:20} {:20p}", p, pc);
>>> +      VERIFY( s == (str_int + ' ' + str_int) );
>>>
>>>  #if __cpp_lib_format >= 202304L
>>> -  // P2510R3 Formatting pointers
>>> -  s = std::format("{:06} {:07P} {:08p}", (void*)0, (const void*)0,
>>> nullptr);
>>> -  VERIFY( s == "0x0000 0X00000 0x000000" );
>>> -  str_int = std::format("{:#016x}",
>>> reinterpret_cast<std::uintptr_t>(p));
>>> -  s = std::format("{:016} {:016}", p, pc);
>>> -  VERIFY( s == (str_int + ' ' + str_int) );
>>> -  str_int = std::format("{:#016X}",
>>> reinterpret_cast<std::uintptr_t>(p));
>>> -  s = std::format("{:016P} {:016P}", p, pc);
>>> -  VERIFY( s == (str_int + ' ' + str_int) );
>>> +      // P2510R3 Formatting pointers
>>> +      s = std::format("{:06} {:07P} {:08p}", (void*)0, (const void*)0,
>>> nullptr);
>>> +      VERIFY( s == "0x0000 0X00000 0x000000" );
>>> +      str_int = std::format("{:#016x}",
>>> reinterpret_cast<std::uintptr_t>(p));
>>> +      s = std::format("{:016} {:016}", p, pc);
>>> +      VERIFY( s == (str_int + ' ' + str_int) );
>>> +      str_int = std::format("{:#016X}",
>>> reinterpret_cast<std::uintptr_t>(p));
>>> +      s = std::format("{:016P} {:016P}", p, pc);
>>> +      VERIFY( s == (str_int + ' ' + str_int) );
>>>  #endif
>>> +    }
>>>  }
>>>
>>> -void
>>> +constexpr26 void
>>>  test_bool()
>>>  {
>>>    std::string s;
>>> @@ -519,7 +547,7 @@ test_bool()
>>>    VERIFY( s == "0 0x1 0X0" );
>>>  }
>>>
>>> -void
>>> +constexpr26 void
>>>  test_unicode()
>>>  {
>>>  #ifdef UNICODE
>>> @@ -579,19 +607,36 @@ test_unicode()
>>>  #endif
>>>  }
>>>
>>> -int main()
>>> +constexpr26 bool
>>> +test_all()
>>>  {
>>>    test_no_args();
>>> -  test_unescaped();
>>>    test_std_examples();
>>>    test_alternate_forms();
>>> -  test_locale();
>>>    test_width();
>>>    test_char();
>>> -  test_wchar();
>>>    test_minmax();
>>>    test_p1652r1();
>>>    test_pointer();
>>>    test_bool();
>>>    test_unicode();
>>> +
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      test_unescaped();
>>> +      test_infnan();
>>> +      test_locale();
>>> +      test_wchar();
>>> +    }
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +#if __cplusplus >= 202400L
>>> +static_assert(test_all());
>>> +#endif
>>> +
>>> +int main()
>>> +{
>>> +  test_all();
>>>  }
>>> diff --git a/libstdc++-v3/testsuite/std/format/functions/format_to.cc
>>> b/libstdc++-v3/testsuite/std/format/functions/format_to.cc
>>> index 94e6262bc66..ae6ffb3a562 100644
>>> --- a/libstdc++-v3/testsuite/std/format/functions/format_to.cc
>>> +++ b/libstdc++-v3/testsuite/std/format/functions/format_to.cc
>>> @@ -1,5 +1,11 @@
>>>  // { dg-do run { target c++20 } }
>>>
>>> +#if __cplusplus >= 202400L
>>> +# define constexpr26 constexpr
>>> +#else
>>> +# define constexpr26
>>> +#endif
>>> +
>>>  #include <format>
>>>  #include <locale>
>>>  #include <vector>
>>> @@ -11,17 +17,20 @@ struct punct : std::numpunct<char>
>>>    std::string do_grouping() const override { return "\2"; }
>>>  };
>>>
>>> -void
>>> +constexpr26 void
>>>  test()
>>>  {
>>>    char buf[32] = { };
>>>    auto out = std::format_to(buf, "test");
>>>    VERIFY( out == buf+4 );
>>>
>>> -  std::locale loc({}, new punct);
>>> -  auto out2 = std::format_to(buf, loc, "{:Ld}", 12345);
>>> -  VERIFY( out2 == buf+7 );
>>> -  VERIFY( std::string_view(buf, out2 - buf) == "1,23,45" );
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      std::locale loc({}, new punct);
>>> +      auto out2 = std::format_to(buf, loc, "{:Ld}", 12345);
>>> +      VERIFY( out2 == buf+7 );
>>> +      VERIFY( std::string_view(buf, out2 - buf) == "1,23,45" );
>>> +    }
>>>  }
>>>
>>>  struct wpunct : std::numpunct<wchar_t>
>>> @@ -29,6 +38,7 @@ struct wpunct : std::numpunct<wchar_t>
>>>    std::string do_grouping() const override { return "\2"; }
>>>  };
>>>
>>> +// constexpr wide formatting not yet implemented
>>>  void
>>>  test_wchar()
>>>  {
>>> @@ -50,20 +60,20 @@ struct move_only_iterator
>>>    using difference_type = iterator::difference_type;
>>>    using iterator_category = std::output_iterator_tag;
>>>
>>> -  move_only_iterator(iterator b) : base_(b) { }
>>> +  constexpr move_only_iterator(iterator b) : base_(b) { }
>>>    move_only_iterator(move_only_iterator&&) = default;
>>>    move_only_iterator& operator=(move_only_iterator&&) = default;
>>>
>>> -  move_only_iterator& operator++() { ++base_; return *this; }
>>> -  move_only_iterator operator++(int) { auto tmp = *this; ++base_;
>>> return tmp; }
>>> +  constexpr move_only_iterator& operator++() { ++base_; return *this; }
>>> +  constexpr move_only_iterator operator++(int) { auto tmp = *this;
>>> ++base_; return tmp; }
>>>
>>> -  decltype(auto) operator*() { return *base_; }
>>> +  constexpr decltype(auto) operator*() { return *base_; }
>>>
>>>  private:
>>>    iterator base_;
>>>  };
>>>
>>> -void
>>> +constexpr26 void
>>>  test_move_only()
>>>  {
>>>    std::string str;
>>> @@ -72,14 +82,17 @@ test_move_only()
>>>      = std::format_to(std::move(mo), "for{:.3} that{:c}", "matte",
>>> (int)'!');
>>>    VERIFY( str == "format that!" );
>>>
>>> -  std::vector<wchar_t> vec;
>>> -  move_only_iterator wmo(std::back_inserter(vec));
>>> -  [[maybe_unused]] auto wres
>>> -    = std::format_to(std::move(wmo), L"for{:.3} hat{:c}", L"matte",
>>> (long)L'!');
>>> -  VERIFY( std::wstring_view(vec.data(), vec.size()) == L"format hat!" );
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      std::vector<wchar_t> vec;
>>> +      move_only_iterator wmo(std::back_inserter(vec));
>>> +      [[maybe_unused]] auto wres
>>> +                        = std::format_to(std::move(wmo), L"for{:.3}
>>> hat{:c}", L"matte", (long)L'!');
>>> +      VERIFY( std::wstring_view(vec.data(), vec.size()) == L"format
>>> hat!" );
>>> +    }
>>>  }
>>>
>>> -void
>>> +constexpr26 void
>>>  test_pr110917()
>>>  {
>>>    // PR libstdc++/110917
>>> @@ -90,10 +103,24 @@ test_pr110917()
>>>    VERIFY( ! std::memcmp(buf, "abc 123", 7) );
>>>  }
>>>
>>> -int main()
>>> +constexpr26 bool
>>> +test_all()
>>>  {
>>>    test();
>>> -  test_wchar();
>>>    test_move_only();
>>>    test_pr110917();
>>> +
>>> +  if (!std::is_constant_evaluated())
>>> +    test_wchar();
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +#if __cplusplus >= 202400L
>>> +static_assert(test_all());
>>> +#endif
>>> +
>>> +int main()
>>> +{
>>> +  test_all();
>>>  }
>>> diff --git a/libstdc++-v3/testsuite/std/format/functions/size.cc
>>> b/libstdc++-v3/testsuite/std/format/functions/size.cc
>>> index 1ece4108d85..24220f632fe 100644
>>> --- a/libstdc++-v3/testsuite/std/format/functions/size.cc
>>> +++ b/libstdc++-v3/testsuite/std/format/functions/size.cc
>>> @@ -1,10 +1,16 @@
>>>  // { dg-do run { target c++20 } }
>>>
>>> +#if __cplusplus >= 202400L
>>> +# define constexpr26 constexpr
>>> +#else
>>> +# define constexpr26
>>> +#endif
>>> +
>>>  #include <format>
>>>  #include <string>
>>>  #include <testsuite_hooks.h>
>>>
>>> -void
>>> +constexpr26 void
>>>  test()
>>>  {
>>>    auto n = std::formatted_size("");
>>> @@ -44,8 +50,20 @@ test_wchar()
>>>    VERIFY( n == 5 );
>>>  }
>>>
>>> -int main()
>>> +constexpr26 bool
>>> +test_all()
>>>  {
>>>    test();
>>> -  test_wchar();
>>> +  if (!std::is_constant_evaluated())
>>> +    test_wchar();
>>> +  return true;
>>> +}
>>> +
>>> +#if __cplusplus >= 202400L
>>> +static_assert(test_all());
>>> +#endif
>>> +
>>> +int main()
>>> +{
>>> +  test_all();
>>>  }
>>> diff --git a/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc
>>> b/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc
>>> index 1450fbaebc5..48795440d13 100644
>>> --- a/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc
>>> +++ b/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc
>>> @@ -1,5 +1,11 @@
>>>  // { dg-do run { target c++23 } }
>>>
>>> +#if __cplusplus >= 202400L
>>> +# define constexpr26 constexpr
>>> +#else
>>> +# define constexpr26
>>> +#endif
>>> +
>>>  #include <deque>
>>>  #include <flat_map>
>>>  #include <flat_set>
>>> @@ -64,7 +70,8 @@ struct CustFormat : std::vector<T>
>>>  template<typename T, std::range_format rf>
>>>  constexpr auto std::format_kind<CustFormat<T, rf>> = rf;
>>>
>>> -void test_override()
>>> +constexpr26 bool
>>> +test_override()
>>>  {
>>>    CustFormat<int, std::range_format::disabled> disabledf;
>>>    static_assert( !std::formattable<decltype(disabledf), char> );
>>> @@ -88,8 +95,14 @@ void test_override()
>>>    VERIFY( std::format("{}", debugf) == R"("abcd")" );
>>>    // Support precision as string do
>>>    VERIFY( std::format("{:.3}", debugf) == R"("ab)" );
>>> +
>>> +  return true;
>>>  }
>>>
>>> +#if __cplusplus >= 202400L
>>> +static_assert(test_override());
>>> +#endif
>>> +
>>>  int main()
>>>  {
>>>    test_override();
>>> diff --git a/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
>>> b/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
>>> index a50c5b1033f..3bd5f37403e 100644
>>> --- a/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
>>> +++ b/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
>>> @@ -1,5 +1,11 @@
>>>  // { dg-do run { target c++23 } }
>>>
>>> +#if __cplusplus >= 202400L
>>> +# define constexpr26 constexpr
>>> +#else
>>> +# define constexpr26
>>> +#endif
>>> +
>>>  #include <flat_map>
>>>  #include <format>
>>>  #include <testsuite_hooks.h>
>>> @@ -32,7 +38,7 @@ struct std::formatter<MyVector<T, Formatter>, CharT>
>>>    { return _formatter.parse(pc);  }
>>>
>>>    template<typename Out>
>>> -  typename std::basic_format_context<Out, CharT>::iterator
>>> +  constexpr26 std::basic_format_context<Out, CharT>::iterator
>>>    format(const MyVector<T, Formatter>& mv,
>>>          std::basic_format_context<Out, CharT>& fc) const
>>>    { return _formatter.format(mv, fc); }
>>> @@ -42,7 +48,7 @@ private:
>>>  };
>>>
>>>  template<typename CharT, template<typename, typename> class Formatter>
>>> -void
>>> +constexpr26 void
>>>  test_default()
>>>  {
>>>    MyVector<int, Formatter> vec{1, 2, 3};
>>> @@ -94,7 +100,7 @@ test_default()
>>>  }
>>>
>>>  template<typename CharT, template<typename, typename> class Formatter>
>>> -void
>>> +constexpr26 void
>>>  test_override()
>>>  {
>>>    MyVector<CharT, Formatter> vc{'a', 'b', 'c', 'd'};
>>> @@ -115,15 +121,20 @@ test_override()
>>>  }
>>>
>>>  template<template<typename, typename> class Formatter>
>>> -void test_outputs()
>>> +constexpr26 void
>>> +test_outputs()
>>>  {
>>>    test_default<char, Formatter>();
>>> -  test_default<wchar_t, Formatter>();
>>>    test_override<char, Formatter>();
>>> -  test_override<wchar_t, Formatter>();
>>> +  // constexpr wide formatting not yet implemented
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      test_default<wchar_t, Formatter>();
>>> +      test_override<wchar_t, Formatter>();
>>> +    }
>>>  }
>>>
>>> -void
>>> +constexpr26 void
>>>  test_nested()
>>>  {
>>>    MyVector<MyVector<int>> v
>>> @@ -152,7 +163,8 @@ struct std::formatter<MyFlatMap, CharT>
>>>    : std::range_formatter<MyFlatMap::reference>
>>>  {};
>>>
>>> -void test_const_ref_type_mismatch()
>>> +constexpr26 void
>>> +test_const_ref_type_mismatch()
>>>  {
>>>    MyFlatMap m{{1, 11}, {2, 22}};
>>>    std::string res = std::format("{:m}", m);
>>> @@ -163,13 +175,15 @@ template<typename T, typename CharT>
>>>  using VectorFormatter = std::formatter<std::vector<T>, CharT>;
>>>
>>>  template<template<typename> typename Range>
>>> -void test_nonblocking()
>>> +constexpr26 void
>>> +test_nonblocking()
>>>  {
>>>    static_assert(!std::enable_nonlocking_formatter_optimization<
>>>                   Range<int>>);
>>>  }
>>>
>>> -int main()
>>> +constexpr26 bool
>>> +test_all()
>>>  {
>>>    test_outputs<std::range_formatter>();
>>>    test_outputs<VectorFormatter>();
>>> @@ -179,4 +193,15 @@ int main()
>>>    test_nonblocking<std::span>();
>>>    test_nonblocking<std::vector>();
>>>    test_nonblocking<MyVector>();
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +#if __cplusplus >= 202400L
>>> +static_assert(test_all());
>>> +#endif
>>> +
>>> +int main()
>>> +{
>>> +  test_all();
>>>  }
>>> diff --git a/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
>>> b/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
>>> index 7fb65f9c551..da1fe7e0df7 100644
>>> --- a/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
>>> +++ b/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
>>> @@ -1,7 +1,13 @@
>>>  // { dg-do run { target c++23 } }
>>> -// { dg-options "-fexec-charset=UTF-8" }
>>> +// { dg-options "-fexec-charset=UTF-8 -fconstexpr-ops-limit=5000000000"
>>> }
>>>  // { dg-timeout-factor 2 }
>>>
>>> +#if __cplusplus >= 202400L
>>> +# define constexpr26 constexpr
>>> +#else
>>> +# define constexpr26
>>> +#endif
>>> +
>>>  #include <array>
>>>  #include <format>
>>>  #include <list>
>>> @@ -19,7 +25,7 @@
>>> static_assert(!std::formattable<std::vector<NotFormattable>, char>);
>>>  static_assert(!std::formattable<std::span<NotFormattable>, wchar_t>);
>>>
>>>  template<typename... Args>
>>> -bool
>>> +constexpr26 bool
>>>  is_format_string_for(const char* str, Args&&... args)
>>>  {
>>>    try {
>>> @@ -31,7 +37,7 @@ is_format_string_for(const char* str, Args&&... args)
>>>  }
>>>
>>>  template<typename... Args>
>>> -bool
>>> +constexpr26 bool
>>>  is_format_string_for(const wchar_t* str, Args&&... args)
>>>  {
>>>    try {
>>> @@ -43,7 +49,8 @@ is_format_string_for(const wchar_t* str, Args&&...
>>> args)
>>>  }
>>>
>>>  template<typename Rg, typename CharT>
>>> -bool is_range_formatter_spec_for(CharT const* spec, Rg&& rg)
>>> +constexpr26 bool
>>> +is_range_formatter_spec_for(CharT const* spec, Rg&& rg)
>>>  {
>>>    using V = std::remove_cvref_t<std::ranges::range_reference_t<Rg>>;
>>>    std::range_formatter<V, CharT> fmt;
>>> @@ -56,6 +63,7 @@ bool is_range_formatter_spec_for(CharT const* spec,
>>> Rg&& rg)
>>>    }
>>>  }
>>>
>>> +// not constexpr because of PR124145
>>>  void
>>>  test_format_string()
>>>  {
>>> @@ -79,7 +87,8 @@ test_format_string()
>>>  #define WIDEN(S) WIDEN_(CharT, S)
>>>
>>>  template<typename CharT, typename Range, typename Storage>
>>> -void test_output()
>>> +constexpr26 void
>>> +test_output()
>>>  {
>>>    using Sv = std::basic_string_view<CharT>;
>>>    using T = std::ranges::range_value_t<Range>;
>>> @@ -153,25 +162,32 @@ void test_output()
>>>  }
>>>
>>>  template<typename Cont>
>>> -void test_output_cont()
>>> +constexpr26 void
>>> +test_output_cont()
>>>  {
>>>    test_output<char, Cont&, Cont>();
>>> -  test_output<wchar_t, Cont const&, Cont>();
>>> +  if (!std::is_constant_evaluated())
>>> +    test_output<wchar_t, Cont const&, Cont>();
>>>  }
>>>
>>>  template<typename View>
>>> -void test_output_view()
>>> +constexpr26 void
>>> +test_output_view()
>>>  {
>>>    test_output<char, View, int[3]>();
>>> -  test_output<wchar_t, View, int[3]>();
>>> +  if (!std::is_constant_evaluated())
>>> +    test_output<wchar_t, View, int[3]>();
>>>  }
>>>
>>> -void
>>> +constexpr26 void
>>>  test_outputs()
>>>  {
>>>    using namespace __gnu_test;
>>>    test_output_cont<std::vector<int>>();
>>> -  test_output_cont<std::list<int>>();
>>> +
>>> +  if (!std::is_constant_evaluated())
>>> +    test_output_cont<std::list<int>>();
>>> +
>>>    test_output_cont<std::array<int, 3>>();
>>>
>>>    test_output_view<std::span<int>>();
>>> @@ -185,7 +201,7 @@ test_outputs()
>>>    test_output_view<test_forward_range<const int>>();
>>>  }
>>>
>>> -void
>>> +constexpr26 void
>>>  test_nested()
>>>  {
>>>    std::vector<std::vector<int>> v
>>> @@ -201,7 +217,8 @@ test_nested()
>>>    VERIFY( res == "+[01, 02, 11, 12]+" );
>>>  }
>>>
>>> -bool strip_quote(std::string_view& v)
>>> +constexpr26 bool
>>> +strip_quote(std::string_view& v)
>>>  {
>>>    if (!v.starts_with('"'))
>>>      return false;
>>> @@ -209,7 +226,8 @@ bool strip_quote(std::string_view& v)
>>>    return true;
>>>  }
>>>
>>> -bool strip_prefix(std::string_view& v, std::string_view expected, bool
>>> quoted = false)
>>> +constexpr26 bool
>>> +strip_prefix(std::string_view& v, std::string_view expected, bool
>>> quoted = false)
>>>  {
>>>    if (quoted && !strip_quote(v))
>>>      return false;
>>> @@ -221,7 +239,8 @@ bool strip_prefix(std::string_view& v,
>>> std::string_view expected, bool quoted =
>>>    return true;
>>>  }
>>>
>>> -bool strip_squares(std::string_view& v)
>>> +constexpr26 bool
>>> +strip_squares(std::string_view& v)
>>>  {
>>>    if (!v.starts_with('[') || !v.ends_with(']'))
>>>      return false;
>>> @@ -230,7 +249,8 @@ bool strip_squares(std::string_view& v)
>>>    return true;
>>>  }
>>>
>>> -bool strip_prefix(std::string_view& v, size_t n, char c)
>>> +constexpr26 bool
>>> +strip_prefix(std::string_view& v, size_t n, char c)
>>>  {
>>>    size_t pos = v.find_first_not_of(c);
>>>    if (pos == std::string_view::npos)
>>> @@ -241,7 +261,8 @@ bool strip_prefix(std::string_view& v, size_t n,
>>> char c)
>>>    return true;
>>>  }
>>>
>>> -void test_padding()
>>> +constexpr26 void
>>> +test_padding()
>>>  {
>>>    std::string res;
>>>    std::string_view resv;
>>> @@ -323,10 +344,24 @@ void test_padding()
>>>    VERIFY( check_elems(resv, false) );
>>>  }
>>>
>>> -int main()
>>> +constexpr26 bool
>>> +test_all()
>>>  {
>>> -  test_format_string();
>>>    test_outputs();
>>>    test_nested();
>>>    test_padding();
>>> +
>>> +  if (!std::is_constant_evaluated())
>>> +    test_format_string();
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +#if __cplusplus >= 202400L
>>> +static_assert(test_all());
>>> +#endif
>>> +
>>> +int main()
>>> +{
>>> +  test_all();
>>>  }
>>> diff --git a/libstdc++-v3/testsuite/std/format/runtime_format.cc
>>> b/libstdc++-v3/testsuite/std/format/runtime_format.cc
>>> index f2bfa5b434d..6bb402a4108 100644
>>> --- a/libstdc++-v3/testsuite/std/format/runtime_format.cc
>>> +++ b/libstdc++-v3/testsuite/std/format/runtime_format.cc
>>> @@ -3,7 +3,7 @@
>>>  #include <format>
>>>  #include <testsuite_hooks.h>
>>>
>>> -void
>>> +constexpr void
>>>  test_char()
>>>  {
>>>    std::string fmt = "{}";
>>> @@ -19,7 +19,7 @@ test_wchar()
>>>    VERIFY( s == L"0710" );
>>>  }
>>>
>>> -void
>>> +constexpr void
>>>  test_internal_api()
>>>  {
>>>    // Using _Runtime_format_string directly works even in C++20 mode.
>>> @@ -40,9 +40,19 @@ static_assert(
>>> !std::is_constructible_v<std::format_string<>,
>>>  static_assert( !std::is_constructible_v<std::wformat_string<>,
>>>
>>> decltype(std::runtime_format(L""))&&> );
>>>
>>> -int main()
>>> +constexpr bool
>>> +test_all()
>>>  {
>>>    test_char();
>>> -  test_wchar();
>>> +  if (!std::is_constant_evaluated())
>>> +    test_wchar();
>>>    test_internal_api();
>>> +  return true;
>>> +}
>>> +
>>> +static_assert(test_all());
>>> +
>>> +int main()
>>> +{
>>> +  test_all();
>>>  }
>>> diff --git a/libstdc++-v3/testsuite/std/format/string.cc
>>> b/libstdc++-v3/testsuite/std/format/string.cc
>>> index ee987a15ec3..90222db90aa 100644
>>> --- a/libstdc++-v3/testsuite/std/format/string.cc
>>> +++ b/libstdc++-v3/testsuite/std/format/string.cc
>>> @@ -1,10 +1,16 @@
>>>  // { dg-do run { target c++20 } }
>>>
>>> +#if __cplusplus >= 202400L
>>> +# define constexpr26 constexpr
>>> +#else
>>> +# define constexpr26
>>> +#endif
>>> +
>>>  #include <format>
>>>  #include <testsuite_hooks.h>
>>>
>>>  template<typename... Args>
>>> -bool
>>> +constexpr26 bool
>>>  is_format_string_for(const char* str, Args&&... args)
>>>  {
>>>    try {
>>> @@ -16,7 +22,7 @@ is_format_string_for(const char* str, Args&&... args)
>>>  }
>>>
>>>  template<typename... Args>
>>> -bool
>>> +constexpr26 bool
>>>  is_format_string_for(const wchar_t* str, Args&&... args)
>>>  {
>>>    try {
>>> @@ -27,28 +33,37 @@ is_format_string_for(const wchar_t* str, Args&&...
>>> args)
>>>    }
>>>  }
>>>
>>> -void
>>> +constexpr26 void
>>>  test_no_args()
>>>  {
>>>    VERIFY( is_format_string_for("") );
>>>    VERIFY( is_format_string_for("chars") );
>>>    VERIFY( is_format_string_for(" The Great Escape {{}} ") );
>>>
>>> -  VERIFY( ! is_format_string_for("{") );
>>> -  VERIFY( ! is_format_string_for("}") );
>>> -  VERIFY( ! is_format_string_for("}{") );
>>> -  VERIFY( ! is_format_string_for("{{}") );
>>> -  VERIFY( ! is_format_string_for("{{{") );
>>> -  VERIFY( ! is_format_string_for("{{{{{") );
>>> +  // not constexpr because of PR124145
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      VERIFY( ! is_format_string_for("{") );
>>> +      VERIFY( ! is_format_string_for("}") );
>>> +      VERIFY( ! is_format_string_for("}{") );
>>> +      VERIFY( ! is_format_string_for("{{}") );
>>> +      VERIFY( ! is_format_string_for("{{{") );
>>> +      VERIFY( ! is_format_string_for("{{{{{") );
>>> +    }
>>>  }
>>>
>>> -void
>>> +constexpr26 void
>>>  test_indexing()
>>>  {
>>>    VERIFY( is_format_string_for("{} to {}", "a", "b") );   // automatic
>>> indexing
>>>    VERIFY( is_format_string_for("{1} to {0}", "a", "b") ); // manual
>>> indexing
>>> -  VERIFY( ! is_format_string_for("{0} to {}", "a", "b") );  // mixed
>>> indexing
>>> -  VERIFY( ! is_format_string_for("{} to {1}", "a", "b") );  // mixed
>>> indexing
>>> +
>>> +  // not constexpr because of PR124145
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      VERIFY( ! is_format_string_for("{0} to {}", "a", "b") );  //
>>> mixed indexing
>>> +      VERIFY( ! is_format_string_for("{} to {1}", "a", "b") );  //
>>> mixed indexing
>>> +    }
>>>
>>>    VERIFY( is_format_string_for("{} {} {}", 1, 2, 3) );
>>>    VERIFY( is_format_string_for("{} {} {}", 1, 2, 3, 4) );
>>> @@ -56,10 +71,14 @@ test_indexing()
>>>    VERIFY( is_format_string_for("{1} {2} {3}", 1, 2, 3, 4) );
>>>    VERIFY( is_format_string_for("{3} {3} {3}", 1, 2, 3, 4) );
>>>
>>> -  VERIFY( ! is_format_string_for("{2}", 1, 2) );
>>> +  // not constexpr because of PR124145
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      VERIFY( ! is_format_string_for("{2}", 1, 2) );
>>>
>>> -  VERIFY( ! is_format_string_for("{0} {}", 1) );
>>> -  VERIFY( ! is_format_string_for("{} {0}", 1) );
>>> +      VERIFY( ! is_format_string_for("{0} {}", 1) );
>>> +      VERIFY( ! is_format_string_for("{} {0}", 1) );
>>> +    }
>>>  }
>>>
>>>  #if __cpp_lib_format_ranges
>>> @@ -68,7 +87,7 @@ constexpr bool escaped_strings_supported = true;
>>>  constexpr bool escaped_strings_supported = false;
>>>  #endif
>>>
>>> -void
>>> +constexpr26 void
>>>  test_format_spec()
>>>  {
>>>    VERIFY( is_format_string_for("{:}", 1) );
>>> @@ -78,92 +97,114 @@ test_format_spec()
>>>    VERIFY( is_format_string_for("{0:} {0:c}", 'c') );
>>>    VERIFY( is_format_string_for("{0:p} {0:}", nullptr) );
>>>    VERIFY( is_format_string_for("{:d} {:+d}", true, true) );
>>> -  VERIFY( is_format_string_for("{:0<-#03Ld}", 1) );
>>> -  VERIFY( is_format_string_for("{1:0<-#03.4Lf}", 1, 2.3) );
>>> -  VERIFY( is_format_string_for("{1:3.3f}", 1, 2.3) );
>>> +
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      VERIFY( is_format_string_for("{:0<-#03Ld}", 1) );
>>> +      VERIFY( is_format_string_for("{1:0<-#03.4Lf}", 1, 2.3) );
>>> +      VERIFY( is_format_string_for("{1:3.3f}", 1, 2.3) );
>>> +    }
>>> +
>>>    VERIFY( is_format_string_for("{:#d}", 'c') );
>>>    VERIFY( is_format_string_for("{:#d}", true) );
>>>    VERIFY( is_format_string_for("{0:s} {0:?}", "str") ==
>>> escaped_strings_supported );
>>>    VERIFY( is_format_string_for("{0:} {0:?}", 'c') ==
>>> escaped_strings_supported );
>>>
>>> -  // Invalid sign options.
>>> -  VERIFY( ! is_format_string_for("{:+}", "str") );
>>> -  VERIFY( ! is_format_string_for("{:+s}", "str") );
>>> -  VERIFY( ! is_format_string_for("{:+}", 'c') );
>>> -  VERIFY( ! is_format_string_for("{:+c}", 'c') );
>>> -  VERIFY( ! is_format_string_for("{:+p}", nullptr) );
>>> -  VERIFY( ! is_format_string_for("{:+}", true) );
>>> -  VERIFY( ! is_format_string_for("{:+s}", true) );
>>> -  VERIFY( ! is_format_string_for("{:+?}", "str") );
>>> -  VERIFY( ! is_format_string_for("{:+?}", 'c') );
>>> -
>>> -  // Invalid alternate forms.
>>> -  VERIFY( ! is_format_string_for("{:#}", "str") );
>>> -  VERIFY( ! is_format_string_for("{:#s}", "str") );
>>> -  VERIFY( ! is_format_string_for("{:#}", 'c') );
>>> -  VERIFY( ! is_format_string_for("{:#c}", 'c') );
>>> -  VERIFY( ! is_format_string_for("{:#}", true) );
>>> -  VERIFY( ! is_format_string_for("{:#s}", true) );
>>> -  VERIFY( ! is_format_string_for("{:#}", nullptr) );
>>> -  VERIFY( ! is_format_string_for("{:#p}", nullptr) );
>>> -  VERIFY( ! is_format_string_for("{:#?}", "str") );
>>> -  VERIFY( ! is_format_string_for("{:#?}", 'c') );
>>> -
>>> -  // The 0 option is not valid for charT and bool.
>>> -  VERIFY( ! is_format_string_for("{:0c}", 'c') );
>>> -  VERIFY( ! is_format_string_for("{:0s}", true) );
>>> -
>>> -  // Dynamic width arg must be a standar integer type.
>>> -  VERIFY( ! is_format_string_for("{:{}d}", 1, 1.5) );
>>> -  VERIFY( ! is_format_string_for("{:{}d}", 1, true) );
>>> -  VERIFY( ! is_format_string_for("{:{}d}", 1, "str") );
>>> -  VERIFY( ! is_format_string_for("{:{}d}", 1, nullptr) );
>>> +  // not constexpr because of PR124145
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      // Invalid sign options.
>>> +      VERIFY( ! is_format_string_for("{:+}", "str") );
>>> +      VERIFY( ! is_format_string_for("{:+s}", "str") );
>>> +      VERIFY( ! is_format_string_for("{:+}", 'c') );
>>> +      VERIFY( ! is_format_string_for("{:+c}", 'c') );
>>> +      VERIFY( ! is_format_string_for("{:+p}", nullptr) );
>>> +      VERIFY( ! is_format_string_for("{:+}", true) );
>>> +      VERIFY( ! is_format_string_for("{:+s}", true) );
>>> +      VERIFY( ! is_format_string_for("{:+?}", "str") );
>>> +      VERIFY( ! is_format_string_for("{:+?}", 'c') );
>>> +
>>> +      // Invalid alternate forms.
>>> +      VERIFY( ! is_format_string_for("{:#}", "str") );
>>> +      VERIFY( ! is_format_string_for("{:#s}", "str") );
>>> +      VERIFY( ! is_format_string_for("{:#}", 'c') );
>>> +      VERIFY( ! is_format_string_for("{:#c}", 'c') );
>>> +      VERIFY( ! is_format_string_for("{:#}", true) );
>>> +      VERIFY( ! is_format_string_for("{:#s}", true) );
>>> +      VERIFY( ! is_format_string_for("{:#}", nullptr) );
>>> +      VERIFY( ! is_format_string_for("{:#p}", nullptr) );
>>> +      VERIFY( ! is_format_string_for("{:#?}", "str") );
>>> +      VERIFY( ! is_format_string_for("{:#?}", 'c') );
>>> +
>>> +      // The 0 option is not valid for charT and bool.
>>> +      VERIFY( ! is_format_string_for("{:0c}", 'c') );
>>> +      VERIFY( ! is_format_string_for("{:0s}", true) );
>>> +
>>> +      // Dynamic width arg must be a standar integer type.
>>> +      VERIFY( ! is_format_string_for("{:{}d}", 1, 1.5) );
>>> +      VERIFY( ! is_format_string_for("{:{}d}", 1, true) );
>>> +      VERIFY( ! is_format_string_for("{:{}d}", 1, "str") );
>>> +      VERIFY( ! is_format_string_for("{:{}d}", 1, nullptr) );
>>>  #ifdef __SIZEOF_INT128__
>>> -  VERIFY( ! is_format_string_for("{:{}d}", 1, static_cast<__int128>(1))
>>> );
>>> +      VERIFY( ! is_format_string_for("{:{}d}", 1,
>>> static_cast<__int128>(1)) );
>>>  #endif
>>>
>>> -  // Precision only valid for string and floating-point types.
>>> -  VERIFY( ! is_format_string_for("{:.3d}", 1) );
>>> -  VERIFY( ! is_format_string_for("{:3.3d}", 1) );
>>> +      // Precision only valid for string and floating-point types.
>>> +      VERIFY( ! is_format_string_for("{:.3d}", 1) );
>>> +      VERIFY( ! is_format_string_for("{:3.3d}", 1) );
>>> +    }
>>> +
>>>    VERIFY( is_format_string_for("{:3.3s}", "str") );
>>> -  VERIFY( ! is_format_string_for("{:3.3s}", 'c') );
>>> -  VERIFY( ! is_format_string_for("{:3.3p}", nullptr) );
>>> -
>>> -  // Dynamic precision arg must be a standard integer type.
>>> -  VERIFY( ! is_format_string_for("{:.{}f}", 1.0, 1.5) );
>>> -  VERIFY( ! is_format_string_for("{:.{}f}", 1.0, true) );
>>> -  VERIFY( ! is_format_string_for("{:.{}f}", 1.0, "str") );
>>> -  VERIFY( ! is_format_string_for("{:.{}f}", 1.0, nullptr) );
>>> +
>>> +  // not constexpr because of PR124145
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      VERIFY( ! is_format_string_for("{:3.3s}", 'c') );
>>> +      VERIFY( ! is_format_string_for("{:3.3p}", nullptr) );
>>> +
>>> +      // Dynamic precision arg must be a standard integer type.
>>> +      VERIFY( ! is_format_string_for("{:.{}f}", 1.0, 1.5) );
>>> +      VERIFY( ! is_format_string_for("{:.{}f}", 1.0, true) );
>>> +      VERIFY( ! is_format_string_for("{:.{}f}", 1.0, "str") );
>>> +      VERIFY( ! is_format_string_for("{:.{}f}", 1.0, nullptr) );
>>>  #ifdef __SIZEOF_INT128__
>>> -  VERIFY( ! is_format_string_for("{:{}f}", 1.0, static_cast<unsigned
>>> __int128>(1)) );
>>> +      VERIFY( ! is_format_string_for("{:{}f}", 1.0,
>>> static_cast<unsigned __int128>(1)) );
>>>  #endif
>>>
>>> -  // Invalid presentation types for integers.
>>> -  VERIFY( ! is_format_string_for("{:f}", 1) );
>>> -  VERIFY( ! is_format_string_for("{:s}", 1) );
>>> -  VERIFY( ! is_format_string_for("{:g}", 1) );
>>> -  VERIFY( ! is_format_string_for("{:E}", 1) );
>>> -  VERIFY( ! is_format_string_for("{:D}", 1) );
>>> +      // Invalid presentation types for integers.
>>> +      VERIFY( ! is_format_string_for("{:f}", 1) );
>>> +      VERIFY( ! is_format_string_for("{:s}", 1) );
>>> +      VERIFY( ! is_format_string_for("{:g}", 1) );
>>> +      VERIFY( ! is_format_string_for("{:E}", 1) );
>>> +      VERIFY( ! is_format_string_for("{:D}", 1) );
>>>
>>> -  // Invalid presentation types for floating-point types.
>>> -  VERIFY( ! is_format_string_for("{:d}", 1.2) );
>>> -  VERIFY( ! is_format_string_for("{:b}", 1.2) );
>>> -  VERIFY( ! is_format_string_for("{:x}", 1.2) );
>>> -  VERIFY( ! is_format_string_for("{:s}", 1.2) );
>>> +      // Invalid presentation types for floating-point types.
>>> +      VERIFY( ! is_format_string_for("{:d}", 1.2) );
>>> +      VERIFY( ! is_format_string_for("{:b}", 1.2) );
>>> +      VERIFY( ! is_format_string_for("{:x}", 1.2) );
>>> +      VERIFY( ! is_format_string_for("{:s}", 1.2) );
>>>
>>> -  // Invalid presentation types for strings.
>>> -  VERIFY( ! is_format_string_for("{:S}", "str") );
>>> -  VERIFY( ! is_format_string_for("{:d}", "str") );
>>> +      // Invalid presentation types for strings.
>>> +      VERIFY( ! is_format_string_for("{:S}", "str") );
>>> +      VERIFY( ! is_format_string_for("{:d}", "str") );
>>> +    }
>>>
>>>    // Maximum integer value supported for widths and precisions is
>>> USHRT_MAX.
>>>    VERIFY( is_format_string_for("{:65535}", 1) );
>>> -  VERIFY( is_format_string_for(L"{:65535}", 1) );
>>> -  VERIFY( ! is_format_string_for("{:65536}", 1) );
>>> -  VERIFY( ! is_format_string_for(L"{:65536}", 1) );
>>> -  VERIFY( ! is_format_string_for("{:9999999}", 1) );
>>> -  VERIFY( ! is_format_string_for(L"{:9999999}", 1) );
>>> +
>>> +  // constexpr wide formatting not yet implemented
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      VERIFY( is_format_string_for(L"{:65535}", 1) );
>>> +      // PR124145
>>> +      VERIFY( ! is_format_string_for("{:65536}", 1) );
>>> +      VERIFY( ! is_format_string_for(L"{:65536}", 1) );
>>> +      VERIFY( ! is_format_string_for("{:9999999}", 1) );
>>> +      VERIFY( ! is_format_string_for(L"{:9999999}", 1) );
>>> +    }
>>>  }
>>>
>>> +// not constexpr because of PR124145
>>>  void
>>>  test_pr110862()
>>>  {
>>> @@ -178,6 +219,7 @@ test_pr110862()
>>>    }
>>>  }
>>>
>>> +// not constexpr because of PR124145
>>>  void
>>>  test_pr110974()
>>>  {
>>> @@ -197,11 +239,27 @@ test_pr110974()
>>>    }
>>>  }
>>>
>>> -int main()
>>> +constexpr26 bool
>>> +test_all()
>>>  {
>>>    test_no_args();
>>>    test_indexing();
>>>    test_format_spec();
>>> -  test_pr110862();
>>> -  test_pr110974();
>>> +
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      test_pr110862();
>>> +      test_pr110974();
>>> +    }
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +#if __cplusplus >= 202400L
>>> +static_assert(test_all());
>>> +#endif
>>> +
>>> +int main()
>>> +{
>>> +  test_all();
>>>  }
>>> diff --git a/libstdc++-v3/testsuite/std/format/tuple.cc
>>> b/libstdc++-v3/testsuite/std/format/tuple.cc
>>> index eace82730f0..10e19149935 100644
>>> --- a/libstdc++-v3/testsuite/std/format/tuple.cc
>>> +++ b/libstdc++-v3/testsuite/std/format/tuple.cc
>>> @@ -2,6 +2,12 @@
>>>  // { dg-options "-fexec-charset=UTF-8" }
>>>  // { dg-timeout-factor 2 }
>>>
>>> +#if __cplusplus >= 202400L
>>> +# define constexpr26 constexpr
>>> +#else
>>> +# define constexpr26
>>> +#endif
>>> +
>>>  #include <format>
>>>  #include <string>
>>>  #include <testsuite_hooks.h>
>>> @@ -15,7 +21,7 @@ static_assert( !std::formattable<std::pair<int,
>>> NotFormattable>, char> );
>>>  static_assert( !std::formattable<std::tuple<int, NotFormattable, int>,
>>> wchar_t> );
>>>
>>>  template<typename... Args>
>>> -bool
>>> +constexpr26 bool
>>>  is_format_string_for(const char* str, Args&&... args)
>>>  {
>>>    try {
>>> @@ -27,7 +33,7 @@ is_format_string_for(const char* str, Args&&... args)
>>>  }
>>>
>>>  template<typename... Args>
>>> -bool
>>> +constexpr26 bool
>>>  is_format_string_for(const wchar_t* str, Args&&... args)
>>>  {
>>>    try {
>>> @@ -41,6 +47,7 @@ is_format_string_for(const wchar_t* str, Args&&...
>>> args)
>>>  #define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
>>>  #define WIDEN(S) WIDEN_(CharT, S)
>>>
>>> +// not constexpr because of PR124145
>>>  void
>>>  test_format_string()
>>>  {
>>> @@ -123,7 +130,8 @@ void test_multi()
>>>  }
>>>
>>>  template<typename CharT, typename Tuple>
>>> -void test_empty()
>>> +constexpr26 void
>>> +test_empty()
>>>  {
>>>    std::basic_string<CharT> res;
>>>
>>> @@ -142,7 +150,8 @@ void test_empty()
>>>  }
>>>
>>>  template<typename CharT, typename Pair>
>>> -void test_pair()
>>> +constexpr26 void
>>> +test_pair()
>>>  {
>>>    using Ft = std::remove_cvref_t<std::tuple_element_t<0, Pair>>;
>>>    using St = std::remove_cvref_t<std::tuple_element_t<1, Pair>>;
>>> @@ -167,7 +176,8 @@ void test_pair()
>>>  }
>>>
>>>  template<typename CharT, template<typename, typename> class PairT>
>>> -void test_pair_e()
>>> +constexpr26 void
>>> +test_pair_e()
>>>  {
>>>    test_pair<CharT, PairT<int, std::basic_string<CharT>>>();
>>>    test_pair<CharT, PairT<int, const CharT*>>();
>>> @@ -196,7 +206,7 @@ struct std::formatter<MyPair<Pair>, CharT>
>>>    { return _formatter.parse(pc);  }
>>>
>>>    template<typename Out>
>>> -  typename std::basic_format_context<Out, CharT>::iterator
>>> +  constexpr26 typename std::basic_format_context<Out, CharT>::iterator
>>>    format(const MyPair<Pair>& mp,
>>>          std::basic_format_context<Out, CharT>& fc) const
>>>    { return _formatter.format(mp, fc); }
>>> @@ -206,7 +216,8 @@ private:
>>>  };
>>>
>>>  template<typename CharT, template<typename, typename> class PairT>
>>> -void test_custom()
>>> +constexpr26 void
>>> +test_custom()
>>>  {
>>>    std::basic_string<CharT> res;
>>>    MyPair<PairT<int, const CharT*>> c1(1, WIDEN("abc"));
>>> @@ -228,9 +239,12 @@ void test_custom()
>>>  }
>>>
>>>  template<typename CharT>
>>> -void test_outputs()
>>> +constexpr26 void
>>> +test_outputs()
>>>  {
>>> -  test_multi<CharT>();
>>> +  if (!std::is_constant_evaluated())
>>> +    test_multi<CharT>();
>>> +
>>>    test_empty<CharT, std::tuple<>>();
>>>    test_pair_e<CharT, std::pair>();
>>>    test_pair_e<CharT, std::tuple>();
>>> @@ -238,7 +252,8 @@ void test_outputs()
>>>    test_custom<CharT, std::tuple>();
>>>  }
>>>
>>> -void test_nested()
>>> +constexpr26 void
>>> +test_nested()
>>>  {
>>>    std::string res;
>>>    std::tuple<std::tuple<>, std::pair<int, std::string>> tt{{}, {1,
>>> "abc"}};
>>> @@ -251,7 +266,8 @@ void test_nested()
>>>    VERIFY( res == R"((): (1, "abc"))" );
>>>  }
>>>
>>> -bool strip_quote(std::string_view& v)
>>> +constexpr26 bool
>>> +strip_quote(std::string_view& v)
>>>  {
>>>    if (!v.starts_with('"'))
>>>      return false;
>>> @@ -259,7 +275,8 @@ bool strip_quote(std::string_view& v)
>>>    return true;
>>>  }
>>>
>>> -bool strip_prefix(std::string_view& v, std::string_view expected, bool
>>> quoted = false)
>>> +constexpr26 bool
>>> +strip_prefix(std::string_view& v, std::string_view expected, bool
>>> quoted = false)
>>>  {
>>>    if (quoted && !strip_quote(v))
>>>      return false;
>>> @@ -271,7 +288,8 @@ bool strip_prefix(std::string_view& v,
>>> std::string_view expected, bool quoted =
>>>    return true;
>>>  }
>>>
>>> -bool strip_parens(std::string_view& v)
>>> +constexpr26 bool
>>> +strip_parens(std::string_view& v)
>>>  {
>>>    if (!v.starts_with('(') || !v.ends_with(')'))
>>>      return false;
>>> @@ -280,7 +298,8 @@ bool strip_parens(std::string_view& v)
>>>    return true;
>>>  }
>>>
>>> -bool strip_prefix(std::string_view& v, size_t n, char c)
>>> +constexpr26 bool
>>> +strip_prefix(std::string_view& v, size_t n, char c)
>>>  {
>>>    size_t pos = v.find_first_not_of(c);
>>>    if (pos == std::string_view::npos)
>>> @@ -291,7 +310,8 @@ bool strip_prefix(std::string_view& v, size_t n,
>>> char c)
>>>    return true;
>>>  }
>>>
>>> -void test_padding()
>>> +constexpr26 void
>>> +test_padding()
>>>  {
>>>    std::string res;
>>>    std::string_view resv;
>>> @@ -351,13 +371,14 @@ struct std::formatter<Custom, CharT>
>>>    { return pc.begin();  }
>>>
>>>    template<typename Out>
>>> -  typename std::basic_format_context<Out, CharT>::iterator
>>> +  constexpr26 typename std::basic_format_context<Out, CharT>::iterator
>>>    format(Custom, const std::basic_format_context<Out, CharT>& fc) const
>>>    { return fc.out(); }
>>>  };
>>>
>>>  template<template<typename...> typename Tuple>
>>> -void test_nonblocking()
>>> +constexpr26 void
>>> +test_nonblocking()
>>>  {
>>>    static_assert(std::enable_nonlocking_formatter_optimization<
>>>                   Tuple<int, float>>);
>>> @@ -374,14 +395,31 @@ void test_nonblocking()
>>>                   Tuple<Custom&, float&>>);
>>>  }
>>>
>>> -int main()
>>> +constexpr26 bool
>>> +test_all()
>>>  {
>>> -  test_format_string();
>>>    test_outputs<char>();
>>> -  test_outputs<wchar_t>();
>>>    test_nested();
>>>    test_padding();
>>>
>>>    test_nonblocking<std::pair>();
>>>    test_nonblocking<std::tuple>();
>>> +
>>> +  if (!std::is_constant_evaluated())
>>> +    {
>>> +      test_format_string();
>>> +      // constexpr wide formatting not yet implemented
>>> +      test_outputs<wchar_t>();
>>> +    }
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +#if __cplusplus >= 202400L
>>> +static_assert(test_all());
>>> +#endif
>>> +
>>> +int main()
>>> +{
>>> +  test_all();
>>>  }
>>> --
>>> 2.43.0
>>>
>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260302/1f7463d9/attachment-0001.htm>


More information about the Libstdc++ mailing list