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

Ivan Lazaric ivan.lazaric1@gmail.com
Wed Mar 18 23:02:59 GMT 2026


Yep, I assumed that this is low priority due to targeting GCC17, thanks for
clarifying!

On Wed, Mar 18, 2026 at 3:30 PM Tomasz Kaminski <tkaminsk@redhat.com> wrote:

>
>
> On Tue, Mar 10, 2026 at 4:02 PM Ivan Lazaric <ivan.lazaric1@gmail.com>
> wrote:
>
>> This patch implements constexpr formatting from P3391R2,
>> and introduces the constexpr_format feature-test macro.
>> Since pre-cxx11 cow_string is not constexpr-enabled,
>> only exposing the feature-test macro under cxx11 ABI.
>>
>> Add `__format::__toupper_numeric` 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.
>>
>> Mark `basic_format_string` consteval constructor noexcept,
>> since exceptions are now constexpr, and the standard mandates
>> failure to parse to be non-catchable ill-formed.
>> https://eel.is/c++draft/format#fmt.string-3
>> > Remarks: A call to this function is not a core constant expression
>> > ([expr.const]) unless there exist args of types Args such that
>> > str is a format string for args.
>>
>> Update some formatting tests to test constexpr as well,
>> and introduce a dedicated smoke test for constexpr formatting.
>>
>> libstdc++-v3/include/ChangeLog:
>>
>>         * bits/version.def: Add constexpr_format.
>>         * bits/version.h: Regenerate.
>>         * std/format:
>>         Expose constexpr_format feature-test macro,
>>         constexpr-ify most functions, replace memcpy with ranges::copy.
>>         (__format::__toupper_numeric): Define.
>>         (__format::__do_vformat_to): Avoid using _Ptr_sink in constexpr.
>>
>> libstdc++-v3/testsuite/ChangeLog:
>>
>>         * std/format/arguments/args_neg.cc: Diagnostics change.
>>         * std/format/constexpr.cc: New test.
>>         * std/format/debug.cc: Constexpr testing.
>>         * std/format/functions/format.cc: Constexpr testing.
>>         * std/format/functions/format_to.cc: Constexpr testing.
>>         * std/format/functions/size.cc: Constexpr testing.
>>         * std/format/ranges/format_kind.cc: Constexpr testing.
>>         * std/format/ranges/formatter.cc: Constexpr testing.
>>         * std/format/ranges/sequence.cc: Constexpr testing.
>>         * std/format/runtime_format.cc: Constexpr testing.
>>         * std/format/string.cc: Constexpr testing.
>>         * std/format/tuple.cc: Constexpr testing.
>>         * std/time/format/data_not_present_neg.cc: Diagnostics change.
>>
>> Signed-off-by: Ivan Lazaric <ivan.lazaric1@gmail.com>
>> ---
>> Rebased, no unmerged patches anymore
>> Restricted to CXX11 ABI
>> Guarding tests and constexpr-ification with __glibcxx_constexpr_format
>>
> As mentioned previously, we will target these patches (this and to_string)
> for GCC17,
> i.e. after GCC16 is released. If you will not be able to do it, I will
> take care of updating and
> merging them.
>
>>
>>  libstdc++-v3/include/bits/version.def         |  12 +
>>  libstdc++-v3/include/bits/version.h           |   9 +
>>  libstdc++-v3/include/std/format               | 393 +++++++++++-------
>>  .../std/format/arguments/args_neg.cc          |   4 +-
>>  .../testsuite/std/format/constexpr.cc         | 166 ++++++++
>>  libstdc++-v3/testsuite/std/format/debug.cc    |  82 ++--
>>  .../testsuite/std/format/functions/format.cc  | 281 +++++++------
>>  .../std/format/functions/format_to.cc         |  58 ++-
>>  .../testsuite/std/format/functions/size.cc    |  23 +-
>>  .../std/format/ranges/format_kind.cc          |  15 +-
>>  .../testsuite/std/format/ranges/formatter.cc  |  37 +-
>>  .../testsuite/std/format/ranges/sequence.cc   |  64 ++-
>>  .../testsuite/std/format/runtime_format.cc    |  25 +-
>>  libstdc++-v3/testsuite/std/format/string.cc   |  59 ++-
>>  libstdc++-v3/testsuite/std/format/tuple.cc    |  70 +++-
>>  .../std/time/format/data_not_present_neg.cc   |   3 +-
>>  16 files changed, 914 insertions(+), 387 deletions(-)
>>  create mode 100644 libstdc++-v3/testsuite/std/format/constexpr.cc
>>
>> diff --git a/libstdc++-v3/include/bits/version.def
>> b/libstdc++-v3/include/bits/version.def
>> index dbe95b8b79f..6a1ee0b0579 100644
>> --- a/libstdc++-v3/include/bits/version.def
>> +++ b/libstdc++-v3/include/bits/version.def
>> @@ -1330,6 +1330,18 @@ ftms = {
>>    };
>>  };
>>
>> +ftms = {
>> +  name = constexpr_format;
>> +  // 202511 P3391R2 constexpr std::format
>> +  no_stdname = true; // in progress
>> +  values = {
>> +    v = 202511;
>> +    cxxmin = 26;
>> +    hosted = yes;
>> +    cxx11abi = yes;
>> +  };
>> +};
>> +
>>  ftms = {
>>    name = format_uchar;
>>    values = {
>> diff --git a/libstdc++-v3/include/bits/version.h
>> b/libstdc++-v3/include/bits/version.h
>> index eee99847490..f690c46c739 100644
>> --- a/libstdc++-v3/include/bits/version.h
>> +++ b/libstdc++-v3/include/bits/version.h
>> @@ -1476,6 +1476,15 @@
>>  #endif /* !defined(__cpp_lib_format) */
>>  #undef __glibcxx_want_format
>>
>> +#if !defined(__cpp_lib_constexpr_format)
>> +# if (__cplusplus >  202302L) && _GLIBCXX_USE_CXX11_ABI &&
>> _GLIBCXX_HOSTED
>> +#  define __glibcxx_constexpr_format 202511L
>> +#  if defined(__glibcxx_want_all) ||
>> defined(__glibcxx_want_constexpr_format)
>> +#  endif
>> +# endif
>> +#endif /* !defined(__cpp_lib_constexpr_format) */
>> +#undef __glibcxx_want_constexpr_format
>> +
>>  #if !defined(__cpp_lib_format_uchar)
>>  # if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED
>>  #  define __glibcxx_format_uchar 202311L
>> diff --git a/libstdc++-v3/include/std/format
>> b/libstdc++-v3/include/std/format
>> index 4297bcc1007..bcbb5211227 100644
>> --- a/libstdc++-v3/include/std/format
>> +++ b/libstdc++-v3/include/std/format
>> @@ -39,6 +39,7 @@
>>  #define __glibcxx_want_format_ranges
>>  #define __glibcxx_want_format_uchar
>>  #define __glibcxx_want_constexpr_exceptions
>> +#define __glibcxx_want_constexpr_format
>>  #include <bits/version.h>
>>
>>  #ifdef __cpp_lib_format // C++ >= 20 && HOSTED
>> @@ -67,6 +68,12 @@
>>  # include <cctype>
>>  #endif
>>
>> +#ifdef __glibcxx_constexpr_format // C++ >= 26 && HOSTED && CXX11 strings
>> +# define _GLIBCXX_CONSTEXPR_FORMAT constexpr
>> +#else
>> +# define _GLIBCXX_CONSTEXPR_FORMAT
>> +#endif
>> +
>>  #pragma GCC diagnostic push
>>  #pragma GCC diagnostic ignored "-Wpedantic" // __int128
>>  #pragma GCC diagnostic ignored "-Wc++23-extensions" // bf16
>> @@ -128,6 +135,7 @@ namespace __format
>>      struct _Runtime_format_string
>>      {
>>        [[__gnu__::__always_inline__]]
>> +      _GLIBCXX_CONSTEXPR_FORMAT
>>        _Runtime_format_string(basic_string_view<_CharT> __s) noexcept
>>        : _M_str(__s) { }
>>
>> @@ -170,9 +178,10 @@ namespace __format
>>        template<typename _Tp>
>>         requires convertible_to<const _Tp&, basic_string_view<_CharT>>
>>         consteval
>> -       basic_format_string(const _Tp& __s);
>> +       basic_format_string(const _Tp& __s) noexcept;
>>
>>        [[__gnu__::__always_inline__]]
>> +      _GLIBCXX_CONSTEXPR_FORMAT
>>        basic_format_string(__format::_Runtime_format_string<_CharT> __s)
>> noexcept
>>        : _M_str(__s._M_str)
>>        { }
>> @@ -197,13 +206,13 @@ namespace __format
>>
>>  #if __cpp_lib_format >= 202311L // >= C++26
>>    [[__gnu__::__always_inline__]]
>> -  inline __format::_Runtime_format_string<char>
>> +  inline _GLIBCXX_CONSTEXPR_FORMAT __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 _GLIBCXX_CONSTEXPR_FORMAT
>> __format::_Runtime_format_string<wchar_t>
>>    runtime_format(wstring_view __fmt) noexcept
>>    { return __fmt; }
>>  #endif
>> @@ -238,7 +247,7 @@ namespace __format
>>
>>    /// @cond undocumented
>>    [[noreturn]]
>> -  inline void
>> +  inline _GLIBCXX_CONSTEXPR_FORMAT void
>>    __throw_format_error(const char* __what)
>>    { _GLIBCXX_THROW_OR_ABORT(format_error(__what)); }
>>
>> @@ -249,27 +258,27 @@ namespace __format
>>    // XXX use named functions for each constexpr error?
>>
>>    [[noreturn]]
>> -  inline void
>> +  inline _GLIBCXX_CONSTEXPR_FORMAT void
>>    __unmatched_left_brace_in_format_string()
>>    { __throw_format_error("format error: unmatched '{' in format
>> string"); }
>>
>>    [[noreturn]]
>> -  inline void
>> +  inline _GLIBCXX_CONSTEXPR_FORMAT void
>>    __unmatched_right_brace_in_format_string()
>>    { __throw_format_error("format error: unmatched '}' in format
>> string"); }
>>
>>    [[noreturn]]
>> -  inline void
>> +  inline _GLIBCXX_CONSTEXPR_FORMAT void
>>    __conflicting_indexing_in_format_string()
>>    { __throw_format_error("format error: conflicting indexing style in
>> format string"); }
>>
>>    [[noreturn]]
>> -  inline void
>> +  inline _GLIBCXX_CONSTEXPR_FORMAT void
>>    __invalid_arg_id_in_format_string()
>>    { __throw_format_error("format error: invalid arg-id in format
>> string"); }
>>
>>    [[noreturn]]
>> -  inline void
>> +  inline _GLIBCXX_CONSTEXPR_FORMAT void
>>    __failed_to_parse_format_spec()
>>    { __throw_format_error("format error: failed to parse format-spec"); }
>>
>> @@ -517,7 +526,7 @@ namespace __format
>>    using enum _WidthPrec;
>>
>>    template<typename _Context>
>> -    size_t
>> +    _GLIBCXX_CONSTEXPR_FORMAT size_t
>>      __int_from_arg(const basic_format_arg<_Context>& __arg);
>>
>>    constexpr bool __is_digit(char __c)
>> @@ -750,7 +759,7 @@ namespace __format
>>        }
>>
>>        template<typename _Context>
>> -       size_t
>> +       _GLIBCXX_CONSTEXPR_FORMAT size_t
>>         _M_get_width(_Context& __ctx) const
>>         {
>>           size_t __width = 0;
>> @@ -762,7 +771,7 @@ namespace __format
>>         }
>>
>>        template<typename _Context>
>> -       size_t
>> +       _GLIBCXX_CONSTEXPR_FORMAT size_t
>>         _M_get_precision(_Context& __ctx) const
>>         {
>>           size_t __prec = -1;
>> @@ -775,7 +784,7 @@ namespace __format
>>      };
>>
>>    template<typename _Int>
>> -    inline char*
>> +    inline _GLIBCXX_CONSTEXPR_FORMAT char*
>>      __put_sign(_Int __i, _Sign __sign, char* __dest) noexcept
>>      {
>>        if (__i < 0)
>> @@ -792,7 +801,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 _GLIBCXX_CONSTEXPR_FORMAT _Out
>>      __write(_Out __out, basic_string_view<_CharT> __str)
>>      {
>>        if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
>> @@ -809,7 +818,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
>> +    _GLIBCXX_CONSTEXPR_FORMAT _Out
>>      __write_padded(_Out __out, basic_string_view<_CharT> __str,
>>                    _Align __align, size_t __nfill, char32_t __fill_char)
>>      {
>> @@ -883,7 +892,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
>> +    _GLIBCXX_CONSTEXPR_FORMAT _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 +914,7 @@ namespace __format
>>      }
>>
>>     template<typename _CharT>
>> -     size_t
>> +     _GLIBCXX_CONSTEXPR_FORMAT size_t
>>       __truncate(basic_string_view<_CharT>& __s, size_t __prec)
>>       {
>>         if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
>> @@ -1049,7 +1058,7 @@ namespace __format
>>
>>    using uint_least32_t = __UINT_LEAST32_TYPE__;
>>    template<typename _Out, typename _CharT>
>> -    _Out
>> +    _GLIBCXX_CONSTEXPR_FORMAT _Out
>>      __write_escape_seq(_Out __out, uint_least32_t __val,
>>                        basic_string_view<_CharT> __prefix)
>>      {
>> @@ -1079,7 +1088,7 @@ namespace __format
>>      }
>>
>>    template<typename _Out, typename _CharT>
>> -    _Out
>> +    _GLIBCXX_CONSTEXPR_FORMAT _Out
>>      __write_escape_seqs(_Out __out, basic_string_view<_CharT> __units)
>>      {
>>        using _UChar = make_unsigned_t<_CharT>;
>> @@ -1090,7 +1099,7 @@ namespace __format
>>      }
>>
>>    template<typename _Out, typename _CharT>
>> -    _Out
>> +    _GLIBCXX_CONSTEXPR_FORMAT _Out
>>      __write_escaped_char(_Out __out, _CharT __c)
>>      {
>>        using _UChar = make_unsigned_t<_CharT>;
>> @@ -1116,7 +1125,7 @@ namespace __format
>>      }
>>
>>    template<typename _CharT, typename _Out>
>> -    _Out
>> +    _GLIBCXX_CONSTEXPR_FORMAT _Out
>>      __write_escaped_ascii(_Out __out,
>>                           basic_string_view<_CharT> __str,
>>                           _Term_char __term)
>> @@ -1146,7 +1155,7 @@ namespace __format
>>      }
>>
>>    template<typename _CharT, typename _Out>
>> -    _Out
>> +    _GLIBCXX_CONSTEXPR_FORMAT _Out
>>      __write_escaped_unicode_part(_Out __out, basic_string_view<_CharT>&
>> __str,
>>                                  bool& __prev_esc, _Term_char __term)
>>      {
>> @@ -1224,7 +1233,7 @@ namespace __format
>>      }
>>
>>    template<typename _CharT, typename _Out>
>> -    _Out
>> +    _GLIBCXX_CONSTEXPR_FORMAT _Out
>>      __write_escaped_unicode(_Out __out, basic_string_view<_CharT> __str,
>>                             _Term_char __term)
>>      {
>> @@ -1236,7 +1245,7 @@ namespace __format
>>      }
>>
>>    template<typename _CharT, typename _Out>
>> -    _Out
>> +    _GLIBCXX_CONSTEXPR_FORMAT _Out
>>      __write_escaped(_Out __out,  basic_string_view<_CharT> __str,
>> _Term_char __term)
>>      {
>>        __out = __format::__write(__out,
>> _Escapes<_CharT>::_S_term(__term));
>> @@ -1257,12 +1266,14 @@ namespace __format
>>    struct _Optional_locale
>>    {
>>      [[__gnu__::__always_inline__]]
>> +    _GLIBCXX_CONSTEXPR_FORMAT
>>      _Optional_locale() : _M_dummy(), _M_hasval(false) { }
>>
>>      _Optional_locale(const locale& __loc) noexcept
>>      : _M_loc(__loc), _M_hasval(true)
>>      { }
>>
>> +    _GLIBCXX_CONSTEXPR_FORMAT
>>      _Optional_locale(const _Optional_locale& __l) noexcept
>>      : _M_dummy(), _M_hasval(__l._M_hasval)
>>      {
>> @@ -1270,6 +1281,7 @@ namespace __format
>>         std::construct_at(&_M_loc, __l._M_loc);
>>      }
>>
>> +    _GLIBCXX_CONSTEXPR_FORMAT
>>      _Optional_locale&
>>      operator=(const _Optional_locale& __l) noexcept
>>      {
>> @@ -1291,6 +1303,7 @@ namespace __format
>>        return *this;
>>      }
>>
>> +    _GLIBCXX_CONSTEXPR_FORMAT
>>      ~_Optional_locale() { if (_M_hasval) _M_loc.~locale(); }
>>
>>      _Optional_locale&
>> @@ -1317,7 +1330,8 @@ namespace __format
>>        return _M_loc;
>>      }
>>
>> -    bool has_value() const noexcept { return _M_hasval; }
>> +    _GLIBCXX_CONSTEXPR_FORMAT bool
>> +    has_value() const noexcept { return _M_hasval; }
>>
>>      union {
>>        char _M_dummy = '\0';
>> @@ -1391,7 +1405,7 @@ namespace __format
>>        }
>>
>>        template<typename _Out>
>> -       _Out
>> +       _GLIBCXX_CONSTEXPR_FORMAT _Out
>>         format(basic_string_view<_CharT> __s,
>>                basic_format_context<_Out, _CharT>& __fc) const
>>         {
>> @@ -1408,7 +1422,7 @@ namespace __format
>>         }
>>
>>        template<typename _Out>
>> -       _Out
>> +       _GLIBCXX_CONSTEXPR_FORMAT _Out
>>         _M_format_escaped(basic_string_view<_CharT> __s,
>>                           basic_format_context<_Out, _CharT>& __fc) const
>>         {
>> @@ -1433,7 +1447,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
>> +       _GLIBCXX_CONSTEXPR_FORMAT _Out
>>         _M_format_range(_Rg&& __rg, basic_format_context<_Out, _CharT>&
>> __fc) const
>>         {
>>           using _Range = remove_reference_t<_Rg>;
>> @@ -1482,6 +1496,28 @@ namespace __format
>>        _Spec<_CharT> _M_spec{};
>>      };
>>
>> +  // A partial implementation of std::toupper that is constexpr-enabled,
>> +  // sufficient for formatting purposes.
>> +  [[__gnu__::__always_inline__]]
>> +  constexpr char
>> +  __toupper_numeric(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';
>> +      case 'x': return 'X';
>> +      default: return __c;
>> +    }
>> +  }
>> +
>>    template<__char _CharT>
>>      struct __formatter_int
>>      {
>> @@ -1641,6 +1677,7 @@ namespace __format
>>         }
>>
>>        template<typename _Int, typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         format(_Int __i, basic_format_context<_Out, _CharT>& __fc) const
>>         {
>> @@ -1690,11 +1727,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_numeric(*__p);
>>               break;
>>             default:
>>               __builtin_unreachable();
>> @@ -1703,8 +1736,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);
>>
>> @@ -1726,6 +1758,7 @@ namespace __format
>>         }
>>
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         format(bool __i, basic_format_context<_Out, _CharT>& __fc) const
>>         {
>> @@ -1756,6 +1789,7 @@ namespace __format
>>         }
>>
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         _M_format_character(_CharT __c,
>>                             basic_format_context<_Out, _CharT>& __fc)
>> const
>> @@ -1787,7 +1821,7 @@ namespace __format
>>         }
>>
>>        template<typename _Int>
>> -       static _CharT
>> +       static _GLIBCXX_CONSTEXPR_FORMAT _CharT
>>         _S_to_character(_Int __i)
>>         {
>>           using _Traits = __gnu_cxx::__int_traits<_CharT>;
>> @@ -1808,6 +1842,7 @@ namespace __format
>>         }
>>
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         _M_format_int(basic_string_view<_CharT> __str, size_t
>> __prefix_len,
>>                       basic_format_context<_Out, _CharT>& __fc) const
>> @@ -2197,7 +2232,7 @@ namespace __format
>>           if (__upper)
>>             {
>>               for (char* __p = __start; __p != __res.ptr; ++__p)
>> -               *__p = std::toupper(*__p);
>> +               *__p = __format::__toupper_numeric(*__p);
>>             }
>>
>>           bool __have_sign = true;
>> @@ -2508,10 +2543,13 @@ namespace __format
>>        }
>>
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         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);
>> +         auto __u = __v
>> +           ? reinterpret_cast<__UINTPTR_TYPE__>(__v)
>> +           : (__UINTPTR_TYPE__)0;
>>           return __formatter_int<_CharT>(_M_spec).format(__u, __fc);
>>         }
>>
>> @@ -2546,6 +2584,7 @@ namespace __format
>>        }
>>
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         format(_CharT __u, basic_format_context<_Out, _CharT>& __fc) const
>>         {
>> @@ -2584,6 +2623,7 @@ namespace __format
>>        }
>>
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, wchar_t>::iterator
>>         format(char __u, basic_format_context<_Out, wchar_t>& __fc) const
>>         {
>> @@ -2619,6 +2659,7 @@ namespace __format
>>
>>        template<typename _Out>
>>         [[__gnu__::__nonnull__]]
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         format(_CharT* __u, basic_format_context<_Out, _CharT>& __fc)
>> const
>>         { return _M_f.format(__u, __fc); }
>> @@ -2648,6 +2689,7 @@ namespace __format
>>
>>        template<typename _Out>
>>         [[__gnu__::__nonnull__]]
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         format(const _CharT* __u,
>>                basic_format_context<_Out, _CharT>& __fc) const
>> @@ -2678,6 +2720,7 @@ namespace __format
>>        { return _M_f.parse(__pc); }
>>
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         format(const _CharT (&__u)[_Nm],
>>                basic_format_context<_Out, _CharT>& __fc) const
>> @@ -2707,6 +2750,7 @@ namespace __format
>>        { return _M_f.parse(__pc); }
>>
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, char>::iterator
>>         format(const basic_string<char, _Traits, _Alloc>& __u,
>>                basic_format_context<_Out, char>& __fc) const
>> @@ -2739,6 +2783,7 @@ namespace __format
>>        { return _M_f.parse(__pc); }
>>
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         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
>> @@ -2772,6 +2817,7 @@ namespace __format
>>        { return _M_f.parse(__pc); }
>>
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, char>::iterator
>>         format(basic_string_view<char, _Traits> __u,
>>                basic_format_context<_Out, char>& __fc) const
>> @@ -2804,6 +2850,7 @@ namespace __format
>>        { return _M_f.parse(__pc); }
>>
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, wchar_t>::iterator
>>         format(basic_string_view<wchar_t, _Traits> __u,
>>                basic_format_context<_Out, wchar_t>& __fc) const
>> @@ -2867,6 +2914,7 @@ namespace __format
>>        }
>>
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         format(_Tp __u, basic_format_context<_Out, _CharT>& __fc) const
>>         { return _M_f.format(__u, __fc); }
>> @@ -3078,6 +3126,7 @@ namespace __format
>>        { return _M_f.parse(__pc); }
>>
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         format(const void* __v, basic_format_context<_Out, _CharT>& __fc)
>> const
>>         { return _M_f.format(__v, __fc); }
>> @@ -3103,6 +3152,7 @@ namespace __format
>>        { return _M_f.parse(__pc); }
>>
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         format(void* __v, basic_format_context<_Out, _CharT>& __fc) const
>>         { return _M_f.format(__v, __fc); }
>> @@ -3128,6 +3178,7 @@ namespace __format
>>        { return _M_f.parse(__pc); }
>>
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         format(nullptr_t, basic_format_context<_Out, _CharT>& __fc) const
>>         { return _M_f.format(nullptr, __fc); }
>> @@ -3272,11 +3323,11 @@ namespace __format
>>        constexpr _Sink_iter
>>        operator++(int) { return *this; }
>>
>> -      auto
>> +      _GLIBCXX_CONSTEXPR_FORMAT auto
>>        _M_reserve(size_t __n) const
>>        { return _M_sink->_M_reserve(__n); }
>>
>> -      bool
>> +      _GLIBCXX_CONSTEXPR_FORMAT bool
>>        _M_discarding() const
>>        { return _M_sink->_M_discarding(); }
>>      };
>> @@ -3308,7 +3359,7 @@ namespace __format
>>
>>        // The portion of the span that has been written to.
>>        [[__gnu__::__always_inline__]]
>> -      span<_CharT>
>> +      _GLIBCXX_CONSTEXPR_FORMAT span<_CharT>
>>        _M_used() const noexcept
>>        { return _M_span.first(_M_next - _M_span.begin()); }
>>
>> @@ -3325,7 +3376,7 @@ namespace __format
>>        { _M_next = _M_span.begin(); }
>>
>>        // Replace the current output range.
>> -      void
>> +      _GLIBCXX_CONSTEXPR_FORMAT void
>>        _M_reset(span<_CharT> __s, size_t __pos = 0) noexcept
>>        {
>>         _M_span = __s;
>> @@ -3365,11 +3416,14 @@ namespace __format
>>        struct _Reservation
>>        {
>>         // True if the reservation was successful, false otherwise.
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         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->(); }
>> +       _GLIBCXX_CONSTEXPR_FORMAT _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); }
>> +       _GLIBCXX_CONSTEXPR_FORMAT void
>> +       _M_bump(size_t __n) { _M_sink->_M_bump(__n); }
>>         _Sink* _M_sink;
>>        };
>>
>> @@ -3377,7 +3431,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
>> +      _GLIBCXX_CONSTEXPR_FORMAT virtual _Reservation
>>        _M_reserve(size_t __n)
>>        {
>>         if (__n <= _M_unused().size())
>> @@ -3394,12 +3448,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
>> +      _GLIBCXX_CONSTEXPR_FORMAT virtual void
>>        _M_bump(size_t __n)
>>        { _M_next += __n; }
>>
>>        // Returns true if the _Sink is discarding incoming characters.
>> -      virtual bool
>> +      _GLIBCXX_CONSTEXPR_FORMAT virtual bool
>>        _M_discarding() const
>>        { return false; }
>>
>> @@ -3417,7 +3471,7 @@ namespace __format
>>    template<typename _CharT>
>>      class _Fixedbuf_sink final : public _Sink<_CharT>
>>      {
>> -      void
>> +      _GLIBCXX_CONSTEXPR_FORMAT void
>>        _M_overflow() override
>>        {
>>         __glibcxx_assert(false);
>> @@ -3465,7 +3519,7 @@ namespace __format
>>        _Seq _M_seq;
>>      protected:
>>        // Transfer buffer contents to the sequence, so buffer can be
>> refilled.
>> -      void
>> +      _GLIBCXX_CONSTEXPR_FORMAT void
>>        _M_overflow() override
>>        {
>>         auto __s = this->_M_used();
>> @@ -3484,7 +3538,7 @@ namespace __format
>>         this->_M_rewind();
>>        }
>>
>> -      typename _Sink<_CharT>::_Reservation
>> +      _GLIBCXX_CONSTEXPR_FORMAT typename _Sink<_CharT>::_Reservation
>>        _M_reserve(size_t __n) override
>>        {
>>         // We might already have n characters available in
>> this->_M_unused(),
>> @@ -3520,7 +3574,7 @@ namespace __format
>>           return _Sink<_CharT>::_M_reserve(__n);
>>        }
>>
>> -      void
>> +      _GLIBCXX_CONSTEXPR_FORMAT void
>>        _M_bump(size_t __n) override
>>        {
>>         if constexpr (__is_specialization_of<_Seq, basic_string>
>> @@ -3535,7 +3589,8 @@ namespace __format
>>           }
>>        }
>>
>> -      void _M_trim(span<const _CharT> __s)
>> +      _GLIBCXX_CONSTEXPR_FORMAT void
>> +      _M_trim(span<const _CharT> __s)
>>         requires __is_specialization_of<_Seq, basic_string>
>>        {
>>         _GLIBCXX_DEBUG_ASSERT(__s.data() == this->_M_buf
>> @@ -3551,16 +3606,18 @@ namespace __format
>>        // to _M_buf if it overflows? Or even do that for all unused
>> capacity?
>>
>>        [[__gnu__::__always_inline__]]
>> +      _GLIBCXX_CONSTEXPR_FORMAT
>>        _Seq_sink() noexcept(is_nothrow_default_constructible_v<_Seq>)
>>        { }
>>
>> +      _GLIBCXX_CONSTEXPR_FORMAT
>>        _Seq_sink(_Seq&& __s)
>> noexcept(is_nothrow_move_constructible_v<_Seq>)
>>        : _M_seq(std::move(__s))
>>        { }
>>
>>        using _Sink<_CharT>::out;
>>
>> -      _Seq
>> +      _GLIBCXX_CONSTEXPR_FORMAT _Seq
>>        get() &&
>>        {
>>         if (this->_M_used().size() != 0)
>> @@ -3570,7 +3627,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>
>> +      _GLIBCXX_CONSTEXPR_FORMAT span<_CharT>
>>        _M_span()
>>        {
>>         auto __s = this->_M_used();
>> @@ -3583,7 +3640,7 @@ namespace __format
>>         return __s;
>>        }
>>
>> -      basic_string_view<_CharT>
>> +      _GLIBCXX_CONSTEXPR_FORMAT basic_string_view<_CharT>
>>        view()
>>        {
>>         auto __span = _M_span();
>> @@ -3608,7 +3665,7 @@ namespace __format
>>      protected:
>>        size_t _M_count = 0;
>>
>> -      void
>> +      _GLIBCXX_CONSTEXPR_FORMAT void
>>        _M_overflow() override
>>        {
>>         auto __s = this->_M_used();
>> @@ -3628,7 +3685,7 @@ namespace __format
>>         _M_count += __s.size();
>>        }
>>
>> -      bool
>> +      _GLIBCXX_CONSTEXPR_FORMAT bool
>>        _M_discarding() const override
>>        {
>>         // format_to_n return total number of characters, that would be
>> written,
>> @@ -3638,14 +3695,14 @@ namespace __format
>>
>>      public:
>>        [[__gnu__::__always_inline__]]
>> -      explicit
>> +      _GLIBCXX_CONSTEXPR_FORMAT 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>
>> +      _GLIBCXX_CONSTEXPR_FORMAT format_to_n_result<_OutIter>
>>        _M_finish() &&
>>        {
>>         if (this->_M_used().size() != 0)
>> @@ -3674,7 +3731,7 @@ namespace __format
>>        _CharT _M_buf[64]; // Write here after outputting _M_max
>> characters.
>>
>>      protected:
>> -      void
>> +      _GLIBCXX_CONSTEXPR_FORMAT void
>>        _M_overflow() override
>>        {
>>         if (this->_M_unused().size() != 0)
>> @@ -3698,7 +3755,7 @@ namespace __format
>>           }
>>        }
>>
>> -      bool
>> +      _GLIBCXX_CONSTEXPR_FORMAT bool
>>        _M_discarding() const override
>>        {
>>         // format_to_n return total number of characters, that would be
>> written,
>> @@ -3706,7 +3763,7 @@ namespace __format
>>         return false;
>>        }
>>
>> -      typename _Sink<_CharT>::_Reservation
>> +      _GLIBCXX_CONSTEXPR_FORMAT typename _Sink<_CharT>::_Reservation
>>        _M_reserve(size_t __n) final
>>        {
>>         auto __avail = this->_M_unused();
>> @@ -3723,7 +3780,7 @@ namespace __format
>>
>>      private:
>>        template<typename _IterDifference>
>> -       static size_t
>> +       static _GLIBCXX_CONSTEXPR_FORMAT size_t
>>         _S_trim_max(_IterDifference __max)
>>         {
>>           if (__max < 0)
>> @@ -3736,7 +3793,7 @@ namespace __format
>>         }
>>
>>        [[__gnu__::__always_inline__]]
>> -      void
>> +      _GLIBCXX_CONSTEXPR_FORMAT void
>>        _M_rebuf(_CharT* __ptr, size_t __total, size_t __inuse = 0)
>>        {
>>         std::span<_CharT> __span(__ptr, __total);
>> @@ -3744,7 +3801,7 @@ namespace __format
>>        }
>>
>>      public:
>> -      explicit
>> +      _GLIBCXX_CONSTEXPR_FORMAT explicit
>>        _Ptr_sink(_CharT* __ptr, size_t __n = _S_no_limit) noexcept
>>        : _Sink<_CharT>(_M_buf), _M_max(__n)
>>        {
>> @@ -3769,13 +3826,13 @@ namespace __format
>>        }
>>
>>        template<contiguous_iterator _OutIter>
>> -       explicit
>> +       _GLIBCXX_CONSTEXPR_FORMAT 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>
>> +       _GLIBCXX_CONSTEXPR_FORMAT format_to_n_result<_OutIter>
>>         _M_finish(_OutIter __first) const
>>         {
>>           auto __s = this->_M_used();
>> @@ -3817,12 +3874,12 @@ namespace __format
>>        size_t _M_printwidth;
>>
>>        [[__gnu__::__always_inline__]]
>> -      bool
>> +      _GLIBCXX_CONSTEXPR_FORMAT bool
>>        _M_ignoring() const
>>        { return _M_printwidth >= _M_maxwidth; }
>>
>>        [[__gnu__::__always_inline__]]
>> -      bool
>> +      _GLIBCXX_CONSTEXPR_FORMAT bool
>>        _M_buffering() const
>>        {
>>         if (_M_printwidth < _M_padwidth)
>> @@ -3832,7 +3889,7 @@ namespace __format
>>         return false;
>>        }
>>
>> -      void
>> +      _GLIBCXX_CONSTEXPR_FORMAT void
>>        _M_sync_discarding()
>>        {
>>         if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
>> @@ -3840,7 +3897,7 @@ namespace __format
>>             _M_maxwidth = _M_printwidth;
>>        }
>>
>> -      void
>> +      _GLIBCXX_CONSTEXPR_FORMAT void
>>        _M_flush()
>>        {
>>         span<_CharT> __new = this->_M_used();
>> @@ -3850,7 +3907,7 @@ namespace __format
>>         this->_M_rewind();
>>        }
>>
>> -      bool
>> +      _GLIBCXX_CONSTEXPR_FORMAT bool
>>        _M_force_update()
>>        {
>>         auto __str = this->view();
>> @@ -3878,7 +3935,7 @@ namespace __format
>>         return false;
>>        }
>>
>> -      bool
>> +      _GLIBCXX_CONSTEXPR_FORMAT bool
>>        _M_update(size_t __new)
>>        {
>>         _M_printwidth += __new;
>> @@ -3888,7 +3945,7 @@ namespace __format
>>         return true;
>>        }
>>
>> -      void
>> +      _GLIBCXX_CONSTEXPR_FORMAT void
>>        _M_overflow() override
>>        {
>>         // Ignore characters in buffer, and override it.
>> @@ -3903,11 +3960,11 @@ namespace __format
>>           _Str_sink<_CharT>::_M_overflow();
>>        }
>>
>> -      bool
>> +      _GLIBCXX_CONSTEXPR_FORMAT bool
>>        _M_discarding() const override
>>        { return _M_ignoring(); }
>>
>> -      typename _Sink<_CharT>::_Reservation
>> +      _GLIBCXX_CONSTEXPR_FORMAT typename _Sink<_CharT>::_Reservation
>>        _M_reserve(size_t __n) override
>>        {
>>         // Ignore characters in buffer, if any.
>> @@ -3926,7 +3983,7 @@ namespace __format
>>         return _Sink<_CharT>::_M_reserve(__n);
>>        }
>>
>> -      void
>> +      _GLIBCXX_CONSTEXPR_FORMAT void
>>        _M_bump(size_t __n) override
>>        {
>>         // Ignore the written characters.
>> @@ -3941,19 +3998,19 @@ namespace __format
>>
>>      public:
>>        [[__gnu__::__always_inline__]]
>> -      explicit
>> +      _GLIBCXX_CONSTEXPR_FORMAT 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
>> +      _GLIBCXX_CONSTEXPR_FORMAT explicit
>>        _Padding_sink(_Out __out, size_t __padwidth)
>>        : _Padding_sink(std::move(__out), __padwidth, (size_t)-1)
>>        { }
>>
>> -      _Out
>> +      _GLIBCXX_CONSTEXPR_FORMAT _Out
>>        _M_finish(_Align __align, char32_t __fill_char)
>>        {
>>         // Handle any characters in the buffer.
>> @@ -3992,14 +4049,14 @@ namespace __format
>>        unsigned _M_prev_escape : 1;
>>        unsigned _M_out_discards : 1;
>>
>> -      void
>> +      _GLIBCXX_CONSTEXPR_FORMAT void
>>        _M_sync_discarding()
>>        {
>>         if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
>>           _M_out_discards = _M_out._M_discarding();
>>        }
>>
>> -      void
>> +      _GLIBCXX_CONSTEXPR_FORMAT void
>>        _M_write()
>>        {
>>         span<_CharT> __bytes = this->_M_used();
>> @@ -4025,7 +4082,7 @@ namespace __format
>>         _M_sync_discarding();
>>        }
>>
>> -      void
>> +      _GLIBCXX_CONSTEXPR_FORMAT void
>>        _M_overflow() override
>>        {
>>         if (_M_out_discards)
>> @@ -4034,13 +4091,13 @@ namespace __format
>>           _M_write();
>>        }
>>
>> -      bool
>> +      _GLIBCXX_CONSTEXPR_FORMAT bool
>>        _M_discarding() const override
>>        { return _M_out_discards; }
>>
>>      public:
>>        [[__gnu__::__always_inline__]]
>> -      explicit
>> +      _GLIBCXX_CONSTEXPR_FORMAT explicit
>>        _Escaping_sink(_Out __out, _Term_char __term)
>>        : _M_out(std::move(__out)), _M_term(__term),
>>         _M_prev_escape(true), _M_out_discards(false)
>> @@ -4049,7 +4106,7 @@ namespace __format
>>         _M_sync_discarding();
>>        }
>>
>> -      _Out
>> +      _GLIBCXX_CONSTEXPR_FORMAT _Out
>>        _M_finish()
>>        {
>>         if (_M_out_discards)
>> @@ -4101,7 +4158,7 @@ namespace __format
>>                               const _Tp, _Tp>;
>>
>>         template<typename _Tq>
>> -         static void
>> +         static _GLIBCXX_CONSTEXPR_FORMAT void
>>           _S_format(basic_format_parse_context<_CharT>& __parse_ctx,
>>                     _Context& __format_ctx, const void* __ptr)
>>           {
>> @@ -4114,7 +4171,7 @@ namespace __format
>>
>>         template<typename _Tp>
>>           requires (!is_same_v<remove_cv_t<_Tp>, handle>)
>> -         explicit
>> +         explicit _GLIBCXX_CONSTEXPR_FORMAT
>>           handle(_Tp& __val) noexcept
>>           : _M_ptr(__builtin_addressof(__val))
>>           , _M_func(&_S_format<__maybe_const_t<_Tp>>)
>> @@ -4127,7 +4184,7 @@ namespace __format
>>         handle& operator=(const handle&) = default;
>>
>>         [[__gnu__::__always_inline__]]
>> -       void
>> +       void _GLIBCXX_CONSTEXPR_FORMAT
>>         format(basic_format_parse_context<_CharT>& __pc, _Context& __fc)
>> const
>>         { _M_func(__pc, __fc, this->_M_ptr); }
>>
>> @@ -4179,10 +4236,12 @@ namespace __format
>>        };
>>
>>        [[__gnu__::__always_inline__]]
>> +      _GLIBCXX_CONSTEXPR_FORMAT
>>        _Arg_value() : _M_none() { }
>>
>>  #if 0
>>        template<typename _Tp>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         _Arg_value(in_place_type_t<_Tp>, _Tp __val)
>>         { _S_get<_Tp>() = __val; }
>>  #endif
>> @@ -4191,7 +4250,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 _GLIBCXX_CONSTEXPR_FORMAT auto&
>>         _S_access(_Self& __u, _Value... __value) noexcept
>>         {
>>           static_assert(sizeof...(_Value) <= 1);
>> @@ -4255,23 +4314,24 @@ namespace __format
>>           else if constexpr (is_same_v<_Tp, handle>)
>>             return __u._M_handle;
>>           // Otherwise, ill-formed.
>> +         __builtin_unreachable();
>>         }
>>
>>        template<typename _Tp>
>>         [[__gnu__::__always_inline__]]
>> -       auto&
>> +       _GLIBCXX_CONSTEXPR_FORMAT auto&
>>         _M_get() noexcept
>>         { return _S_access<_Tp>(*this); }
>>
>>        template<typename _Tp>
>>         [[__gnu__::__always_inline__]]
>> -       const auto&
>> +       _GLIBCXX_CONSTEXPR_FORMAT const auto&
>>         _M_get() const noexcept
>>         { return _S_access<_Tp>(*this); }
>>
>>        template<typename _Tp>
>>         [[__gnu__::__always_inline__]]
>> -       void
>> +       _GLIBCXX_CONSTEXPR_FORMAT void
>>         _M_set(_Tp __v) noexcept
>>         {
>>           // Explicitly construct types without trivial default
>> constructor.
>> @@ -4291,7 +4351,8 @@ namespace __format
>>      class _Arg_store;
>>
>>    template<typename _Visitor, typename _Ctx>
>> -    decltype(auto) __visit_format_arg(_Visitor&&,
>> basic_format_arg<_Ctx>);
>> +    _GLIBCXX_CONSTEXPR_FORMAT decltype(auto)
>> +    __visit_format_arg(_Visitor&&, basic_format_arg<_Ctx>);
>>
>>    template<typename _Ch, typename _Tp>
>>      consteval _Arg_t
>> @@ -4308,20 +4369,21 @@ namespace __format
>>        using handle = __format::_Arg_value<_Context>::handle;
>>
>>        [[__gnu__::__always_inline__]]
>> +      _GLIBCXX_CONSTEXPR_FORMAT
>>        basic_format_arg() noexcept : _M_type(__format::_Arg_none) { }
>>
>>        [[nodiscard,__gnu__::__always_inline__]]
>> -      explicit operator bool() const noexcept
>> +      explicit _GLIBCXX_CONSTEXPR_FORMAT operator bool() const noexcept
>>        { return _M_type != __format::_Arg_none; }
>>
>>  #if __cpp_lib_format >= 202306L // >= C++26
>>        template<typename _Visitor>
>> -       decltype(auto)
>> +       _GLIBCXX_CONSTEXPR_FORMAT 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
>> +       _GLIBCXX_CONSTEXPR_FORMAT _Res
>>         visit(this basic_format_arg __arg, _Visitor&& __vis)
>>         { return __arg._M_visit_user(std::forward<_Visitor>(__vis),
>> __arg._M_type); }
>>  #endif
>> @@ -4498,7 +4560,7 @@ namespace __format
>>         }
>>
>>        template<typename _Tp>
>> -       void
>> +       _GLIBCXX_CONSTEXPR_FORMAT void
>>         _M_set(_Tp __v) noexcept
>>         {
>>           _M_type = _S_to_enum<_Tp>();
>> @@ -4507,7 +4569,7 @@ namespace __format
>>
>>        template<typename _Tp>
>>         requires __format::__formattable_with<_Tp, _Context>
>> -       explicit
>> +       _GLIBCXX_CONSTEXPR_FORMAT explicit
>>         basic_format_arg(_Tp& __v) noexcept
>>         {
>>           using _Td = _Normalize<_Tp>;
>> @@ -4521,15 +4583,15 @@ namespace __format
>>         }
>>
>>        template<typename _Ctx, typename... _Argz>
>> -       friend auto
>> +       friend _GLIBCXX_CONSTEXPR_FORMAT auto
>>         make_format_args(_Argz&...) noexcept;
>>
>>        template<typename _Visitor, typename _Ctx>
>> -       friend decltype(auto)
>> +       friend _GLIBCXX_CONSTEXPR_FORMAT decltype(auto)
>>         visit_format_arg(_Visitor&& __vis, basic_format_arg<_Ctx>);
>>
>>        template<typename _Visitor, typename _Ctx>
>> -       friend decltype(auto)
>> +       friend _GLIBCXX_CONSTEXPR_FORMAT decltype(auto)
>>         __format::__visit_format_arg(_Visitor&&, basic_format_arg<_Ctx>);
>>
>>        template<typename _Ch, typename _Tp>
>> @@ -4537,7 +4599,7 @@ namespace __format
>>         __format::__to_arg_t_enum() noexcept;
>>
>>        template<typename _Visitor>
>> -       decltype(auto)
>> +       _GLIBCXX_CONSTEXPR_FORMAT decltype(auto)
>>         _M_visit(_Visitor&& __vis, __format::_Arg_t __type)
>>         {
>>           using namespace __format;
>> @@ -4612,7 +4674,7 @@ namespace __format
>>         }
>>
>>        template<typename _Visitor>
>> -       decltype(auto)
>> +       _GLIBCXX_CONSTEXPR_FORMAT decltype(auto)
>>         _M_visit_user(_Visitor&& __vis, __format::_Arg_t __type)
>>         {
>>           return _M_visit([&__vis]<typename _Tp>(_Tp& __val) ->
>> decltype(auto)
>> @@ -4636,7 +4698,7 @@ namespace __format
>>
>>    template<typename _Visitor, typename _Context>
>>      _GLIBCXX26_DEPRECATED_SUGGEST("std::basic_format_arg::visit")
>> -    inline decltype(auto)
>> +    inline _GLIBCXX_CONSTEXPR_FORMAT decltype(auto)
>>      visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg)
>>      {
>>        return __arg._M_visit_user(std::forward<_Visitor>(__vis),
>> __arg._M_type);
>> @@ -4646,7 +4708,7 @@ namespace __format
>>  namespace __format
>>  {
>>    template<typename _Visitor, typename _Ctx>
>> -    inline decltype(auto)
>> +    inline _GLIBCXX_CONSTEXPR_FORMAT decltype(auto)
>>      __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Ctx> __arg)
>>      {
>>        return __arg._M_visit(std::forward<_Visitor>(__vis),
>> __arg._M_type);
>> @@ -4655,7 +4717,7 @@ namespace __format
>>    struct _WidthPrecVisitor
>>    {
>>      template<typename _Tp>
>> -      size_t
>> +      _GLIBCXX_CONSTEXPR_FORMAT size_t
>>        operator()(_Tp& __arg) const
>>        {
>>         if constexpr (is_same_v<_Tp, monostate>)
>> @@ -4681,7 +4743,7 @@ namespace __format
>>  #pragma GCC diagnostic push
>>  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
>>    template<typename _Context>
>> -    inline size_t
>> +    inline _GLIBCXX_CONSTEXPR_FORMAT size_t
>>      __int_from_arg(const basic_format_arg<_Context>& __arg)
>>      { return __format::__visit_format_arg(_WidthPrecVisitor(), __arg); }
>>
>> @@ -4729,11 +4791,11 @@ namespace __format
>>         const _Format_arg* _M_args;       // Active when _M_packed_size
>> == 0
>>        };
>>
>> -      size_t
>> +      _GLIBCXX_CONSTEXPR_FORMAT size_t
>>        _M_size() const noexcept
>>        { return _M_packed_size ? _M_packed_size : _M_unpacked_size; }
>>
>> -      typename __format::_Arg_t
>> +      _GLIBCXX_CONSTEXPR_FORMAT typename __format::_Arg_t
>>        _M_type(size_t __i) const noexcept
>>        {
>>         uint64_t __t = _M_unpacked_size >> (__i * _S_packed_type_bits);
>> @@ -4741,7 +4803,7 @@ namespace __format
>>        }
>>
>>        template<typename _Ctx, typename... _Args>
>> -       friend auto
>> +       friend _GLIBCXX_CONSTEXPR_FORMAT auto
>>         make_format_args(_Args&...) noexcept;
>>
>>        // An array of _Arg_t enums corresponding to _Args...
>> @@ -4752,10 +4814,11 @@ namespace __format
>>
>>      public:
>>        template<typename... _Args>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         basic_format_args(const _Store<_Args...>& __store) noexcept;
>>
>>        [[nodiscard,__gnu__::__always_inline__]]
>> -      basic_format_arg<_Context>
>> +      _GLIBCXX_CONSTEXPR_FORMAT basic_format_arg<_Context>
>>        get(size_t __i) const noexcept
>>        {
>>         basic_format_arg<_Context> __arg;
>> @@ -4777,7 +4840,7 @@ namespace __format
>>        -> basic_format_args<_Context>;
>>
>>    template<typename _Context, typename... _Args>
>> -    auto
>> +    _GLIBCXX_CONSTEXPR_FORMAT auto
>>      make_format_args(_Args&... __fmt_args) noexcept;
>>
>>    // An array of type-erased formatting arguments.
>> @@ -4787,7 +4850,7 @@ namespace __format
>>        friend std::basic_format_args<_Context>;
>>
>>        template<typename _Ctx, typename... _Argz>
>> -       friend auto std::
>> +       friend _GLIBCXX_CONSTEXPR_FORMAT auto std::
>>  #if _GLIBCXX_INLINE_VERSION
>>         __8:: // Needed for PR c++/59256
>>  #endif
>> @@ -4806,7 +4869,7 @@ namespace __format
>>        _Element_t _M_args[sizeof...(_Args)];
>>
>>        template<typename _Tp>
>> -       static _Element_t
>> +       static _GLIBCXX_CONSTEXPR_FORMAT _Element_t
>>         _S_make_elt(_Tp& __v)
>>         {
>>           using _Tq = remove_const_t<_Tp>;
>> @@ -4832,6 +4895,7 @@ namespace __format
>>        template<typename... _Tp>
>>         requires (sizeof...(_Tp) == sizeof...(_Args))
>>         [[__gnu__::__always_inline__]]
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         _Arg_store(_Tp&... __a) noexcept
>>         : _M_args{_S_make_elt(__a)...}
>>         { }
>> @@ -4843,7 +4907,7 @@ namespace __format
>>
>>    template<typename _Context>
>>      template<typename... _Args>
>> -      inline
>> +      inline _GLIBCXX_CONSTEXPR_FORMAT
>>        basic_format_args<_Context>::
>>        basic_format_args(const _Store<_Args...>& __store) noexcept
>>        {
>> @@ -4877,7 +4941,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 _GLIBCXX_CONSTEXPR_FORMAT auto
>>      make_format_args(_Args&... __fmt_args) noexcept
>>      {
>>        using _Fmt_arg = basic_format_arg<_Context>;
>> @@ -4890,7 +4954,7 @@ namespace __format
>>    /// Capture formatting arguments for use by `std::vformat` (for wide
>> output).
>>    template<typename... _Args>
>>      [[nodiscard,__gnu__::__always_inline__]]
>> -    inline auto
>> +    inline _GLIBCXX_CONSTEXPR_FORMAT auto
>>      make_wformat_args(_Args&... __args) noexcept
>>      { return std::make_format_args<wformat_context>(__args...); }
>>  #endif
>> @@ -4899,7 +4963,7 @@ namespace __format
>>  namespace __format
>>  {
>>    template<typename _Out, typename _CharT, typename _Context>
>> -    _Out
>> +    _GLIBCXX_CONSTEXPR_FORMAT _Out
>>      __do_vformat_to(_Out, basic_string_view<_CharT>,
>>                     const basic_format_args<_Context>&,
>>                     const locale* = nullptr);
>> @@ -4931,11 +4995,13 @@ namespace __format
>>        _Out _M_out;
>>        __format::_Optional_locale _M_loc;
>>
>> +      _GLIBCXX_CONSTEXPR_FORMAT
>>        basic_format_context(basic_format_args<basic_format_context>
>> __args,
>>                            _Out __out)
>>        : _M_args(__args), _M_out(std::move(__out))
>>        { }
>>
>> +      _GLIBCXX_CONSTEXPR_FORMAT
>>        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)
>> @@ -4948,7 +5014,7 @@ namespace __format
>>        basic_format_context& operator=(const basic_format_context&) =
>> delete;
>>
>>        template<typename _Out2, typename _CharT2, typename _Context2>
>> -       friend _Out2
>> +       friend _GLIBCXX_CONSTEXPR_FORMAT _Out2
>>         __format::__do_vformat_to(_Out2, basic_string_view<_CharT2>,
>>                                   const basic_format_args<_Context2>&,
>>                                   const locale*);
>> @@ -4964,7 +5030,7 @@ namespace __format
>>         using formatter_type = formatter<_Tp, _CharT>;
>>
>>        [[nodiscard]]
>> -      basic_format_arg<basic_format_context>
>> +      _GLIBCXX_CONSTEXPR_FORMAT basic_format_arg<basic_format_context>
>>        arg(size_t __id) const noexcept
>>        { return _M_args.get(__id); }
>>
>> @@ -4972,9 +5038,11 @@ namespace __format
>>        std::locale locale() { return _M_loc.value(); }
>>
>>        [[nodiscard]]
>> -      iterator out() { return std::move(_M_out); }
>> +      _GLIBCXX_CONSTEXPR_FORMAT iterator
>> +      out() { return std::move(_M_out); }
>>
>> -      void advance_to(iterator __it) { _M_out = std::move(__it); }
>> +      _GLIBCXX_CONSTEXPR_FORMAT void
>> +      advance_to(iterator __it) { _M_out = std::move(__it); }
>>      };
>>
>>
>> @@ -5113,6 +5181,7 @@ namespace __format
>>      class _Formatting_scanner : public _Scanner<_CharT>
>>      {
>>      public:
>> +      _GLIBCXX_CONSTEXPR_FORMAT
>>        _Formatting_scanner(basic_format_context<_Out, _CharT>& __fc,
>>                           basic_string_view<_CharT> __str)
>>        : _Scanner<_CharT>(__str), _M_fc(__fc)
>> @@ -5220,7 +5289,7 @@ namespace __format
>>      };
>>
>>    template<typename _Out, typename _CharT, typename _Context>
>> -    inline _Out
>> +    inline _GLIBCXX_CONSTEXPR_FORMAT _Out
>>      __do_vformat_to(_Out __out, basic_string_view<_CharT> __fmt,
>>                     const basic_format_args<_Context>& __args,
>>                     const locale* __loc)
>> @@ -5240,7 +5309,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;
>>                         }
>> @@ -5278,7 +5347,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;
>>                         }
>> @@ -5296,14 +5365,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;
>> @@ -5311,7 +5382,7 @@ namespace __format
>>      }
>>
>>    template<typename _Out, typename _CharT>
>> -    format_to_n_result<_Out>
>> +    _GLIBCXX_CONSTEXPR_FORMAT 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<
>> @@ -5351,7 +5422,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>()...
>>             };
>> @@ -5369,7 +5444,7 @@ namespace __format
>>        requires convertible_to<const _Tp&, basic_string_view<_CharT>>
>>        consteval
>>        basic_format_string<_CharT, _Args...>::
>> -      basic_format_string(const _Tp& __s)
>> +      basic_format_string(const _Tp& __s) noexcept
>>        : _M_str(__s)
>>        {
>>         __format::_Checking_scanner<_CharT, remove_cvref_t<_Args>...>
>> @@ -5381,14 +5456,14 @@ namespace __format
>>
>>    template<typename _Out> requires output_iterator<_Out, const char&>
>>      [[__gnu__::__always_inline__]]
>> -    inline _Out
>> +    inline _GLIBCXX_CONSTEXPR_FORMAT _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 _GLIBCXX_CONSTEXPR_FORMAT _Out
>>      vformat_to(_Out __out, wstring_view __fmt, wformat_args __args)
>>      { return __format::__do_vformat_to(std::move(__out), __fmt, __args);
>> }
>>  #endif
>> @@ -5414,7 +5489,7 @@ namespace __format
>>  #endif
>>
>>    [[nodiscard]]
>> -  inline string
>> +  inline _GLIBCXX_CONSTEXPR_FORMAT string
>>    vformat(string_view __fmt, format_args __args)
>>    {
>>      __format::_Str_sink<char> __buf;
>> @@ -5424,7 +5499,7 @@ namespace __format
>>
>>  #ifdef _GLIBCXX_USE_WCHAR_T
>>    [[nodiscard]]
>> -  inline wstring
>> +  inline _GLIBCXX_CONSTEXPR_FORMAT wstring
>>    vformat(wstring_view __fmt, wformat_args __args)
>>    {
>>      __format::_Str_sink<wchar_t> __buf;
>> @@ -5455,14 +5530,14 @@ namespace __format
>>
>>    template<typename... _Args>
>>      [[nodiscard]]
>> -    inline string
>> +    inline _GLIBCXX_CONSTEXPR_FORMAT 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 _GLIBCXX_CONSTEXPR_FORMAT wstring
>>      format(wformat_string<_Args...> __fmt, _Args&&... __args)
>>      { return std::vformat(__fmt.get(),
>> std::make_wformat_args(__args...)); }
>>  #endif
>> @@ -5491,7 +5566,7 @@ namespace __format
>>
>>    template<typename _Out, typename... _Args>
>>      requires output_iterator<_Out, const char&>
>> -    inline _Out
>> +    inline _GLIBCXX_CONSTEXPR_FORMAT _Out
>>      format_to(_Out __out, format_string<_Args...> __fmt, _Args&&...
>> __args)
>>      {
>>        return std::vformat_to(std::move(__out), __fmt.get(),
>> @@ -5501,7 +5576,7 @@ namespace __format
>>  #ifdef _GLIBCXX_USE_WCHAR_T
>>    template<typename _Out, typename... _Args>
>>      requires output_iterator<_Out, const wchar_t&>
>> -    inline _Out
>> +    inline _GLIBCXX_CONSTEXPR_FORMAT _Out
>>      format_to(_Out __out, wformat_string<_Args...> __fmt, _Args&&...
>> __args)
>>      {
>>        return std::vformat_to(std::move(__out), __fmt.get(),
>> @@ -5533,7 +5608,7 @@ namespace __format
>>
>>    template<typename _Out, typename... _Args>
>>      requires output_iterator<_Out, const char&>
>> -    inline format_to_n_result<_Out>
>> +    inline _GLIBCXX_CONSTEXPR_FORMAT format_to_n_result<_Out>
>>      format_to_n(_Out __out, iter_difference_t<_Out> __n,
>>                 format_string<_Args...> __fmt, _Args&&... __args)
>>      {
>> @@ -5545,7 +5620,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 _GLIBCXX_CONSTEXPR_FORMAT format_to_n_result<_Out>
>>      format_to_n(_Out __out, iter_difference_t<_Out> __n,
>>                 wformat_string<_Args...> __fmt, _Args&&... __args)
>>      {
>> @@ -5587,10 +5662,11 @@ namespace __format
>>      class _Counting_sink final : public _Ptr_sink<_CharT>
>>      {
>>      public:
>> +      _GLIBCXX_CONSTEXPR_FORMAT
>>        _Counting_sink() : _Ptr_sink<_CharT>(nullptr, 0) { }
>>
>>        [[__gnu__::__always_inline__]]
>> -      size_t
>> +      _GLIBCXX_CONSTEXPR_FORMAT size_t
>>        count() const
>>        { return this->_M_count + this->_M_used().size(); }
>>      };
>> @@ -5625,7 +5701,7 @@ namespace __format
>>
>>    template<typename... _Args>
>>      [[nodiscard]]
>> -    inline size_t
>> +    inline _GLIBCXX_CONSTEXPR_FORMAT size_t
>>      formatted_size(format_string<_Args...> __fmt, _Args&&... __args)
>>      {
>>        __format::_Counting_sink<char> __buf;
>> @@ -5637,7 +5713,7 @@ namespace __format
>>  #ifdef _GLIBCXX_USE_WCHAR_T
>>    template<typename... _Args>
>>      [[nodiscard]]
>> -    inline size_t
>> +    inline _GLIBCXX_CONSTEXPR_FORMAT size_t
>>      formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args)
>>      {
>>        __format::_Counting_sink<wchar_t> __buf;
>> @@ -5708,6 +5784,7 @@ namespace __format
>>  namespace __format
>>  {
>>    template<typename _CharT, typename _Out, typename _Callback>
>> +    _GLIBCXX_CONSTEXPR_FORMAT
>>      typename basic_format_context<_Out, _CharT>::iterator
>>      __format_padded(basic_format_context<_Out, _CharT>& __fc,
>>                     const _Spec<_CharT>& __spec,
>> @@ -5727,14 +5804,16 @@ namespace __format
>>
>>          struct _Restore_out
>>          {
>> +          _GLIBCXX_CONSTEXPR_FORMAT
>>            _Restore_out(basic_format_context<_Sink_iter<_CharT>, _CharT>&
>> __fc)
>>            : _M_ctx(std::addressof(__fc)), _M_out(__fc.out())
>>           { }
>>
>> -         void
>> +         _GLIBCXX_CONSTEXPR_FORMAT void
>>           _M_disarm()
>>           { _M_ctx = nullptr; }
>>
>> +         _GLIBCXX_CONSTEXPR_FORMAT
>>           ~_Restore_out()
>>           {
>>             if (_M_ctx)
>> @@ -5768,7 +5847,7 @@ namespace __format
>>        }
>>
>>        template<typename _Out>
>> -       void
>> +       _GLIBCXX_CONSTEXPR_FORMAT void
>>         _M_format(__maybe_const<_Tp, _CharT>& __elem,
>>                   basic_format_context<_Out, _CharT>& __fc,
>>                   basic_string_view<_CharT> __sep) const
>> @@ -5866,12 +5945,14 @@ namespace __format
>>
>>      protected:
>>        template<typename _Tuple, typename _Out, size_t... _Ids>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         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>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         _M_format_elems(__maybe_const<_Tps, _CharT>&... __elems,
>>                         basic_format_context<_Out, _CharT>& __fc) const
>> @@ -5901,7 +5982,7 @@ namespace __format
>>           }
>>
>>           template<typename _Out>
>> -           void
>> +           _GLIBCXX_CONSTEXPR_FORMAT void
>>             _M_format(__maybe_const<_Tps, _CharT>&... __elems,
>>                       basic_format_context<_Out, _CharT>& __fc,
>>                       _String_view __sep) const
>> @@ -5917,7 +5998,7 @@ namespace __format
>>         };
>>
>>        template<size_t... _Ids>
>> -       static auto
>> +       static _GLIBCXX_CONSTEXPR_FORMAT auto
>>         _S_create_storage(index_sequence<_Ids...>)
>>           -> __formatters_storage<_Ids...>;
>>        using _Formatters
>> @@ -5953,6 +6034,7 @@ namespace __format
>>        // We deviate from standard, that declares this as template
>> accepting
>>        // unconstrained FormatContext type, which seems unimplementable.
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         format(__maybe_const_pair& __p,
>>                basic_format_context<_Out, _CharT>& __fc) const
>> @@ -5980,6 +6062,7 @@ namespace __format
>>        // We deviate from standard, that declares this as template
>> accepting
>>        // unconstrained FormatContext type, which seems unimplementable.
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         format(__maybe_const_tuple& __t,
>>                basic_format_context<_Out, _CharT>& __fc) const
>> @@ -6143,6 +6226,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>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         format(_Rg&& __rg, basic_format_context<_Out, _CharT>& __fc) const
>>         {
>> @@ -6155,6 +6239,7 @@ namespace __format
>>
>>      private:
>>        template<ranges::input_range _Rg, typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         _M_format(_Rg& __rg, basic_format_context<_Out, _CharT>& __fc)
>> const
>>         {
>> @@ -6172,6 +6257,7 @@ namespace __format
>>
>>
>>        template<ranges::input_range _Rg, typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         _M_format_elems(_Rg& __rg,
>>                         basic_format_context<_Out, _CharT>& __fc) const
>> @@ -6271,6 +6357,7 @@ namespace __format
>>        // We deviate from standard, that declares this as template
>> accepting
>>        // unconstrained FormatContext type, which seems unimplementable.
>>        template<typename _Out>
>> +       _GLIBCXX_CONSTEXPR_FORMAT
>>         typename basic_format_context<_Out, _CharT>::iterator
>>         format(__format::__maybe_const_range<_Rg, _CharT>& __rg,
>>                basic_format_context<_Out, _CharT>& __fc) const
>> @@ -6297,6 +6384,8 @@ namespace __format
>>
>>  #endif // C++23 formatting ranges
>>  #undef _GLIBCXX_WIDEN
>> +#undef _GLIBCXX_WIDEN_
>> +#undef _GLIBCXX_CONSTEXPR_FORMAT
>>
>>  _GLIBCXX_END_NAMESPACE_VERSION
>>  } // namespace std
>> diff --git a/libstdc++-v3/testsuite/std/format/arguments/args_neg.cc
>> b/libstdc++-v3/testsuite/std/format/arguments/args_neg.cc
>> index 83c7b22d081..6894d6c4fc3 100644
>> --- a/libstdc++-v3/testsuite/std/format/arguments/args_neg.cc
>> +++ b/libstdc++-v3/testsuite/std/format/arguments/args_neg.cc
>> @@ -15,7 +15,7 @@ void test_missing_specialization()
>>  {
>>    struct X { };
>>    X x;
>> -  (void)std::make_format_args(x); // { dg-error "here" }
>> +  (void)std::make_format_args(x); // { dg-error "(here|in 'constexpr'
>> expansion of)" }
>>  // { dg-error "std::formatter must be specialized" "" { target *-*-* } 0
>> }
>>  }
>>
>> @@ -37,7 +37,7 @@ void test(std::formatter<Y>& f,
>> std::format_parse_context& pc) {
>>  void test_const_arg()
>>  {
>>    const Y y;
>> -  (void)std::make_format_args(y); // { dg-error "here" }
>> +  (void)std::make_format_args(y); // { dg-error "(here|in 'constexpr'
>> expansion of)" }
>>  // { dg-error "format arg must be non-const" "" { target *-*-* } 0 }
>>  }
>>
>> diff --git a/libstdc++-v3/testsuite/std/format/constexpr.cc
>> b/libstdc++-v3/testsuite/std/format/constexpr.cc
>> new file mode 100644
>> index 00000000000..7f806081f4e
>> --- /dev/null
>> +++ b/libstdc++-v3/testsuite/std/format/constexpr.cc
>> @@ -0,0 +1,166 @@
>> +// { dg-do compile { target c++26 } }
>> +
>> +#include <format>
>> +#include <string>
>> +#include <string_view>
>> +#include <tuple>
>> +#include <vector>
>> +#include <testsuite_hooks.h>
>> +
>> +#if _GLIBCXX_USE_CXX11_ABI
>> +
>> +#ifndef __glibcxx_constexpr_format
>> +# error "Feature test macro for constexpr std::format is missing in
>> <format>"
>> +#elif __glibcxx_constexpr_format < 202511L
>> +# error "Feature test macro for constexpr std::format has wrong value in
>> <format>"
>> +#endif
>> +
>> +// Slightly more general from __format::_Widen, works with character
>> literals.
>> +template<typename CharT>
>> +consteval auto widen(auto narrow, auto wide)
>> +{
>> +  if constexpr (std::is_same_v<CharT, wchar_t>)
>> +    return wide;
>> +  else
>> +    return narrow;
>> +}
>> +
>> +#define WIDEN_(C, S) widen<C>(S, L##S)
>> +#define WIDEN(S) WIDEN_(CharT, S)
>> +
>> +template<typename CharT>
>> +constexpr void
>> +test_format()
>> +{
>> +  using namespace std;
>> +
>> +  basic_string<CharT> res;
>> +
>> +  res = format(WIDEN("{}"), WIDEN('c'));
>> +  VERIFY( res == WIDEN("c") );
>> +  res = format(WIDEN("{1} {0} {0}"), WIDEN('a'), WIDEN('b'));
>> +  VERIFY( res == WIDEN("b a a") );
>> +  res = format(WIDEN("{:?}"), WIDEN('\n'));
>> +  VERIFY( res == WIDEN("'\\n'") );
>> +  res = format(WIDEN("{:.^10}"), WIDEN("hello"));
>> +  VERIFY( res == WIDEN("..hello...") );
>> +  res = format(WIDEN("{:.>{}}"), WIDEN("world"), 8);
>> +  VERIFY( res == WIDEN("...world") );
>> +  res = format(WIDEN("{:+#06X}"), 0xa);
>> +  VERIFY( res == WIDEN("+0X00A") );
>> +  res = format(WIDEN("{:p}"), nullptr);
>> +  VERIFY( res == WIDEN("0x0") );
>> +  res = format(WIDEN("{:07P}"), nullptr);
>> +  VERIFY( res == WIDEN("0X00000") );
>> +  res = format(WIDEN("{} {}"), true, false);
>> +  VERIFY( res == WIDEN("true false") );
>> +  res = format(WIDEN("{:+#06b}"), true);
>> +  VERIFY( res == WIDEN("+0b001") );
>> +  res = format(WIDEN("{} {} {}"), WIDEN("abc"),
>> basic_string_view<CharT>(WIDEN("def")), basic_string<CharT>(WIDEN("ghi")));
>> +  VERIFY( res == WIDEN("abc def ghi") );
>> +  res = format(WIDEN("{:?}"), WIDEN("hello\nworld"));
>> +  VERIFY( res == WIDEN("\"hello\\nworld\"") );
>> +  res = format(WIDEN("{}"), tuple(1, true));
>> +  VERIFY( res == WIDEN("(1, true)") );
>> +  res = format(WIDEN("{:t<12m}"), tuple(WIDEN('a'), WIDEN("bc")));
>> +  VERIFY( res == WIDEN("'a': \"bc\"ttt") );
>> +  res = format(WIDEN("{:n}"), tuple(nullptr, -1, 1));
>> +  VERIFY( res == WIDEN("0x0, -1, 1") );
>> +  res = format(WIDEN("{}"), vector{1, 2, 3, 4});
>> +  VERIFY( res == WIDEN("[1, 2, 3, 4]") );
>> +  res = format(WIDEN("{:?s}"), vector{WIDEN('a'), WIDEN('\n'),
>> WIDEN('b')});
>> +  VERIFY( res == WIDEN("\"a\\nb\"") );
>> +  res = format(WIDEN("{:n:+}"), vector{1, 2, 3});
>> +  VERIFY( res == WIDEN("+1, +2, +3") );
>> +}
>> +
>> +template<typename CharT>
>> +constexpr void
>> +test_format_to()
>> +{
>> +  using namespace std;
>> +
>> +  CharT buf[100];
>> +  CharT* out;
>> +
>> +  out = format_to(buf, WIDEN("{:.^5}"), WIDEN("foo"));
>> +  VERIFY( basic_string_view<CharT>(buf, out) == WIDEN(".foo.") );
>> +  out = format_to(buf, WIDEN("{} {}"), nullptr, true);
>> +  VERIFY( basic_string_view<CharT>(buf, out) == WIDEN("0x0 true") );
>> +}
>> +
>> +template<typename CharT>
>> +constexpr void
>> +test_vformat()
>> +{
>> +  using namespace std;
>> +  using context = __format::__format_context<CharT>;
>> +
>> +  basic_string<CharT> res;
>> +
>> +  int arg1 = 1;
>> +  CharT arg2 = WIDEN('a');
>> +  bool arg3 = true;
>> +  res = vformat(WIDEN("{} {:?} {}"), make_format_args<context>(arg1,
>> arg2, arg3));
>> +  VERIFY( res == WIDEN("1 'a' true") );
>> +}
>> +
>> +template<typename CharT>
>> +constexpr void
>> +test_vformat_to()
>> +{
>> +  using namespace std;
>> +  using context = __format::__format_context<CharT>;
>> +
>> +  CharT buf[100];
>> +  CharT* out;
>> +
>> +  nullptr_t arg1 = nullptr;
>> +  basic_string<CharT> arg2 = WIDEN("foo");
>> +  tuple<int, int> arg3{-3, 5};
>> +  out = vformat_to(buf, WIDEN("{} {:?} {}"),
>> make_format_args<context>(arg1, arg2, arg3));
>> +  VERIFY( basic_string_view<CharT>(buf, out) == WIDEN("0x0 \"foo\" (-3,
>> 5)") );
>> +}
>> +
>> +template<typename CharT>
>> +constexpr void
>> +test_format_to_n()
>> +{
>> +  using namespace std;
>> +
>> +  CharT buf[100];
>> +  format_to_n_result<CharT*> out;
>> +  int n;
>> +
>> +  n = 100;
>> +  out = format_to_n(buf, n, WIDEN("{:+} {:?} {}"), 1, WIDEN("\n\n"),
>> vector{1, 2, 3});
>> +  VERIFY( out.size <= n );
>> +  VERIFY( out.out - buf == out.size );
>> +  VERIFY( basic_string_view<CharT>(buf, out.size) == WIDEN("+1
>> \"\\n\\n\" [1, 2, 3]") );
>> +  n = 12;
>> +  out = format_to_n(buf, n, WIDEN("{} {} {}"), true, nullptr,
>> WIDEN("long string"));
>> +  VERIFY( out.size > n );
>> +  VERIFY( out.out - buf == n );
>> +  VERIFY( basic_string_view<CharT>(buf, out.out) == WIDEN("true 0x0
>> lon") );
>> +}
>> +
>> +constexpr bool
>> +all_tests()
>> +{
>> +  test_format<char>();
>> +  test_format<wchar_t>();
>> +  test_format_to<char>();
>> +  test_format_to<wchar_t>();
>> +  test_vformat<char>();
>> +  test_vformat<wchar_t>();
>> +  test_vformat_to<char>();
>> +  test_vformat_to<wchar_t>();
>> +  test_format_to_n<char>();
>> +  test_format_to_n<wchar_t>();
>> +
>> +  return true;
>> +}
>> +
>> +static_assert(all_tests());
>> +
>> +#endif // _GLIBCXX_USE_CXX11_ABI
>> diff --git a/libstdc++-v3/testsuite/std/format/debug.cc
>> b/libstdc++-v3/testsuite/std/format/debug.cc
>> index 43e930c579e..3b8b5b9874c 100644
>> --- a/libstdc++-v3/testsuite/std/format/debug.cc
>> +++ b/libstdc++-v3/testsuite/std/format/debug.cc
>> @@ -1,5 +1,5 @@
>> -// { 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 }
>> @@ -8,19 +8,25 @@
>>  #include <format>
>>  #include <testsuite_hooks.h>
>>
>> -std::string
>> +#ifdef __glibcxx_constexpr_format
>> +# define CONSTEXPR constexpr
>> +#else
>> +# define CONSTEXPR
>> +#endif
>> +
>> +CONSTEXPR std::string
>>  fdebug(char t)
>>  { return std::format("{:?}", t); }
>>
>> -std::wstring
>> +CONSTEXPR std::wstring
>>  fdebug(wchar_t t)
>>  { return std::format(L"{:?}", t); }
>>
>> -std::string
>> +CONSTEXPR std::string
>>  fdebug(std::string_view t)
>>  { return std::format("{:?}", t); }
>>
>> -std::wstring
>> +CONSTEXPR std::wstring
>>  fdebug(std::wstring_view t)
>>  { return std::format(L"{:?}", t); }
>>
>> @@ -29,7 +35,7 @@ fdebug(std::wstring_view t)
>>  #define WIDEN(S) WIDEN_(CharT, S)
>>
>>  template<typename CharT>
>> -void
>> +CONSTEXPR void
>>  test_basic_escapes()
>>  {
>>    std::basic_string<CharT> res;
>> @@ -72,7 +78,7 @@ test_basic_escapes()
>>  }
>>
>>  template<typename CharT>
>> -void
>> +CONSTEXPR void
>>  test_ascii_escapes()
>>  {
>>    std::basic_string<CharT> res;
>> @@ -89,7 +95,7 @@ test_ascii_escapes()
>>  }
>>
>>  template<typename CharT>
>> -void
>> +CONSTEXPR void
>>  test_extended_ascii()
>>  {
>>    std::basic_string<CharT> res;
>> @@ -117,7 +123,7 @@ test_extended_ascii()
>>  }
>>
>>  template<typename CharT>
>> -void
>> +CONSTEXPR void
>>  test_unicode_escapes()
>>  {
>>  #if UNICODE_ENC
>> @@ -166,7 +172,7 @@ test_unicode_escapes()
>>  }
>>
>>  template<typename CharT>
>> -void
>> +CONSTEXPR void
>>  test_grapheme_extend()
>>  {
>>  #if UNICODE_ENC
>> @@ -192,7 +198,7 @@ test_grapheme_extend()
>>  }
>>
>>  template<typename CharT>
>> -void
>> +CONSTEXPR void
>>  test_replacement_char()
>>  {
>>  #if UNICODE_ENC
>> @@ -206,7 +212,7 @@ test_replacement_char()
>>  #endif // UNICODE_ENC
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_ill_formed_utf8_seq()
>>  {
>>  #if UNICODE_ENC
>> @@ -244,7 +250,7 @@ test_ill_formed_utf8_seq()
>>  #endif // UNICODE_ENC
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_ill_formed_utf32()
>>  {
>>  #if UNICODE_ENC
>> @@ -269,7 +275,7 @@ test_ill_formed_utf32()
>>  }
>>
>>  template<typename CharT>
>> -void
>> +CONSTEXPR void
>>  test_fill()
>>  {
>>    std::basic_string<CharT> res;
>> @@ -315,7 +321,7 @@ test_fill()
>>  }
>>
>>  template<typename CharT>
>> -void
>> +CONSTEXPR void
>>  test_prec()
>>  {
>>    std::basic_string<CharT> res;
>> @@ -341,7 +347,8 @@ test_prec()
>>  #endif // UNICODE_ENC
>>  }
>>
>> -bool strip_quote(std::string_view& v)
>> +CONSTEXPR 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)
>> +CONSTEXPR 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)
>> +CONSTEXPR 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()
>> +CONSTEXPR void
>> +test_padding()
>>  {
>>    std::string res;
>>    std::string_view resv;
>> @@ -719,7 +729,8 @@ void test_padding()
>>  #endif // UNICODE_ENC
>>  }
>>
>> -void test_char_as_wchar()
>> +CONSTEXPR void
>> +test_char_as_wchar()
>>  {
>>    std::wstring res;
>>
>> @@ -751,8 +762,9 @@ struct std::formatter<DebugWrapper<T>, CharT>
>>    }
>>
>>    template<typename Out>
>> -  Out format(DebugWrapper<T> const& t,
>> -            std::basic_format_context<Out, CharT>& fc) const
>> +  CONSTEXPR Out
>> +  format(DebugWrapper<T> const& t,
>> +        std::basic_format_context<Out, CharT>& fc) const
>>    { return under.format(t.val, fc); }
>>
>>  private:
>> @@ -760,7 +772,7 @@ private:
>>  };
>>
>>  template<typename CharT, typename StrT>
>> -void
>> +CONSTEXPR void
>>  test_formatter_str()
>>  {
>>    CharT buf[]{ 'a', 'b', 'c', 0 };
>> @@ -770,7 +782,7 @@ test_formatter_str()
>>  }
>>
>>  template<typename CharT>
>> -void
>> +CONSTEXPR void
>>  test_formatter_arr()
>>  {
>>    std::basic_string<CharT> res;
>> @@ -786,7 +798,7 @@ test_formatter_arr()
>>  }
>>
>>  template<typename CharT, typename SrcT>
>> -void
>> +CONSTEXPR void
>>  test_formatter_char()
>>  {
>>    DebugWrapper<SrcT> in{ 'a' };
>> @@ -795,7 +807,7 @@ test_formatter_char()
>>  }
>>
>>  template<typename CharT>
>> -void
>> +CONSTEXPR void
>>  test_formatters()
>>  {
>>    test_formatter_char<CharT, CharT>();
>> @@ -806,7 +818,7 @@ test_formatters()
>>    test_formatter_arr<CharT>();
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_formatters_c()
>>  {
>>    test_formatters<char>();
>> @@ -814,7 +826,8 @@ test_formatters_c()
>>    test_formatter_char<wchar_t, char>();
>>  }
>>
>> -int main()
>> +CONSTEXPR bool
>> +test_all()
>>  {
>>    test_basic_escapes<char>();
>>    test_basic_escapes<wchar_t>();
>> @@ -840,4 +853,15 @@ int main()
>>    test_padding();
>>
>>    test_formatters_c();
>> +
>> +  return true;
>> +}
>> +
>> +#ifdef __glibcxx_constexpr_format
>> +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..88e95a788b5 100644
>> --- a/libstdc++-v3/testsuite/std/format/functions/format.cc
>> +++ b/libstdc++-v3/testsuite/std/format/functions/format.cc
>> @@ -5,6 +5,12 @@
>>
>>  #include <format>
>>
>> +#ifdef __glibcxx_constexpr_format
>> +# define CONSTEXPR constexpr
>> +#else
>> +# define CONSTEXPR
>> +#endif
>> +
>>  #ifndef __cpp_lib_format
>>  # error "Feature test macro for std::format is missing in <format>"
>>  #elif __cpp_lib_format < 202110L
>> @@ -41,7 +47,7 @@
>>  #include <cstdio>
>>  #include <testsuite_hooks.h>
>>
>> -void
>> +CONSTEXPR void
>>  test_no_args()
>>  {
>>    std::string s;
>> @@ -55,7 +61,7 @@ test_no_args()
>>    VERIFY( s == "128bpm }" );
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_unescaped()
>>  {
>>  #ifdef __cpp_exceptions
>> @@ -78,7 +84,7 @@ struct brit_punc : std::numpunct<char>
>>    std::string do_falsename() const override { return "nah bruv"; }
>>  };
>>
>> -void
>> +CONSTEXPR void
>>  test_std_examples()
>>  {
>>    using namespace std;
>> @@ -125,10 +131,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 +152,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
>> +CONSTEXPR void
>>  test_alternate_forms()
>>  {
>>    std::string s;
>> @@ -180,23 +190,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 +288,7 @@ test_locale()
>>    std::locale::global(cloc);
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_width()
>>  {
>>    std::string s;
>> @@ -317,7 +330,7 @@ test_width()
>>    }
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_char()
>>  {
>>    std::string s;
>> @@ -347,7 +360,7 @@ test_char()
>>    VERIFY( s == "11110000 11110000 240 360 f0 F0" );
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_wchar()
>>  {
>>    using namespace std::literals;
>> @@ -356,24 +369,27 @@ test_wchar()
>>    s = std::format(L"{}", L'a');
>>    VERIFY( s == L"a" );
>>
>> -  s = std::format(L"{} {} {} {} {} {}", L'0', 1, 2LL, 3.4, L"five",
>> L"six"s);
>> -  VERIFY( s == L"0 1 2 3.4 five six" );
>> -
>> -  std::locale loc;
>> -  s = std::format(loc, L"{:L} {:.3s}{:Lc}", true, L"data"sv, '.');
>> -  VERIFY( s == L"true dat." );
>> -
>> -  s = std::format(L"{}", 0.0625);
>> -  VERIFY( s == L"0.0625" );
>> -  s = std::format(L"{}", 0.25);
>> -  VERIFY( s == L"0.25" );
>> -  s = std::format(L"{:+a} {:A}", 0x1.23p45, -0x1.abcdefp-15);
>> -  VERIFY( s == L"+1.23p+45 -1.ABCDEFP-15" );
>> -
>> -  double inf = std::numeric_limits<double>::infinity();
>> -  double nan = std::numeric_limits<double>::quiet_NaN();
>> -  s = std::format(L"{0} {0:F} {1} {1:E}", -inf, -nan);
>> -  VERIFY( s == L"-inf -INF -nan -NAN" );
>> +  if (!std::is_constant_evaluated())
>> +    {
>> +      s = std::format(L"{} {} {} {} {} {}", L'0', 1, 2LL, 3.4, L"five",
>> L"six"s);
>> +      VERIFY( s == L"0 1 2 3.4 five six" );
>> +
>> +      std::locale loc;
>> +      s = std::format(loc, L"{:L} {:.3s}{:Lc}", true, L"data"sv, '.');
>> +      VERIFY( s == L"true dat." );
>> +
>> +      s = std::format(L"{}", 0.0625);
>> +      VERIFY( s == L"0.0625" );
>> +      s = std::format(L"{}", 0.25);
>> +      VERIFY( s == L"0.25" );
>> +      s = std::format(L"{:+a} {:A}", 0x1.23p45, -0x1.abcdefp-15);
>> +      VERIFY( s == L"+1.23p+45 -1.ABCDEFP-15" );
>> +
>> +      double inf = std::numeric_limits<double>::infinity();
>> +      double nan = std::numeric_limits<double>::quiet_NaN();
>> +      s = std::format(L"{0} {0:F} {1} {1:E}", -inf, -nan);
>> +      VERIFY( s == L"-inf -INF -nan -NAN" );
>> +    }
>>
>>    s = std::format(L"{0:#b} {0:#B} {0:#x} {0:#X}", 99);
>>    VERIFY( s == L"0b1100011 0B1100011 0x63 0X63" );
>> @@ -382,20 +398,23 @@ test_wchar()
>>    s = std::format(L"{:d} {:d}", wchar_t(-1), char(-1));
>>    VERIFY( s.find('-') == std::wstring::npos );
>>
>> -  auto ws = std::format(L"{:L}", 0.5);
>> -  VERIFY( ws == L"0.5" );
>> -  // The default C locale.
>> -  std::locale cloc = std::locale::classic();
>> -  // PR libstdc++/119671 use-after-free formatting floating-point to
>> wstring
>> -  ws = std::format(cloc, L"{:L}", 0.5);
>> -  VERIFY( ws == L"0.5" );
>> -  // A locale with no name, but with the same facets as the C locale.
>> -  std::locale locx(cloc, &std::use_facet<std::ctype<char>>(cloc));
>> -  ws = std::format(locx, L"{:L}", 0.5);
>> -  VERIFY( ws == L"0.5" );
>> +  if (!std::is_constant_evaluated())
>> +    {
>> +      auto ws = std::format(L"{:L}", 0.5);
>> +      VERIFY( ws == L"0.5" );
>> +      // The default C locale.
>> +      std::locale cloc = std::locale::classic();
>> +      // PR libstdc++/119671 use-after-free formatting floating-point to
>> wstring
>> +      ws = std::format(cloc, L"{:L}", 0.5);
>> +      VERIFY( ws == L"0.5" );
>> +      // A locale with no name, but with the same facets as the C locale.
>> +      std::locale locx(cloc, &std::use_facet<std::ctype<char>>(cloc));
>> +      ws = std::format(locx, L"{:L}", 0.5);
>> +      VERIFY( ws == L"0.5" );
>> +    }
>>  }
>>
>> -void
>> +CONSTEXPR 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
>> +CONSTEXPR 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
>> +CONSTEXPR 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
>> +CONSTEXPR void
>>  test_bool()
>>  {
>>    std::string s;
>> @@ -519,7 +547,7 @@ test_bool()
>>    VERIFY( s == "0 0x1 0X0" );
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_unicode()
>>  {
>>  #ifdef UNICODE
>> @@ -579,13 +607,13 @@ test_unicode()
>>  #endif
>>  }
>>
>> -int main()
>> +CONSTEXPR bool
>> +test_all()
>>  {
>>    test_no_args();
>>    test_unescaped();
>>    test_std_examples();
>>    test_alternate_forms();
>> -  test_locale();
>>    test_width();
>>    test_char();
>>    test_wchar();
>> @@ -594,4 +622,21 @@ int main()
>>    test_pointer();
>>    test_bool();
>>    test_unicode();
>> +
>> +  if (!std::is_constant_evaluated())
>> +    {
>> +      test_infnan();
>> +      test_locale();
>> +    }
>> +
>> +  return true;
>> +}
>> +
>> +#ifdef __glibcxx_constexpr_format
>> +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..ec6816ddba9 100644
>> --- a/libstdc++-v3/testsuite/std/format/functions/format_to.cc
>> +++ b/libstdc++-v3/testsuite/std/format/functions/format_to.cc
>> @@ -6,22 +6,31 @@
>>  #include <cstring>
>>  #include <testsuite_hooks.h>
>>
>> +#ifdef __glibcxx_constexpr_format
>> +# define CONSTEXPR constexpr
>> +#else
>> +# define CONSTEXPR
>> +#endif
>> +
>>  struct punct : std::numpunct<char>
>>  {
>>    std::string do_grouping() const override { return "\2"; }
>>  };
>>
>> -void
>> +CONSTEXPR 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,17 +38,20 @@ struct wpunct : std::numpunct<wchar_t>
>>    std::string do_grouping() const override { return "\2"; }
>>  };
>>
>> -void
>> +CONSTEXPR void
>>  test_wchar()
>>  {
>>    wchar_t buf[32] = { };
>>    auto out = std::format_to(buf, L"123 + 456 = {}", 579);
>>    VERIFY( out == buf+15 );
>>
>> -  std::locale loc({}, new wpunct);
>> -  auto out2 = std::format_to(buf, loc, L"{:Ld}", 12345);
>> -  VERIFY( out2 == buf+7 );
>> -  VERIFY( std::wstring_view(buf, out2 - buf) == L"1,23,45" );
>> +  if (!std::is_constant_evaluated())
>> +    {
>> +      std::locale loc({}, new wpunct);
>> +      auto out2 = std::format_to(buf, loc, L"{:Ld}", 12345);
>> +      VERIFY( out2 == buf+7 );
>> +      VERIFY( std::wstring_view(buf, out2 - buf) == L"1,23,45" );
>> +    }
>>  }
>>
>>  template<typename I>
>> @@ -50,20 +62,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
>> +CONSTEXPR void
>>  test_move_only()
>>  {
>>    std::string str;
>> @@ -79,7 +91,7 @@ test_move_only()
>>    VERIFY( std::wstring_view(vec.data(), vec.size()) == L"format hat!" );
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_pr110917()
>>  {
>>    // PR libstdc++/110917
>> @@ -90,10 +102,22 @@ test_pr110917()
>>    VERIFY( ! std::memcmp(buf, "abc 123", 7) );
>>  }
>>
>> -int main()
>> +CONSTEXPR bool
>> +test_all()
>>  {
>>    test();
>>    test_wchar();
>>    test_move_only();
>>    test_pr110917();
>> +
>> +  return true;
>> +}
>> +
>> +#ifdef __glibcxx_constexpr_format
>> +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..16029bd5949 100644
>> --- a/libstdc++-v3/testsuite/std/format/functions/size.cc
>> +++ b/libstdc++-v3/testsuite/std/format/functions/size.cc
>> @@ -4,7 +4,13 @@
>>  #include <string>
>>  #include <testsuite_hooks.h>
>>
>> -void
>> +#ifdef __glibcxx_constexpr_format
>> +# define CONSTEXPR constexpr
>> +#else
>> +# define CONSTEXPR
>> +#endif
>> +
>> +CONSTEXPR void
>>  test()
>>  {
>>    auto n = std::formatted_size("");
>> @@ -24,7 +30,7 @@ test()
>>    VERIFY( n == 5 );
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_wchar()
>>  {
>>    auto n = std::formatted_size(L"");
>> @@ -44,8 +50,19 @@ test_wchar()
>>    VERIFY( n == 5 );
>>  }
>>
>> -int main()
>> +CONSTEXPR bool
>> +test_all()
>>  {
>>    test();
>>    test_wchar();
>> +  return true;
>> +}
>> +
>> +#ifdef __glibcxx_constexpr_format
>> +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..49c8246fee2 100644
>> --- a/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc
>> +++ b/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc
>> @@ -12,6 +12,12 @@
>>  #include <unordered_set>
>>  #include <vector>
>>
>> +#ifdef __glibcxx_constexpr_format
>> +# define CONSTEXPR constexpr
>> +#else
>> +# define CONSTEXPR
>> +#endif
>> +
>>  static_assert( std::format_kind<std::vector<int>> ==
>> std::range_format::sequence );
>>  static_assert( std::format_kind<std::deque<int>> ==
>> std::range_format::sequence );
>>  static_assert( std::format_kind<std::list<int>> ==
>> std::range_format::sequence );
>> @@ -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()
>> +CONSTEXPR 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;
>>  }
>>
>> +#ifdef __glibcxx_constexpr_format
>> +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..947e6c3bc60 100644
>> --- a/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
>> +++ b/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
>> @@ -6,6 +6,12 @@
>>  #include <vector>
>>  #include <span>
>>
>> +#ifdef __glibcxx_constexpr_format
>> +# define CONSTEXPR constexpr
>> +#else
>> +# define CONSTEXPR
>> +#endif
>> +
>>  #define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
>>  #define WIDEN(S) WIDEN_(CharT, S)
>>
>> @@ -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
>> +  CONSTEXPR 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
>> +CONSTEXPR 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
>> +CONSTEXPR void
>>  test_override()
>>  {
>>    MyVector<CharT, Formatter> vc{'a', 'b', 'c', 'd'};
>> @@ -115,7 +121,8 @@ test_override()
>>  }
>>
>>  template<template<typename, typename> class Formatter>
>> -void test_outputs()
>> +CONSTEXPR void
>> +test_outputs()
>>  {
>>    test_default<char, Formatter>();
>>    test_default<wchar_t, Formatter>();
>> @@ -123,7 +130,7 @@ void test_outputs()
>>    test_override<wchar_t, Formatter>();
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_nested()
>>  {
>>    MyVector<MyVector<int>> v
>> @@ -152,7 +159,8 @@ struct std::formatter<MyFlatMap, CharT>
>>    : std::range_formatter<MyFlatMap::reference>
>>  {};
>>
>> -void test_const_ref_type_mismatch()
>> +CONSTEXPR void
>> +test_const_ref_type_mismatch()
>>  {
>>    MyFlatMap m{{1, 11}, {2, 22}};
>>    std::string res = std::format("{:m}", m);
>> @@ -163,13 +171,15 @@ template<typename T, typename CharT>
>>  using VectorFormatter = std::formatter<std::vector<T>, CharT>;
>>
>>  template<template<typename> typename Range>
>> -void test_nonblocking()
>> +CONSTEXPR void
>> +test_nonblocking()
>>  {
>>    static_assert(!std::enable_nonlocking_formatter_optimization<
>>                   Range<int>>);
>>  }
>>
>> -int main()
>> +CONSTEXPR bool
>> +test_all()
>>  {
>>    test_outputs<std::range_formatter>();
>>    test_outputs<VectorFormatter>();
>> @@ -179,4 +189,15 @@ int main()
>>    test_nonblocking<std::span>();
>>    test_nonblocking<std::vector>();
>>    test_nonblocking<MyVector>();
>> +
>> +  return true;
>> +}
>> +
>> +#ifdef __glibcxx_constexpr_format
>> +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..cba53b46270 100644
>> --- a/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
>> +++ b/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
>> @@ -1,5 +1,5 @@
>>  // { 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 }
>>
>>  #include <array>
>> @@ -12,6 +12,12 @@
>>  #include <testsuite_iterators.h>
>>  #include <vector>
>>
>> +#ifdef __glibcxx_constexpr_format
>> +# define CONSTEXPR constexpr
>> +#else
>> +# define CONSTEXPR
>> +#endif
>> +
>>  struct NotFormattable
>>  {};
>>
>> @@ -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
>> +CONSTEXPR 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
>> +CONSTEXPR 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)
>> +CONSTEXPR 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,7 +63,7 @@ bool is_range_formatter_spec_for(CharT const* spec,
>> Rg&& rg)
>>    }
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_format_string()
>>  {
>>    // invalid format spec 'p'
>> @@ -79,7 +86,8 @@ test_format_string()
>>  #define WIDEN(S) WIDEN_(CharT, S)
>>
>>  template<typename CharT, typename Range, typename Storage>
>> -void test_output()
>> +CONSTEXPR void
>> +test_output()
>>  {
>>    using Sv = std::basic_string_view<CharT>;
>>    using T = std::ranges::range_value_t<Range>;
>> @@ -153,25 +161,30 @@ void test_output()
>>  }
>>
>>  template<typename Cont>
>> -void test_output_cont()
>> +CONSTEXPR void
>> +test_output_cont()
>>  {
>>    test_output<char, Cont&, Cont>();
>>    test_output<wchar_t, Cont const&, Cont>();
>>  }
>>
>>  template<typename View>
>> -void test_output_view()
>> +CONSTEXPR void
>> +test_output_view()
>>  {
>>    test_output<char, View, int[3]>();
>>    test_output<wchar_t, View, int[3]>();
>>  }
>>
>> -void
>> +CONSTEXPR 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 +198,7 @@ test_outputs()
>>    test_output_view<test_forward_range<const int>>();
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_nested()
>>  {
>>    std::vector<std::vector<int>> v
>> @@ -201,7 +214,8 @@ test_nested()
>>    VERIFY( res == "+[01, 02, 11, 12]+" );
>>  }
>>
>> -bool strip_quote(std::string_view& v)
>> +CONSTEXPR bool
>> +strip_quote(std::string_view& v)
>>  {
>>    if (!v.starts_with('"'))
>>      return false;
>> @@ -209,7 +223,8 @@ bool strip_quote(std::string_view& v)
>>    return true;
>>  }
>>
>> -bool strip_prefix(std::string_view& v, std::string_view expected, bool
>> quoted = false)
>> +CONSTEXPR bool
>> +strip_prefix(std::string_view& v, std::string_view expected, bool quoted
>> = false)
>>  {
>>    if (quoted && !strip_quote(v))
>>      return false;
>> @@ -221,7 +236,8 @@ bool strip_prefix(std::string_view& v,
>> std::string_view expected, bool quoted =
>>    return true;
>>  }
>>
>> -bool strip_squares(std::string_view& v)
>> +CONSTEXPR bool
>> +strip_squares(std::string_view& v)
>>  {
>>    if (!v.starts_with('[') || !v.ends_with(']'))
>>      return false;
>> @@ -230,7 +246,8 @@ bool strip_squares(std::string_view& v)
>>    return true;
>>  }
>>
>> -bool strip_prefix(std::string_view& v, size_t n, char c)
>> +CONSTEXPR 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 +258,8 @@ bool strip_prefix(std::string_view& v, size_t n, char
>> c)
>>    return true;
>>  }
>>
>> -void test_padding()
>> +CONSTEXPR void
>> +test_padding()
>>  {
>>    std::string res;
>>    std::string_view resv;
>> @@ -323,10 +341,22 @@ void test_padding()
>>    VERIFY( check_elems(resv, false) );
>>  }
>>
>> -int main()
>> +CONSTEXPR bool
>> +test_all()
>>  {
>>    test_format_string();
>>    test_outputs();
>>    test_nested();
>>    test_padding();
>> +
>> +  return true;
>> +}
>> +
>> +#ifdef __glibcxx_constexpr_format
>> +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..d18a35ca6a9 100644
>> --- a/libstdc++-v3/testsuite/std/format/runtime_format.cc
>> +++ b/libstdc++-v3/testsuite/std/format/runtime_format.cc
>> @@ -3,7 +3,13 @@
>>  #include <format>
>>  #include <testsuite_hooks.h>
>>
>> -void
>> +#ifdef __glibcxx_constexpr_format
>> +# define CONSTEXPR constexpr
>> +#else
>> +# define CONSTEXPR
>> +#endif
>> +
>> +CONSTEXPR void
>>  test_char()
>>  {
>>    std::string fmt = "{}";
>> @@ -11,7 +17,7 @@ test_char()
>>    VERIFY( s == "123" );
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_wchar()
>>  {
>>    std::wstring fmt = L"{:#o}";
>> @@ -19,7 +25,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 +46,20 @@ 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();
>>    test_internal_api();
>> +  return true;
>> +}
>> +
>> +#ifdef __glibcxx_constexpr_format
>> +static_assert(test_all());
>> +#endif
>> +
>> +int main()
>> +{
>> +  test_all();
>>  }
>> diff --git a/libstdc++-v3/testsuite/std/format/string.cc
>> b/libstdc++-v3/testsuite/std/format/string.cc
>> index ee987a15ec3..004690ad8da 100644
>> --- a/libstdc++-v3/testsuite/std/format/string.cc
>> +++ b/libstdc++-v3/testsuite/std/format/string.cc
>> @@ -1,10 +1,17 @@
>>  // { dg-do run { target c++20 } }
>> +// { dg-options "-fconstexpr-ops-limit=100000000" }
>>
>>  #include <format>
>>  #include <testsuite_hooks.h>
>>
>> +#ifdef __glibcxx_constexpr_format
>> +# define CONSTEXPR constexpr
>> +#else
>> +# define CONSTEXPR
>> +#endif
>> +
>>  template<typename... Args>
>> -bool
>> +CONSTEXPR bool
>>  is_format_string_for(const char* str, Args&&... args)
>>  {
>>    try {
>> @@ -16,7 +23,7 @@ is_format_string_for(const char* str, Args&&... args)
>>  }
>>
>>  template<typename... Args>
>> -bool
>> +CONSTEXPR bool
>>  is_format_string_for(const wchar_t* str, Args&&... args)
>>  {
>>    try {
>> @@ -27,7 +34,7 @@ is_format_string_for(const wchar_t* str, Args&&... args)
>>    }
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_no_args()
>>  {
>>    VERIFY( is_format_string_for("") );
>> @@ -42,7 +49,7 @@ test_no_args()
>>    VERIFY( ! is_format_string_for("{{{{{") );
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_indexing()
>>  {
>>    VERIFY( is_format_string_for("{} to {}", "a", "b") );   // automatic
>> indexing
>> @@ -68,7 +75,7 @@ constexpr bool escaped_strings_supported = true;
>>  constexpr bool escaped_strings_supported = false;
>>  #endif
>>
>> -void
>> +CONSTEXPR void
>>  test_format_spec()
>>  {
>>    VERIFY( is_format_string_for("{:}", 1) );
>> @@ -78,9 +85,14 @@ 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 );
>> @@ -130,13 +142,16 @@ test_format_spec()
>>    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) );
>> +  if (!std::is_constant_evaluated())
>> +    {
>> +      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) );
>> @@ -164,7 +179,7 @@ test_format_spec()
>>    VERIFY( ! is_format_string_for(L"{:9999999}", 1) );
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_pr110862()
>>  {
>>    try {
>> @@ -178,7 +193,7 @@ test_pr110862()
>>    }
>>  }
>>
>> -void
>> +CONSTEXPR void
>>  test_pr110974()
>>  {
>>    try {
>> @@ -197,11 +212,23 @@ test_pr110974()
>>    }
>>  }
>>
>> -int main()
>> +CONSTEXPR bool
>> +test_all()
>>  {
>>    test_no_args();
>>    test_indexing();
>>    test_format_spec();
>>    test_pr110862();
>>    test_pr110974();
>> +
>> +  return true;
>> +}
>> +
>> +#ifdef __glibcxx_constexpr_format
>> +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..faa6d289410 100644
>> --- a/libstdc++-v3/testsuite/std/format/tuple.cc
>> +++ b/libstdc++-v3/testsuite/std/format/tuple.cc
>> @@ -8,6 +8,12 @@
>>  #include <tuple>
>>  #include <utility>
>>
>> +#ifdef __glibcxx_constexpr_format
>> +# define CONSTEXPR constexpr
>> +#else
>> +# define CONSTEXPR
>> +#endif
>> +
>>  struct NotFormattable
>>  {};
>>
>> @@ -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
>> +CONSTEXPR 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
>> +CONSTEXPR bool
>>  is_format_string_for(const wchar_t* str, Args&&... args)
>>  {
>>    try {
>> @@ -41,7 +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)
>>
>> -void
>> +CONSTEXPR void
>>  test_format_string()
>>  {
>>    // invalid format stringss
>> @@ -123,7 +129,8 @@ void test_multi()
>>  }
>>
>>  template<typename CharT, typename Tuple>
>> -void test_empty()
>> +CONSTEXPR void
>> +test_empty()
>>  {
>>    std::basic_string<CharT> res;
>>
>> @@ -142,7 +149,8 @@ void test_empty()
>>  }
>>
>>  template<typename CharT, typename Pair>
>> -void test_pair()
>> +CONSTEXPR 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 +175,8 @@ void test_pair()
>>  }
>>
>>  template<typename CharT, template<typename, typename> class PairT>
>> -void test_pair_e()
>> +CONSTEXPR void
>> +test_pair_e()
>>  {
>>    test_pair<CharT, PairT<int, std::basic_string<CharT>>>();
>>    test_pair<CharT, PairT<int, const CharT*>>();
>> @@ -196,7 +205,7 @@ struct std::formatter<MyPair<Pair>, CharT>
>>    { return _formatter.parse(pc);  }
>>
>>    template<typename Out>
>> -  typename std::basic_format_context<Out, CharT>::iterator
>> +  CONSTEXPR 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 +215,8 @@ private:
>>  };
>>
>>  template<typename CharT, template<typename, typename> class PairT>
>> -void test_custom()
>> +CONSTEXPR void
>> +test_custom()
>>  {
>>    std::basic_string<CharT> res;
>>    MyPair<PairT<int, const CharT*>> c1(1, WIDEN("abc"));
>> @@ -228,9 +238,12 @@ void test_custom()
>>  }
>>
>>  template<typename CharT>
>> -void test_outputs()
>> +CONSTEXPR 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 +251,8 @@ void test_outputs()
>>    test_custom<CharT, std::tuple>();
>>  }
>>
>> -void test_nested()
>> +CONSTEXPR void
>> +test_nested()
>>  {
>>    std::string res;
>>    std::tuple<std::tuple<>, std::pair<int, std::string>> tt{{}, {1,
>> "abc"}};
>> @@ -251,7 +265,8 @@ void test_nested()
>>    VERIFY( res == R"((): (1, "abc"))" );
>>  }
>>
>> -bool strip_quote(std::string_view& v)
>> +CONSTEXPR bool
>> +strip_quote(std::string_view& v)
>>  {
>>    if (!v.starts_with('"'))
>>      return false;
>> @@ -259,7 +274,8 @@ bool strip_quote(std::string_view& v)
>>    return true;
>>  }
>>
>> -bool strip_prefix(std::string_view& v, std::string_view expected, bool
>> quoted = false)
>> +CONSTEXPR bool
>> +strip_prefix(std::string_view& v, std::string_view expected, bool quoted
>> = false)
>>  {
>>    if (quoted && !strip_quote(v))
>>      return false;
>> @@ -271,7 +287,8 @@ bool strip_prefix(std::string_view& v,
>> std::string_view expected, bool quoted =
>>    return true;
>>  }
>>
>> -bool strip_parens(std::string_view& v)
>> +CONSTEXPR bool
>> +strip_parens(std::string_view& v)
>>  {
>>    if (!v.starts_with('(') || !v.ends_with(')'))
>>      return false;
>> @@ -280,7 +297,8 @@ bool strip_parens(std::string_view& v)
>>    return true;
>>  }
>>
>> -bool strip_prefix(std::string_view& v, size_t n, char c)
>> +CONSTEXPR 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 +309,8 @@ bool strip_prefix(std::string_view& v, size_t n, char
>> c)
>>    return true;
>>  }
>>
>> -void test_padding()
>> +CONSTEXPR void
>> +test_padding()
>>  {
>>    std::string res;
>>    std::string_view resv;
>> @@ -351,13 +370,14 @@ struct std::formatter<Custom, CharT>
>>    { return pc.begin();  }
>>
>>    template<typename Out>
>> -  typename std::basic_format_context<Out, CharT>::iterator
>> +  CONSTEXPR 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()
>> +CONSTEXPR void
>> +test_nonblocking()
>>  {
>>    static_assert(std::enable_nonlocking_formatter_optimization<
>>                   Tuple<int, float>>);
>> @@ -374,7 +394,8 @@ void test_nonblocking()
>>                   Tuple<Custom&, float&>>);
>>  }
>>
>> -int main()
>> +CONSTEXPR bool
>> +test_all()
>>  {
>>    test_format_string();
>>    test_outputs<char>();
>> @@ -384,4 +405,15 @@ int main()
>>
>>    test_nonblocking<std::pair>();
>>    test_nonblocking<std::tuple>();
>> +
>> +  return true;
>> +}
>> +
>> +#ifdef __glibcxx_constexpr_format
>> +static_assert(test_all());
>> +#endif
>> +
>> +int main()
>> +{
>> +  test_all();
>>  }
>> diff --git
>> a/libstdc++-v3/testsuite/std/time/format/data_not_present_neg.cc
>> b/libstdc++-v3/testsuite/std/time/format/data_not_present_neg.cc
>> index cb8f916f216..86f3b618599 100644
>> --- a/libstdc++-v3/testsuite/std/time/format/data_not_present_neg.cc
>> +++ b/libstdc++-v3/testsuite/std/time/format/data_not_present_neg.cc
>> @@ -161,4 +161,5 @@ auto si7 = std::format("{:%Q}", sys_info()); // {
>> dg-error "call to consteval fu
>>  auto si8 = std::format("{:%Z}", sys_info()); // { dg-error "call to
>> consteval function" "" { target cxx11_abi } }
>>  #endif
>>
>> -// { dg-error "call to non-'constexpr' function" "" { target *-*-* } 0 }
>> +// { dg-error "call to non-'constexpr' function" "" { target c++23_down
>> } 0 }
>> +// { dg-error "'std::terminate' called after throwing an exception" "" {
>> target { ! c++23_down } } 0 }
>> --
>> 2.43.0
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260319/7668c75e/attachment-0001.htm>


More information about the Libstdc++ mailing list