This patch partially implements constexpr formatting from P3391R2,
and introduces the constexpr_format feature-test macro.

This patch mostly adds `_GLIBCXX26_CONSTEXPR` to functions.

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.

Some wide formatting relies on `__builtin_alloca` which doesn't work
in constexpr, changed it to go through regular allocation
and cleanup in constexpr.

Update some formatting tests to test constexpr as well,
and introduce a dedicated smoke test for constexpr formatting.

This patch is missing:
* constexpr to_{,w}string
* more constexpr tests

libstdc++-v3/ChangeLog:

        * include/bits/version.def: Add constexpr_format.
        * include/bits/version.h: Regenerate.
        * include/std/format:
        Pepper in _GLIBCXX26_CONSTEXPR, replace memcpy with ranges::copy,
        avoid __builtin_alloca in constexpr wide formatting.
        (__format::__toupper_numeric): Define.
        (__format::__do_vformat_to):
        Avoid using _Ptr_sink in constexpr.
        * testsuite/std/format/arguments/args_neg.cc: Diagnostics change.
        * testsuite/std/format/constexpr.cc: New test.
        * testsuite/std/format/debug.cc: Constexpr testing.
        * testsuite/std/format/functions/format.cc: Constexpr testing.
        * testsuite/std/format/functions/format_to.cc: Constexpr testing.
        * testsuite/std/format/functions/size.cc: Constexpr testing.
        * testsuite/std/format/ranges/format_kind.cc: Constexpr testing.
        * testsuite/std/format/ranges/formatter.cc: Constexpr testing.
        * testsuite/std/format/ranges/sequence.cc: Constexpr testing.
        * testsuite/std/format/runtime_format.cc: Constexpr testing.
        * testsuite/std/format/string.cc: Constexpr testing.
        * testsuite/std/format/tuple.cc: Constexpr testing.
        * testsuite/std/time/format/data_not_present_neg.cc: Diagnostics change.

Signed-off-by: Ivan Lazaric <[email protected]>
---
Notable changes:

std/format/arguments/args_neg.cc & std/time/format/data_not_present_neg.cc:
touched up the diagnostics they expect.

Fixed up constexpr wide formatting, avoiding the __builtin_alloca
with regular allocation, and a unique_ptr-esque _Cleanup deallocation
on scope exit. Last remaining __builtin_alloca is in locale related path.
Testing constexpr wide formatting in both existing tests and
newly introduced constexpr.cc.

Rebased on top of untested fix mentioned in:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124145
This allows for constexpr tests related to exceptions,
enabled them in the existing tests I touched.

Marked basic_format_string constructor as noexcept,
so the exception blows up compilation and is not catchable.

Patches this is based on top of that aren't merged yet:
* libstdc++: Store basic_format_arg::handle in __format::_Arg_value
* libstdc++: Introduce __format::_Ptr_sink for contingous iterators.
* libstdc++: Remove UB in _Arg_value union alteranatives assigment
* PR c++/124145 mentioned fix
In case the base for this patch is becoming confusing, it can be found at:
https://github.com/ilazaric/gcc/tree/ilazaric/constexpr-formatting-base

One test I took a look at and didn't constexpr-ify:
std/format/parse_ctx.cc
I'm unsure it makes sense to constexpr-ify it,
as it runs into: https://eel.is/c++draft/format#parse.ctx-note-1
> Note: Any call to next_arg_id, check_arg_id, or check_dynamic_spec
> on an instance of basic_format_parse_context initialized using
> this constructor is not a core constant expression.

I am also noting not yet resolved LWG issue as relevant:
https://cplusplus.github.io/LWG/issue4531



 libstdc++-v3/include/bits/version.def         |  11 +
 libstdc++-v3/include/bits/version.h           |   9 +
 libstdc++-v3/include/std/format               | 429 +++++++++++-------
 .../std/format/arguments/args_neg.cc          |   4 +-
 .../testsuite/std/format/constexpr.cc         | 156 +++++++
 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    |  17 +-
 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, 923 insertions(+), 395 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 c7709ba3a07..8cd7df5b37a 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1330,6 +1330,17 @@ ftms = {
   };
 };
 
+ftms = {
+  name = constexpr_format;
+  // 202511 P3391R2 constexpr std::format
+  no_stdname = true; // not fully implemented yet
+  values = {
+    v = 202511;
+    cxxmin = 26;
+    hosted = yes;
+  };
+};
+
 ftms = {
   name = format_uchar;
   values = {
diff --git a/libstdc++-v3/include/bits/version.h 
b/libstdc++-v3/include/bits/version.h
index c72cda506f1..ff53e9821c4 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_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 4f0b0f377c6..536bd565c83 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
@@ -128,6 +129,7 @@ namespace __format
     struct _Runtime_format_string
     {
       [[__gnu__::__always_inline__]]
+      _GLIBCXX26_CONSTEXPR
       _Runtime_format_string(basic_string_view<_CharT> __s) noexcept
       : _M_str(__s) { }
 
@@ -170,9 +172,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__]]
+      _GLIBCXX26_CONSTEXPR
       basic_format_string(__format::_Runtime_format_string<_CharT> __s) 
noexcept
       : _M_str(__s._M_str)
       { }
@@ -197,13 +200,13 @@ namespace __format
 
 #if __cpp_lib_format >= 202311L // >= C++26
   [[__gnu__::__always_inline__]]
-  inline __format::_Runtime_format_string<char>
+  inline _GLIBCXX26_CONSTEXPR __format::_Runtime_format_string<char>
   runtime_format(string_view __fmt) noexcept
   { return __fmt; }
 
 #ifdef _GLIBCXX_USE_WCHAR_T
   [[__gnu__::__always_inline__]]
-  inline __format::_Runtime_format_string<wchar_t>
+  inline _GLIBCXX26_CONSTEXPR __format::_Runtime_format_string<wchar_t>
   runtime_format(wstring_view __fmt) noexcept
   { return __fmt; }
 #endif
@@ -238,7 +241,7 @@ namespace __format
 
   /// @cond undocumented
   [[noreturn]]
-  inline void
+  inline _GLIBCXX26_CONSTEXPR void
   __throw_format_error(const char* __what)
   { _GLIBCXX_THROW_OR_ABORT(format_error(__what)); }
 
@@ -249,27 +252,27 @@ namespace __format
   // XXX use named functions for each constexpr error?
 
   [[noreturn]]
-  inline void
+  inline _GLIBCXX26_CONSTEXPR void
   __unmatched_left_brace_in_format_string()
   { __throw_format_error("format error: unmatched '{' in format string"); }
 
   [[noreturn]]
-  inline void
+  inline _GLIBCXX26_CONSTEXPR void
   __unmatched_right_brace_in_format_string()
   { __throw_format_error("format error: unmatched '}' in format string"); }
 
   [[noreturn]]
-  inline void
+  inline _GLIBCXX26_CONSTEXPR void
   __conflicting_indexing_in_format_string()
   { __throw_format_error("format error: conflicting indexing style in format 
string"); }
 
   [[noreturn]]
-  inline void
+  inline _GLIBCXX26_CONSTEXPR void
   __invalid_arg_id_in_format_string()
   { __throw_format_error("format error: invalid arg-id in format string"); }
 
   [[noreturn]]
-  inline void
+  inline _GLIBCXX26_CONSTEXPR void
   __failed_to_parse_format_spec()
   { __throw_format_error("format error: failed to parse format-spec"); }
 
@@ -517,7 +520,7 @@ namespace __format
   using enum _WidthPrec;
 
   template<typename _Context>
-    size_t
+    _GLIBCXX26_CONSTEXPR size_t
     __int_from_arg(const basic_format_arg<_Context>& __arg);
 
   constexpr bool __is_digit(char __c)
@@ -750,7 +753,7 @@ namespace __format
       }
 
       template<typename _Context>
-       size_t
+       _GLIBCXX26_CONSTEXPR size_t
        _M_get_width(_Context& __ctx) const
        {
          size_t __width = 0;
@@ -762,7 +765,7 @@ namespace __format
        }
 
       template<typename _Context>
-       size_t
+       _GLIBCXX26_CONSTEXPR size_t
        _M_get_precision(_Context& __ctx) const
        {
          size_t __prec = -1;
@@ -775,7 +778,7 @@ namespace __format
     };
 
   template<typename _Int>
-    inline char*
+    inline _GLIBCXX26_CONSTEXPR char*
     __put_sign(_Int __i, _Sign __sign, char* __dest) noexcept
     {
       if (__i < 0)
@@ -792,7 +795,7 @@ namespace __format
   // Write STR to OUT (and do so efficiently if OUT is a _Sink_iter).
   template<typename _Out, typename _CharT>
     requires output_iterator<_Out, const _CharT&>
-    inline _Out
+    inline _GLIBCXX26_CONSTEXPR _Out
     __write(_Out __out, basic_string_view<_CharT> __str)
     {
       if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
@@ -809,7 +812,7 @@ namespace __format
   // Write STR to OUT with NFILL copies of FILL_CHAR specified by ALIGN.
   // pre: __align != _Align_default
   template<typename _Out, typename _CharT>
-    _Out
+    _GLIBCXX26_CONSTEXPR _Out
     __write_padded(_Out __out, basic_string_view<_CharT> __str,
                   _Align __align, size_t __nfill, char32_t __fill_char)
     {
@@ -883,7 +886,7 @@ namespace __format
   // Write STR to OUT, with alignment and padding as determined by SPEC.
   // pre: __spec._M_align != _Align_default || __align != _Align_default
   template<typename _CharT, typename _Out>
-    _Out
+    _GLIBCXX26_CONSTEXPR _Out
     __write_padded_as_spec(basic_string_view<type_identity_t<_CharT>> __str,
                           size_t __estimated_width,
                           basic_format_context<_Out, _CharT>& __fc,
@@ -905,7 +908,7 @@ namespace __format
     }
 
    template<typename _CharT>
-     size_t
+     _GLIBCXX26_CONSTEXPR size_t
      __truncate(basic_string_view<_CharT>& __s, size_t __prec)
      {
        if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
@@ -1049,7 +1052,7 @@ namespace __format
 
   using uint_least32_t = __UINT_LEAST32_TYPE__;
   template<typename _Out, typename _CharT>
-    _Out
+    _GLIBCXX26_CONSTEXPR _Out
     __write_escape_seq(_Out __out, uint_least32_t __val,
                       basic_string_view<_CharT> __prefix)
     {
@@ -1079,7 +1082,7 @@ namespace __format
     }
 
   template<typename _Out, typename _CharT>
-    _Out
+    _GLIBCXX26_CONSTEXPR _Out
     __write_escape_seqs(_Out __out, basic_string_view<_CharT> __units)
     {
       using _UChar = make_unsigned_t<_CharT>;
@@ -1090,7 +1093,7 @@ namespace __format
     }
 
   template<typename _Out, typename _CharT>
-    _Out
+    _GLIBCXX26_CONSTEXPR _Out
     __write_escaped_char(_Out __out, _CharT __c)
     {
       using _UChar = make_unsigned_t<_CharT>;
@@ -1116,7 +1119,7 @@ namespace __format
     }
 
   template<typename _CharT, typename _Out>
-    _Out
+    _GLIBCXX26_CONSTEXPR _Out
     __write_escaped_ascii(_Out __out,
                          basic_string_view<_CharT> __str,
                          _Term_char __term)
@@ -1146,7 +1149,7 @@ namespace __format
     }
 
   template<typename _CharT, typename _Out>
-    _Out
+    _GLIBCXX26_CONSTEXPR _Out
     __write_escaped_unicode_part(_Out __out, basic_string_view<_CharT>& __str,
                                 bool& __prev_esc, _Term_char __term)
     {
@@ -1224,7 +1227,7 @@ namespace __format
     }
 
   template<typename _CharT, typename _Out>
-    _Out
+    _GLIBCXX26_CONSTEXPR _Out
     __write_escaped_unicode(_Out __out, basic_string_view<_CharT> __str,
                            _Term_char __term)
     {
@@ -1236,7 +1239,7 @@ namespace __format
     }
 
   template<typename _CharT, typename _Out>
-    _Out
+    _GLIBCXX26_CONSTEXPR _Out
     __write_escaped(_Out __out,  basic_string_view<_CharT> __str, _Term_char 
__term)
     {
       __out = __format::__write(__out, _Escapes<_CharT>::_S_term(__term));
@@ -1257,12 +1260,14 @@ namespace __format
   struct _Optional_locale
   {
     [[__gnu__::__always_inline__]]
+    _GLIBCXX26_CONSTEXPR
     _Optional_locale() : _M_dummy(), _M_hasval(false) { }
 
     _Optional_locale(const locale& __loc) noexcept
     : _M_loc(__loc), _M_hasval(true)
     { }
 
+    _GLIBCXX26_CONSTEXPR
     _Optional_locale(const _Optional_locale& __l) noexcept
     : _M_dummy(), _M_hasval(__l._M_hasval)
     {
@@ -1270,6 +1275,7 @@ namespace __format
        std::construct_at(&_M_loc, __l._M_loc);
     }
 
+    _GLIBCXX26_CONSTEXPR
     _Optional_locale&
     operator=(const _Optional_locale& __l) noexcept
     {
@@ -1291,6 +1297,7 @@ namespace __format
       return *this;
     }
 
+    _GLIBCXX26_CONSTEXPR
     ~_Optional_locale() { if (_M_hasval) _M_loc.~locale(); }
 
     _Optional_locale&
@@ -1317,7 +1324,8 @@ namespace __format
       return _M_loc;
     }
 
-    bool has_value() const noexcept { return _M_hasval; }
+    _GLIBCXX26_CONSTEXPR bool
+    has_value() const noexcept { return _M_hasval; }
 
     union {
       char _M_dummy = '\0';
@@ -1391,7 +1399,7 @@ namespace __format
       }
 
       template<typename _Out>
-       _Out
+       _GLIBCXX26_CONSTEXPR _Out
        format(basic_string_view<_CharT> __s,
               basic_format_context<_Out, _CharT>& __fc) const
        {
@@ -1408,7 +1416,7 @@ namespace __format
        }
 
       template<typename _Out>
-       _Out
+       _GLIBCXX26_CONSTEXPR _Out
        _M_format_escaped(basic_string_view<_CharT> __s,
                          basic_format_context<_Out, _CharT>& __fc) const
        {
@@ -1433,7 +1441,7 @@ namespace __format
 #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
       template<ranges::input_range _Rg, typename _Out>
        requires same_as<remove_cvref_t<ranges::range_reference_t<_Rg>>, _CharT>
-       _Out
+       _GLIBCXX26_CONSTEXPR _Out
        _M_format_range(_Rg&& __rg, basic_format_context<_Out, _CharT>& __fc) 
const
        {
          using _Range = remove_reference_t<_Rg>;
@@ -1482,6 +1490,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 +1671,7 @@ namespace __format
        }
 
       template<typename _Int, typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        format(_Int __i, basic_format_context<_Out, _CharT>& __fc) const
        {
@@ -1689,11 +1720,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();
@@ -1702,8 +1729,7 @@ namespace __format
          if (_M_spec._M_alt && __base_prefix.size())
            {
              __start -= __base_prefix.size();
-             __builtin_memcpy(__start, __base_prefix.data(),
-                              __base_prefix.size());
+             ranges::copy(__base_prefix, __start);
            }
          __start = __format::__put_sign(__i, _M_spec._M_sign, __start - 1);
 
@@ -1712,6 +1738,7 @@ namespace __format
        }
 
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        format(bool __i, basic_format_context<_Out, _CharT>& __fc) const
        {
@@ -1742,6 +1769,7 @@ namespace __format
        }
 
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        _M_format_character(_CharT __c,
                            basic_format_context<_Out, _CharT>& __fc) const
@@ -1773,7 +1801,7 @@ namespace __format
        }
 
       template<typename _Int>
-       static _CharT
+       static _GLIBCXX26_CONSTEXPR _CharT
        _S_to_character(_Int __i)
        {
          using _Traits = __gnu_cxx::__int_traits<_CharT>;
@@ -1794,6 +1822,7 @@ namespace __format
        }
 
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        _M_format_int(string_view __narrow_str, size_t __prefix_len,
                      basic_format_context<_Out, _CharT>& __fc) const
@@ -1807,10 +1836,25 @@ namespace __format
          else
            {
              size_t __n = __narrow_str.size();
-             auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
+             auto __p = std::is_constant_evaluated()
+               ? new _CharT[__n * sizeof(_CharT)]
+               : (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
              std::__to_wstring_numeric(__narrow_str.data(), __n, __p);
              __str = {__p, __n};
            }
+
+#ifdef __glibcxx_constexpr_format // C++ >= 26
+         struct _Cleanup
+         {
+           const _CharT* _M_ptr;
+
+           constexpr ~_Cleanup()
+           {
+             if (std::is_constant_evaluated())
+               delete[] _M_ptr;
+           }
+         } __cleanup(is_same_v<char, _CharT> ? nullptr : __str.data());
+#endif
 #endif
 
          if (_M_spec._M_localized)
@@ -2197,7 +2241,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;
@@ -2502,10 +2546,15 @@ namespace __format
       }
 
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        format(const void* __v, basic_format_context<_Out, _CharT>& __fc) const
        {
-         auto __u = reinterpret_cast<__UINTPTR_TYPE__>(__v);
+         // Treating nullptr specially
+         // to enable constexpr formatting of nullptr_t.
+         auto __u = __v
+           ? reinterpret_cast<__UINTPTR_TYPE__>(__v)
+           : (__UINTPTR_TYPE__)0;
          char __buf[2 + sizeof(__v) * 2];
          auto [__ptr, __ec] = std::to_chars(__buf + 2, std::end(__buf),
                                             __u, 16);
@@ -2517,11 +2566,7 @@ namespace __format
            {
              __buf[1] = 'X';
              for (auto __p = __buf + 2; __p != __ptr; ++__p)
-#if __has_builtin(__builtin_toupper)
-               *__p = __builtin_toupper(*__p);
-#else
-               *__p = std::toupper(*__p);
-#endif
+               *__p = __format::__toupper_numeric(*__p);
            }
 #endif
 
@@ -2531,10 +2576,25 @@ namespace __format
 #ifdef _GLIBCXX_USE_WCHAR_T
          else
            {
-             auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
+             auto __p = std::is_constant_evaluated()
+               ? new _CharT[__n * sizeof(_CharT)]
+               : (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
              std::__to_wstring_numeric(__buf, __n, __p);
              __str = wstring_view(__p, __n);
            }
+
+#ifdef __glibcxx_constexpr_format // C++ >= 26
+         struct _Cleanup
+         {
+           const _CharT* _M_ptr;
+
+           constexpr ~_Cleanup()
+           {
+             if (std::is_constant_evaluated())
+               delete[] _M_ptr;
+           }
+         } __cleanup(is_same_v<char, _CharT> ? nullptr : __str.data());
+#endif
 #endif
 
 #if __glibcxx_format >= 202304L
@@ -2590,6 +2650,7 @@ namespace __format
       }
 
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        format(_CharT __u, basic_format_context<_Out, _CharT>& __fc) const
        {
@@ -2628,6 +2689,7 @@ namespace __format
       }
 
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, wchar_t>::iterator
        format(char __u, basic_format_context<_Out, wchar_t>& __fc) const
        {
@@ -2663,6 +2725,7 @@ namespace __format
 
       template<typename _Out>
        [[__gnu__::__nonnull__]]
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        format(_CharT* __u, basic_format_context<_Out, _CharT>& __fc) const
        { return _M_f.format(__u, __fc); }
@@ -2692,6 +2755,7 @@ namespace __format
 
       template<typename _Out>
        [[__gnu__::__nonnull__]]
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        format(const _CharT* __u,
               basic_format_context<_Out, _CharT>& __fc) const
@@ -2722,6 +2786,7 @@ namespace __format
       { return _M_f.parse(__pc); }
 
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        format(const _CharT (&__u)[_Nm],
               basic_format_context<_Out, _CharT>& __fc) const
@@ -2751,6 +2816,7 @@ namespace __format
       { return _M_f.parse(__pc); }
 
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, char>::iterator
        format(const basic_string<char, _Traits, _Alloc>& __u,
               basic_format_context<_Out, char>& __fc) const
@@ -2783,6 +2849,7 @@ namespace __format
       { return _M_f.parse(__pc); }
 
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, wchar_t>::iterator
        format(const basic_string<wchar_t, _Traits, _Alloc>& __u,
               basic_format_context<_Out, wchar_t>& __fc) const
@@ -2816,6 +2883,7 @@ namespace __format
       { return _M_f.parse(__pc); }
 
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, char>::iterator
        format(basic_string_view<char, _Traits> __u,
               basic_format_context<_Out, char>& __fc) const
@@ -2848,6 +2916,7 @@ namespace __format
       { return _M_f.parse(__pc); }
 
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, wchar_t>::iterator
        format(basic_string_view<wchar_t, _Traits> __u,
               basic_format_context<_Out, wchar_t>& __fc) const
@@ -2911,6 +2980,7 @@ namespace __format
       }
 
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        format(_Tp __u, basic_format_context<_Out, _CharT>& __fc) const
        { return _M_f.format(__u, __fc); }
@@ -3122,6 +3192,7 @@ namespace __format
       { return _M_f.parse(__pc); }
 
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        format(const void* __v, basic_format_context<_Out, _CharT>& __fc) const
        { return _M_f.format(__v, __fc); }
@@ -3147,6 +3218,7 @@ namespace __format
       { return _M_f.parse(__pc); }
 
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        format(void* __v, basic_format_context<_Out, _CharT>& __fc) const
        { return _M_f.format(__v, __fc); }
@@ -3172,6 +3244,7 @@ namespace __format
       { return _M_f.parse(__pc); }
 
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        format(nullptr_t, basic_format_context<_Out, _CharT>& __fc) const
        { return _M_f.format(nullptr, __fc); }
@@ -3316,11 +3389,11 @@ namespace __format
       constexpr _Sink_iter
       operator++(int) { return *this; }
 
-      auto
+      _GLIBCXX26_CONSTEXPR auto
       _M_reserve(size_t __n) const
       { return _M_sink->_M_reserve(__n); }
 
-      bool
+      _GLIBCXX26_CONSTEXPR bool
       _M_discarding() const
       { return _M_sink->_M_discarding(); }
     };
@@ -3352,7 +3425,7 @@ namespace __format
 
       // The portion of the span that has been written to.
       [[__gnu__::__always_inline__]]
-      span<_CharT>
+      _GLIBCXX26_CONSTEXPR span<_CharT>
       _M_used() const noexcept
       { return _M_span.first(_M_next - _M_span.begin()); }
 
@@ -3369,7 +3442,7 @@ namespace __format
       { _M_next = _M_span.begin(); }
 
       // Replace the current output range.
-      void
+      _GLIBCXX26_CONSTEXPR void
       _M_reset(span<_CharT> __s, size_t __pos = 0) noexcept
       {
        _M_span = __s;
@@ -3409,11 +3482,14 @@ namespace __format
       struct _Reservation
       {
        // True if the reservation was successful, false otherwise.
+       _GLIBCXX26_CONSTEXPR
        explicit operator bool() const noexcept { return _M_sink; }
        // A pointer to write directly to the sink.
-       _CharT* get() const noexcept { return _M_sink->_M_next.operator->(); }
+       _GLIBCXX26_CONSTEXPR _CharT*
+       get() const noexcept { return _M_sink->_M_next.operator->(); }
        // Add n to the _M_next iterator for the sink.
-       void _M_bump(size_t __n) { _M_sink->_M_bump(__n); }
+       _GLIBCXX26_CONSTEXPR void
+       _M_bump(size_t __n) { _M_sink->_M_bump(__n); }
        _Sink* _M_sink;
       };
 
@@ -3421,7 +3497,7 @@ namespace __format
       // If anything is written to the reservation then there must be a call
       // to _M_bump(N2) before any call to another member function of *this,
       // where N2 is the number of characters written.
-      virtual _Reservation
+      _GLIBCXX26_CONSTEXPR virtual _Reservation
       _M_reserve(size_t __n)
       {
        if (__n <= _M_unused().size())
@@ -3438,12 +3514,12 @@ namespace __format
 
       // Update the next output position after writing directly to the sink.
       // pre: no calls to _M_write or _M_overflow since _M_reserve.
-      virtual void
+      _GLIBCXX26_CONSTEXPR virtual void
       _M_bump(size_t __n)
       { _M_next += __n; }
 
       // Returns true if the _Sink is discarding incoming characters.
-      virtual bool
+      _GLIBCXX26_CONSTEXPR virtual bool
       _M_discarding() const
       { return false; }
 
@@ -3461,7 +3537,7 @@ namespace __format
   template<typename _CharT>
     class _Fixedbuf_sink final : public _Sink<_CharT>
     {
-      void
+      _GLIBCXX26_CONSTEXPR void
       _M_overflow() override
       {
        __glibcxx_assert(false);
@@ -3509,7 +3585,7 @@ namespace __format
       _Seq _M_seq;
     protected:
       // Transfer buffer contents to the sequence, so buffer can be refilled.
-      void
+      _GLIBCXX26_CONSTEXPR void
       _M_overflow() override
       {
        auto __s = this->_M_used();
@@ -3528,7 +3604,7 @@ namespace __format
        this->_M_rewind();
       }
 
-      typename _Sink<_CharT>::_Reservation
+      _GLIBCXX26_CONSTEXPR typename _Sink<_CharT>::_Reservation
       _M_reserve(size_t __n) override
       {
        // We might already have n characters available in this->_M_unused(),
@@ -3564,7 +3640,7 @@ namespace __format
          return _Sink<_CharT>::_M_reserve(__n);
       }
 
-      void
+      _GLIBCXX26_CONSTEXPR void
       _M_bump(size_t __n) override
       {
        if constexpr (__is_specialization_of<_Seq, basic_string>
@@ -3579,7 +3655,8 @@ namespace __format
          }
       }
 
-      void _M_trim(span<const _CharT> __s)
+      _GLIBCXX26_CONSTEXPR void
+      _M_trim(span<const _CharT> __s)
        requires __is_specialization_of<_Seq, basic_string>
       {
        _GLIBCXX_DEBUG_ASSERT(__s.data() == this->_M_buf
@@ -3595,16 +3672,18 @@ namespace __format
       // to _M_buf if it overflows? Or even do that for all unused capacity?
 
       [[__gnu__::__always_inline__]]
+      _GLIBCXX26_CONSTEXPR
       _Seq_sink() noexcept(is_nothrow_default_constructible_v<_Seq>)
       { }
 
+      _GLIBCXX26_CONSTEXPR
       _Seq_sink(_Seq&& __s) noexcept(is_nothrow_move_constructible_v<_Seq>)
       : _M_seq(std::move(__s))
       { }
 
       using _Sink<_CharT>::out;
 
-      _Seq
+      _GLIBCXX26_CONSTEXPR _Seq
       get() &&
       {
        if (this->_M_used().size() != 0)
@@ -3614,7 +3693,7 @@ namespace __format
 
       // A writable span that views everything written to the sink.
       // Will be either a view over _M_seq or the used part of _M_buf.
-      span<_CharT>
+      _GLIBCXX26_CONSTEXPR span<_CharT>
       _M_span()
       {
        auto __s = this->_M_used();
@@ -3627,7 +3706,7 @@ namespace __format
        return __s;
       }
 
-      basic_string_view<_CharT>
+      _GLIBCXX26_CONSTEXPR basic_string_view<_CharT>
       view()
       {
        auto __span = _M_span();
@@ -3652,7 +3731,7 @@ namespace __format
     protected:
       size_t _M_count = 0;
 
-      void
+      _GLIBCXX26_CONSTEXPR void
       _M_overflow() override
       {
        auto __s = this->_M_used();
@@ -3672,7 +3751,7 @@ namespace __format
        _M_count += __s.size();
       }
 
-      bool
+      _GLIBCXX26_CONSTEXPR bool
       _M_discarding() const override
       {
        // format_to_n return total number of characters, that would be written,
@@ -3682,14 +3761,14 @@ namespace __format
 
     public:
       [[__gnu__::__always_inline__]]
-      explicit
+      _GLIBCXX26_CONSTEXPR explicit
       _Iter_sink(_OutIter __out, iter_difference_t<_OutIter> __max = -1)
       : _M_out(std::move(__out)), _M_max(__max)
       { }
 
       using _Sink<_CharT>::out;
 
-      format_to_n_result<_OutIter>
+      _GLIBCXX26_CONSTEXPR format_to_n_result<_OutIter>
       _M_finish() &&
       {
        if (this->_M_used().size() != 0)
@@ -3718,7 +3797,7 @@ namespace __format
       _CharT _M_buf[64]; // Write here after outputting _M_max characters.
 
     protected:
-      void
+      _GLIBCXX26_CONSTEXPR void
       _M_overflow() override
       {
        if (this->_M_unused().size() != 0)
@@ -3742,7 +3821,7 @@ namespace __format
          }
       }
 
-      bool
+      _GLIBCXX26_CONSTEXPR bool
       _M_discarding() const override
       {
        // format_to_n return total number of characters, that would be written,
@@ -3750,7 +3829,7 @@ namespace __format
        return false;
       }
 
-      typename _Sink<_CharT>::_Reservation
+      _GLIBCXX26_CONSTEXPR typename _Sink<_CharT>::_Reservation
       _M_reserve(size_t __n) final
       {
        auto __avail = this->_M_unused();
@@ -3767,7 +3846,7 @@ namespace __format
 
     private:
       template<typename _IterDifference>
-       static size_t
+       static _GLIBCXX26_CONSTEXPR size_t
        _S_trim_max(_IterDifference __max)
        {
          if (__max < 0)
@@ -3780,7 +3859,7 @@ namespace __format
        }
 
       [[__gnu__::__always_inline__]]
-      void
+      _GLIBCXX26_CONSTEXPR void
       _M_rebuf(_CharT* __ptr, size_t __total, size_t __inuse = 0)
       {
        std::span<_CharT> __span(__ptr, __total);
@@ -3788,7 +3867,7 @@ namespace __format
       }
 
     public:
-      explicit
+      _GLIBCXX26_CONSTEXPR explicit
       _Ptr_sink(_CharT* __ptr, size_t __n = _S_no_limit) noexcept
       : _Sink<_CharT>(_M_buf), _M_max(__n)
       { 
@@ -3813,13 +3892,13 @@ namespace __format
       }
 
       template<contiguous_iterator _OutIter>
-       explicit
+       _GLIBCXX26_CONSTEXPR explicit
        _Ptr_sink(_OutIter __out, iter_difference_t<_OutIter> __n = -1)
        : _Ptr_sink(std::to_address(__out), _S_trim_max(__n))
        { }
 
       template<contiguous_iterator _OutIter>
-       format_to_n_result<_OutIter>
+       _GLIBCXX26_CONSTEXPR format_to_n_result<_OutIter>
        _M_finish(_OutIter __first) const
        {
          auto __s = this->_M_used();
@@ -3861,12 +3940,12 @@ namespace __format
       size_t _M_printwidth;
 
       [[__gnu__::__always_inline__]]
-      bool
+      _GLIBCXX26_CONSTEXPR bool
       _M_ignoring() const
       { return _M_printwidth >= _M_maxwidth; }
 
       [[__gnu__::__always_inline__]]
-      bool
+      _GLIBCXX26_CONSTEXPR bool
       _M_buffering() const
       {
        if (_M_printwidth < _M_padwidth)
@@ -3876,7 +3955,7 @@ namespace __format
        return false;
       }
 
-      void
+      _GLIBCXX26_CONSTEXPR void
       _M_sync_discarding()
       {
        if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
@@ -3884,7 +3963,7 @@ namespace __format
            _M_maxwidth = _M_printwidth;
       }
 
-      void
+      _GLIBCXX26_CONSTEXPR void
       _M_flush()
       {
        span<_CharT> __new = this->_M_used();
@@ -3894,7 +3973,7 @@ namespace __format
        this->_M_rewind();
       }
 
-      bool
+      _GLIBCXX26_CONSTEXPR bool
       _M_force_update()
       {
        auto __str = this->view();
@@ -3922,7 +4001,7 @@ namespace __format
        return false;
       }
 
-      bool
+      _GLIBCXX26_CONSTEXPR bool
       _M_update(size_t __new)
       {
        _M_printwidth += __new;
@@ -3932,7 +4011,7 @@ namespace __format
        return true;
       }
 
-      void
+      _GLIBCXX26_CONSTEXPR void
       _M_overflow() override
       {
        // Ignore characters in buffer, and override it.
@@ -3947,11 +4026,11 @@ namespace __format
          _Str_sink<_CharT>::_M_overflow();
       }
 
-      bool
+      _GLIBCXX26_CONSTEXPR bool
       _M_discarding() const override
       { return _M_ignoring(); }
 
-      typename _Sink<_CharT>::_Reservation
+      _GLIBCXX26_CONSTEXPR typename _Sink<_CharT>::_Reservation
       _M_reserve(size_t __n) override
       {
        // Ignore characters in buffer, if any.
@@ -3970,7 +4049,7 @@ namespace __format
        return _Sink<_CharT>::_M_reserve(__n);
       }
 
-      void
+      _GLIBCXX26_CONSTEXPR void
       _M_bump(size_t __n) override
       {
        // Ignore the written characters.
@@ -3985,19 +4064,19 @@ namespace __format
 
     public:
       [[__gnu__::__always_inline__]]
-      explicit
+      _GLIBCXX26_CONSTEXPR explicit
       _Padding_sink(_Out __out, size_t __padwidth, size_t __maxwidth)
       : _M_padwidth(__padwidth), _M_maxwidth(__maxwidth),
        _M_out(std::move(__out)), _M_printwidth(0)
       { _M_sync_discarding(); }
 
       [[__gnu__::__always_inline__]]
-      explicit
+      _GLIBCXX26_CONSTEXPR explicit
       _Padding_sink(_Out __out, size_t __padwidth)
       : _Padding_sink(std::move(__out), __padwidth, (size_t)-1)
       { }
 
-      _Out
+      _GLIBCXX26_CONSTEXPR _Out
       _M_finish(_Align __align, char32_t __fill_char)
       {
        // Handle any characters in the buffer.
@@ -4036,14 +4115,14 @@ namespace __format
       unsigned _M_prev_escape : 1;
       unsigned _M_out_discards : 1;
 
-      void
+      _GLIBCXX26_CONSTEXPR void
       _M_sync_discarding()
       {
        if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
          _M_out_discards = _M_out._M_discarding();
       }
 
-      void
+      _GLIBCXX26_CONSTEXPR void
       _M_write()
       {
        span<_CharT> __bytes = this->_M_used();
@@ -4069,7 +4148,7 @@ namespace __format
        _M_sync_discarding();
       }
 
-      void
+      _GLIBCXX26_CONSTEXPR void
       _M_overflow() override
       {
        if (_M_out_discards)
@@ -4078,13 +4157,13 @@ namespace __format
          _M_write();
       }
 
-      bool
+      _GLIBCXX26_CONSTEXPR bool
       _M_discarding() const override
       { return _M_out_discards; }
 
     public:
       [[__gnu__::__always_inline__]]
-      explicit
+      _GLIBCXX26_CONSTEXPR explicit
       _Escaping_sink(_Out __out, _Term_char __term)
       : _M_out(std::move(__out)), _M_term(__term),
        _M_prev_escape(true), _M_out_discards(false)
@@ -4093,7 +4172,7 @@ namespace __format
        _M_sync_discarding();
       }
 
-      _Out
+      _GLIBCXX26_CONSTEXPR _Out
       _M_finish()
       {
        if (_M_out_discards)
@@ -4141,7 +4220,7 @@ namespace __format
                            const _Tp, _Tp>;
 
       template<typename _Tq>
-       static void
+       static _GLIBCXX26_CONSTEXPR void
        _S_format(basic_format_parse_context<_CharT>& __parse_ctx,
                  _Context& __format_ctx, const void* __ptr)
        {
@@ -4154,7 +4233,7 @@ namespace __format
 
       template<typename _Tp>
        requires (!is_same_v<remove_cv_t<_Tp>, _Handle>)
-       explicit
+       _GLIBCXX26_CONSTEXPR explicit
        _Handle(_Tp& __val) noexcept
        : _M_ptr(__builtin_addressof(__val))
        , _M_func(&_S_format<__maybe_const_t<_Tp>>)
@@ -4169,7 +4248,7 @@ namespace __format
       _Handle& operator=(const _Handle&) = default;
 
       [[__gnu__::__always_inline__]]
-      void
+      _GLIBCXX26_CONSTEXPR void
       format(basic_format_parse_context<_CharT>& __pc, _Context& __fc) const
       { _M_func(__pc, __fc, this->_M_ptr); }
 
@@ -4226,10 +4305,12 @@ namespace __format
       };
 
       [[__gnu__::__always_inline__]]
+      _GLIBCXX26_CONSTEXPR
       _Arg_value() : _M_none() { }
 
 #if 0
       template<typename _Tp>
+       _GLIBCXX26_CONSTEXPR
        _Arg_value(in_place_type_t<_Tp>, _Tp __val)
        { _S_get<_Tp>() = __val; }
 #endif
@@ -4238,7 +4319,7 @@ namespace __format
       // Value of second argument (if provided), is assigned to that member. 
       template<typename _Tp, typename _Self, typename... _Value>
        [[__gnu__::__always_inline__]]
-       static auto&
+       static _GLIBCXX26_CONSTEXPR auto&
        _S_access(_Self& __u, _Value... __value) noexcept
        {
          static_assert(sizeof...(_Value) <= 1);
@@ -4302,23 +4383,24 @@ namespace __format
          else if constexpr (is_same_v<_Tp, _Handle<_Context>>)
            return (__u._M_handle = ... = __value);
          // Otherwise, ill-formed.
+         __builtin_unreachable();
        }
 
       template<typename _Tp>
        [[__gnu__::__always_inline__]]
-       auto&
+       _GLIBCXX26_CONSTEXPR auto&
        _M_get() noexcept
        { return _S_access<_Tp>(*this); }
 
       template<typename _Tp>
        [[__gnu__::__always_inline__]]
-       const auto&
+       _GLIBCXX26_CONSTEXPR const auto&
        _M_get() const noexcept
        { return _S_access<_Tp>(*this); }
 
       template<typename _Tp>
        [[__gnu__::__always_inline__]]
-       void
+       _GLIBCXX26_CONSTEXPR void
        _M_set(_Tp __v) noexcept
        {
          if constexpr (is_same_v<_Tp, basic_string_view<_CharT>>)
@@ -4335,7 +4417,8 @@ namespace __format
     class _Arg_store;
 
   template<typename _Visitor, typename _Ctx>
-    decltype(auto) __visit_format_arg(_Visitor&&, basic_format_arg<_Ctx>);
+    _GLIBCXX26_CONSTEXPR decltype(auto)
+    __visit_format_arg(_Visitor&&, basic_format_arg<_Ctx>);
 
   template<typename _Ch, typename _Tp>
     consteval _Arg_t
@@ -4351,20 +4434,21 @@ namespace __format
     public:
       using handle = __format::_Handle<_Context>;
       [[__gnu__::__always_inline__]]
+      _GLIBCXX26_CONSTEXPR
       basic_format_arg() noexcept : _M_type(__format::_Arg_none) { }
 
       [[nodiscard,__gnu__::__always_inline__]]
-      explicit operator bool() const noexcept
+      explicit _GLIBCXX26_CONSTEXPR operator bool() const noexcept
       { return _M_type != __format::_Arg_none; }
 
 #if __cpp_lib_format >= 202306L // >= C++26
       template<typename _Visitor>
-       decltype(auto)
+       _GLIBCXX26_CONSTEXPR decltype(auto)
        visit(this basic_format_arg __arg, _Visitor&& __vis)
        { return __arg._M_visit_user(std::forward<_Visitor>(__vis), 
__arg._M_type); }
 
       template<typename _Res, typename _Visitor>
-       _Res
+       _GLIBCXX26_CONSTEXPR _Res
        visit(this basic_format_arg __arg, _Visitor&& __vis)
        { return __arg._M_visit_user(std::forward<_Visitor>(__vis), 
__arg._M_type); }
 #endif
@@ -4541,7 +4625,7 @@ namespace __format
        }
 
       template<typename _Tp>
-       void
+       _GLIBCXX26_CONSTEXPR void
        _M_set(_Tp __v) noexcept
        {
          _M_type = _S_to_enum<_Tp>();
@@ -4550,7 +4634,7 @@ namespace __format
 
       template<typename _Tp>
        requires __format::__formattable_with<_Tp, _Context>
-       explicit
+       _GLIBCXX26_CONSTEXPR explicit
        basic_format_arg(_Tp& __v) noexcept
        {
          using _Td = _Normalize<_Tp>;
@@ -4564,15 +4648,15 @@ namespace __format
        }
 
       template<typename _Ctx, typename... _Argz>
-       friend auto
+       friend _GLIBCXX26_CONSTEXPR auto
        make_format_args(_Argz&...) noexcept;
 
       template<typename _Visitor, typename _Ctx>
-       friend decltype(auto)
+       friend _GLIBCXX26_CONSTEXPR decltype(auto)
        visit_format_arg(_Visitor&& __vis, basic_format_arg<_Ctx>);
 
       template<typename _Visitor, typename _Ctx>
-       friend decltype(auto)
+       friend _GLIBCXX26_CONSTEXPR decltype(auto)
        __format::__visit_format_arg(_Visitor&&, basic_format_arg<_Ctx>);
 
       template<typename _Ch, typename _Tp>
@@ -4580,7 +4664,7 @@ namespace __format
        __format::__to_arg_t_enum() noexcept;
 
       template<typename _Visitor>
-       decltype(auto)
+       _GLIBCXX26_CONSTEXPR decltype(auto)
        _M_visit(_Visitor&& __vis, __format::_Arg_t __type)
        {
          using namespace __format;
@@ -4655,7 +4739,7 @@ namespace __format
        }
 
       template<typename _Visitor>
-       decltype(auto)
+       _GLIBCXX26_CONSTEXPR decltype(auto)
        _M_visit_user(_Visitor&& __vis, __format::_Arg_t __type)
        {
          return _M_visit([&__vis]<typename _Tp>(_Tp& __val) -> decltype(auto)
@@ -4679,7 +4763,7 @@ namespace __format
 
   template<typename _Visitor, typename _Context>
     _GLIBCXX26_DEPRECATED_SUGGEST("std::basic_format_arg::visit")
-    inline decltype(auto)
+    inline _GLIBCXX26_CONSTEXPR decltype(auto)
     visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg)
     {
       return __arg._M_visit_user(std::forward<_Visitor>(__vis), __arg._M_type);
@@ -4689,7 +4773,7 @@ namespace __format
 namespace __format
 {
   template<typename _Visitor, typename _Ctx>
-    inline decltype(auto)
+    inline _GLIBCXX26_CONSTEXPR decltype(auto)
     __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Ctx> __arg)
     {
       return __arg._M_visit(std::forward<_Visitor>(__vis), __arg._M_type);
@@ -4698,7 +4782,7 @@ namespace __format
   struct _WidthPrecVisitor
   {
     template<typename _Tp>
-      size_t
+      _GLIBCXX26_CONSTEXPR size_t
       operator()(_Tp& __arg) const
       {
        if constexpr (is_same_v<_Tp, monostate>)
@@ -4724,7 +4808,7 @@ namespace __format
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
   template<typename _Context>
-    inline size_t
+    inline _GLIBCXX26_CONSTEXPR size_t
     __int_from_arg(const basic_format_arg<_Context>& __arg)
     { return __format::__visit_format_arg(_WidthPrecVisitor(), __arg); }
 
@@ -4772,11 +4856,11 @@ namespace __format
        const _Format_arg* _M_args;       // Active when _M_packed_size == 0
       };
 
-      size_t
+      _GLIBCXX26_CONSTEXPR size_t
       _M_size() const noexcept
       { return _M_packed_size ? _M_packed_size : _M_unpacked_size; }
 
-      typename __format::_Arg_t
+      _GLIBCXX26_CONSTEXPR typename __format::_Arg_t
       _M_type(size_t __i) const noexcept
       {
        uint64_t __t = _M_unpacked_size >> (__i * _S_packed_type_bits);
@@ -4784,7 +4868,7 @@ namespace __format
       }
 
       template<typename _Ctx, typename... _Args>
-       friend auto
+       friend _GLIBCXX26_CONSTEXPR auto
        make_format_args(_Args&...) noexcept;
 
       // An array of _Arg_t enums corresponding to _Args...
@@ -4795,10 +4879,11 @@ namespace __format
 
     public:
       template<typename... _Args>
+       _GLIBCXX26_CONSTEXPR
        basic_format_args(const _Store<_Args...>& __store) noexcept;
 
       [[nodiscard,__gnu__::__always_inline__]]
-      basic_format_arg<_Context>
+      _GLIBCXX26_CONSTEXPR basic_format_arg<_Context>
       get(size_t __i) const noexcept
       {
        basic_format_arg<_Context> __arg;
@@ -4820,7 +4905,7 @@ namespace __format
       -> basic_format_args<_Context>;
 
   template<typename _Context, typename... _Args>
-    auto
+    _GLIBCXX26_CONSTEXPR auto
     make_format_args(_Args&... __fmt_args) noexcept;
 
   // An array of type-erased formatting arguments.
@@ -4830,7 +4915,7 @@ namespace __format
       friend std::basic_format_args<_Context>;
 
       template<typename _Ctx, typename... _Argz>
-       friend auto std::
+       friend _GLIBCXX26_CONSTEXPR auto std::
 #if _GLIBCXX_INLINE_VERSION
        __8:: // Needed for PR c++/59256
 #endif
@@ -4849,7 +4934,7 @@ namespace __format
       _Element_t _M_args[sizeof...(_Args)];
 
       template<typename _Tp>
-       static _Element_t
+       static _GLIBCXX26_CONSTEXPR _Element_t
        _S_make_elt(_Tp& __v)
        {
          using _Tq = remove_const_t<_Tp>;
@@ -4875,6 +4960,7 @@ namespace __format
       template<typename... _Tp>
        requires (sizeof...(_Tp) == sizeof...(_Args))
        [[__gnu__::__always_inline__]]
+       _GLIBCXX26_CONSTEXPR
        _Arg_store(_Tp&... __a) noexcept
        : _M_args{_S_make_elt(__a)...}
        { }
@@ -4886,7 +4972,7 @@ namespace __format
 
   template<typename _Context>
     template<typename... _Args>
-      inline
+      inline _GLIBCXX26_CONSTEXPR
       basic_format_args<_Context>::
       basic_format_args(const _Store<_Args...>& __store) noexcept
       {
@@ -4920,7 +5006,7 @@ namespace __format
   /// Capture formatting arguments for use by `std::vformat`.
   template<typename _Context = format_context, typename... _Args>
     [[nodiscard,__gnu__::__always_inline__]]
-    inline auto
+    inline _GLIBCXX26_CONSTEXPR auto
     make_format_args(_Args&... __fmt_args) noexcept
     {
       using _Fmt_arg = basic_format_arg<_Context>;
@@ -4933,7 +5019,7 @@ namespace __format
   /// Capture formatting arguments for use by `std::vformat` (for wide output).
   template<typename... _Args>
     [[nodiscard,__gnu__::__always_inline__]]
-    inline auto
+    inline _GLIBCXX26_CONSTEXPR auto
     make_wformat_args(_Args&... __args) noexcept
     { return std::make_format_args<wformat_context>(__args...); }
 #endif
@@ -4942,13 +5028,13 @@ namespace __format
 namespace __format
 {
   template<typename _Out, typename _CharT, typename _Context>
-    _Out
+    _GLIBCXX26_CONSTEXPR _Out
     __do_vformat_to(_Out, basic_string_view<_CharT>,
                    const basic_format_args<_Context>&,
                    const locale* = nullptr);
 
   template<typename _Out, typename _CharT>
-    format_to_n_result<_Out>
+    _GLIBCXX26_CONSTEXPR format_to_n_result<_Out>
     __do_vformat_to_n(_Out, iter_difference_t<_Out>,
                      basic_string_view<_CharT>,
                      const type_identity_t<
@@ -4982,11 +5068,13 @@ namespace __format
       _Out _M_out;
       __format::_Optional_locale _M_loc;
 
+      _GLIBCXX26_CONSTEXPR
       basic_format_context(basic_format_args<basic_format_context> __args,
                           _Out __out)
       : _M_args(__args), _M_out(std::move(__out))
       { }
 
+      _GLIBCXX26_CONSTEXPR
       basic_format_context(basic_format_args<basic_format_context> __args,
                           _Out __out, const std::locale& __loc)
       : _M_args(__args), _M_out(std::move(__out)), _M_loc(__loc)
@@ -4999,7 +5087,7 @@ namespace __format
       basic_format_context& operator=(const basic_format_context&) = delete;
 
       template<typename _Out2, typename _CharT2, typename _Context2>
-       friend _Out2
+       friend _GLIBCXX26_CONSTEXPR _Out2
        __format::__do_vformat_to(_Out2, basic_string_view<_CharT2>,
                                  const basic_format_args<_Context2>&,
                                  const locale*);
@@ -5015,7 +5103,7 @@ namespace __format
        using formatter_type = formatter<_Tp, _CharT>;
 
       [[nodiscard]]
-      basic_format_arg<basic_format_context>
+      _GLIBCXX26_CONSTEXPR basic_format_arg<basic_format_context>
       arg(size_t __id) const noexcept
       { return _M_args.get(__id); }
 
@@ -5023,9 +5111,11 @@ namespace __format
       std::locale locale() { return _M_loc.value(); }
 
       [[nodiscard]]
-      iterator out() { return std::move(_M_out); }
+      _GLIBCXX26_CONSTEXPR iterator
+      out() { return std::move(_M_out); }
 
-      void advance_to(iterator __it) { _M_out = std::move(__it); }
+      _GLIBCXX26_CONSTEXPR void
+      advance_to(iterator __it) { _M_out = std::move(__it); }
     };
 
 
@@ -5164,6 +5254,7 @@ namespace __format
     class _Formatting_scanner : public _Scanner<_CharT>
     {
     public:
+      _GLIBCXX26_CONSTEXPR
       _Formatting_scanner(basic_format_context<_Out, _CharT>& __fc,
                          basic_string_view<_CharT> __str)
       : _Scanner<_CharT>(__str), _M_fc(__fc)
@@ -5271,7 +5362,7 @@ namespace __format
     };
 
   template<typename _Out, typename _CharT, typename _Context>
-    inline _Out
+    inline _GLIBCXX26_CONSTEXPR _Out
     __do_vformat_to(_Out __out, basic_string_view<_CharT> __fmt,
                    const basic_format_args<_Context>& __args,
                    const locale* __loc)
@@ -5291,7 +5382,7 @@ namespace __format
                      const char* __chars[] = { "false", "true" };
                      if (auto __res = __out._M_reserve(__len))
                        {
-                         __builtin_memcpy(__res.get(), __chars[__arg], __len);
+                         ranges::copy_n(__chars[__arg], __len, __res.get());
                          __res._M_bump(__len);
                          __done = true;
                        }
@@ -5329,7 +5420,7 @@ namespace __format
                      string_view __sv = __arg;
                      if (auto __res = __out._M_reserve(__sv.size()))
                        {
-                         __builtin_memcpy(__res.get(), __sv.data(), 
__sv.size());
+                         ranges::copy(__sv, __res.get());
                          __res._M_bump(__sv.size());
                          __done = true;
                        }
@@ -5347,14 +5438,16 @@ namespace __format
          __scanner._M_scan();
          return __out;
        }
-      else if constexpr (__contiguous_char_iter<_CharT, _Out>)
-       {
-         _Ptr_sink<_CharT> __sink(__out);
-         __format::__do_vformat_to(__sink.out(), __fmt, __args, __loc);
-         return std::move(__sink)._M_finish(__out).out;
-       }
       else
        {
+         if constexpr (__contiguous_char_iter<_CharT, _Out>)
+           if (!std::is_constant_evaluated())
+             {
+               _Ptr_sink<_CharT> __sink(__out);
+               __format::__do_vformat_to(__sink.out(), __fmt, __args, __loc);
+               return std::move(__sink)._M_finish(__out).out;
+             }
+
          _Iter_sink<_CharT, _Out> __sink(std::move(__out));
          __format::__do_vformat_to(__sink.out(), __fmt, __args, __loc);
          return std::move(__sink)._M_finish().out;
@@ -5362,7 +5455,7 @@ namespace __format
     }
 
   template<typename _Out, typename _CharT>
-    format_to_n_result<_Out>
+    _GLIBCXX26_CONSTEXPR format_to_n_result<_Out>
     __do_vformat_to_n(_Out __out, iter_difference_t<_Out> __n,
                      basic_string_view<_CharT> __fmt,
                      const type_identity_t<
@@ -5402,7 +5495,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>()...
            };
@@ -5420,7 +5517,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>...>
@@ -5432,14 +5529,14 @@ namespace __format
 
   template<typename _Out> requires output_iterator<_Out, const char&>
     [[__gnu__::__always_inline__]]
-    inline _Out
+    inline _GLIBCXX26_CONSTEXPR _Out
     vformat_to(_Out __out, string_view __fmt, format_args __args)
     { return __format::__do_vformat_to(std::move(__out), __fmt, __args); }
 
 #ifdef _GLIBCXX_USE_WCHAR_T
   template<typename _Out> requires output_iterator<_Out, const wchar_t&>
     [[__gnu__::__always_inline__]]
-    inline _Out
+    inline _GLIBCXX26_CONSTEXPR _Out
     vformat_to(_Out __out, wstring_view __fmt, wformat_args __args)
     { return __format::__do_vformat_to(std::move(__out), __fmt, __args); }
 #endif
@@ -5465,7 +5562,7 @@ namespace __format
 #endif
 
   [[nodiscard]]
-  inline string
+  inline _GLIBCXX26_CONSTEXPR string
   vformat(string_view __fmt, format_args __args)
   {
     __format::_Str_sink<char> __buf;
@@ -5475,7 +5572,7 @@ namespace __format
 
 #ifdef _GLIBCXX_USE_WCHAR_T
   [[nodiscard]]
-  inline wstring
+  inline _GLIBCXX26_CONSTEXPR wstring
   vformat(wstring_view __fmt, wformat_args __args)
   {
     __format::_Str_sink<wchar_t> __buf;
@@ -5506,14 +5603,14 @@ namespace __format
 
   template<typename... _Args>
     [[nodiscard]]
-    inline string
+    inline _GLIBCXX26_CONSTEXPR string
     format(format_string<_Args...> __fmt, _Args&&... __args)
     { return std::vformat(__fmt.get(), std::make_format_args(__args...)); }
 
 #ifdef _GLIBCXX_USE_WCHAR_T
   template<typename... _Args>
     [[nodiscard]]
-    inline wstring
+    inline _GLIBCXX26_CONSTEXPR wstring
     format(wformat_string<_Args...> __fmt, _Args&&... __args)
     { return std::vformat(__fmt.get(), std::make_wformat_args(__args...)); }
 #endif
@@ -5542,7 +5639,7 @@ namespace __format
 
   template<typename _Out, typename... _Args>
     requires output_iterator<_Out, const char&>
-    inline _Out
+    inline _GLIBCXX26_CONSTEXPR _Out
     format_to(_Out __out, format_string<_Args...> __fmt, _Args&&... __args)
     {
       return std::vformat_to(std::move(__out), __fmt.get(),
@@ -5552,7 +5649,7 @@ namespace __format
 #ifdef _GLIBCXX_USE_WCHAR_T
   template<typename _Out, typename... _Args>
     requires output_iterator<_Out, const wchar_t&>
-    inline _Out
+    inline _GLIBCXX26_CONSTEXPR _Out
     format_to(_Out __out, wformat_string<_Args...> __fmt, _Args&&... __args)
     {
       return std::vformat_to(std::move(__out), __fmt.get(),
@@ -5584,7 +5681,7 @@ namespace __format
 
   template<typename _Out, typename... _Args>
     requires output_iterator<_Out, const char&>
-    inline format_to_n_result<_Out>
+    inline _GLIBCXX26_CONSTEXPR format_to_n_result<_Out>
     format_to_n(_Out __out, iter_difference_t<_Out> __n,
                format_string<_Args...> __fmt, _Args&&... __args)
     {
@@ -5596,7 +5693,7 @@ namespace __format
 #ifdef _GLIBCXX_USE_WCHAR_T
   template<typename _Out, typename... _Args>
     requires output_iterator<_Out, const wchar_t&>
-    inline format_to_n_result<_Out>
+    inline _GLIBCXX26_CONSTEXPR format_to_n_result<_Out>
     format_to_n(_Out __out, iter_difference_t<_Out> __n,
                wformat_string<_Args...> __fmt, _Args&&... __args)
     {
@@ -5638,10 +5735,11 @@ namespace __format
     class _Counting_sink final : public _Ptr_sink<_CharT>
     {
     public:
+      _GLIBCXX26_CONSTEXPR
       _Counting_sink() : _Ptr_sink<_CharT>(nullptr, 0) { }
 
       [[__gnu__::__always_inline__]]
-      size_t
+      _GLIBCXX26_CONSTEXPR size_t
       count() const
       { return this->_M_count + this->_M_used().size(); }
     };
@@ -5676,7 +5774,7 @@ namespace __format
 
   template<typename... _Args>
     [[nodiscard]]
-    inline size_t
+    inline _GLIBCXX26_CONSTEXPR size_t
     formatted_size(format_string<_Args...> __fmt, _Args&&... __args)
     {
       __format::_Counting_sink<char> __buf;
@@ -5688,7 +5786,7 @@ namespace __format
 #ifdef _GLIBCXX_USE_WCHAR_T
   template<typename... _Args>
     [[nodiscard]]
-    inline size_t
+    inline _GLIBCXX26_CONSTEXPR size_t
     formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args)
     {
       __format::_Counting_sink<wchar_t> __buf;
@@ -5759,6 +5857,7 @@ namespace __format
 namespace __format
 {
   template<typename _CharT, typename _Out, typename _Callback>
+    _GLIBCXX26_CONSTEXPR
     typename basic_format_context<_Out, _CharT>::iterator
     __format_padded(basic_format_context<_Out, _CharT>& __fc,
                    const _Spec<_CharT>& __spec,
@@ -5778,14 +5877,16 @@ namespace __format
 
          struct _Restore_out
          {
+          _GLIBCXX26_CONSTEXPR
           _Restore_out(basic_format_context<_Sink_iter<_CharT>, _CharT>& __fc)
           : _M_ctx(std::addressof(__fc)), _M_out(__fc.out())
          { }
 
-         void
+         _GLIBCXX26_CONSTEXPR void
          _M_disarm()
          { _M_ctx = nullptr; }
 
+         _GLIBCXX26_CONSTEXPR
          ~_Restore_out()
          {
            if (_M_ctx)
@@ -5819,7 +5920,7 @@ namespace __format
       }
 
       template<typename _Out>
-       void
+       _GLIBCXX26_CONSTEXPR void
        _M_format(__maybe_const<_Tp, _CharT>& __elem,
                  basic_format_context<_Out, _CharT>& __fc,
                  basic_string_view<_CharT> __sep) const
@@ -5917,12 +6018,14 @@ namespace __format
 
     protected:
       template<typename _Tuple, typename _Out, size_t... _Ids>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        _M_format(_Tuple& __tuple, index_sequence<_Ids...>,
                  basic_format_context<_Out, _CharT>& __fc) const
        { return _M_format_elems(std::get<_Ids>(__tuple)..., __fc); }
 
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        _M_format_elems(__maybe_const<_Tps, _CharT>&... __elems,
                        basic_format_context<_Out, _CharT>& __fc) const
@@ -5952,7 +6055,7 @@ namespace __format
          }
 
          template<typename _Out>
-           void
+           _GLIBCXX26_CONSTEXPR void
            _M_format(__maybe_const<_Tps, _CharT>&... __elems,
                      basic_format_context<_Out, _CharT>& __fc,
                      _String_view __sep) const
@@ -5968,7 +6071,7 @@ namespace __format
        };
 
       template<size_t... _Ids>
-       static auto
+       static _GLIBCXX26_CONSTEXPR auto
        _S_create_storage(index_sequence<_Ids...>)
          -> __formatters_storage<_Ids...>;
       using _Formatters
@@ -6004,6 +6107,7 @@ namespace __format
       // We deviate from standard, that declares this as template accepting
       // unconstrained FormatContext type, which seems unimplementable.
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        format(__maybe_const_pair& __p,
               basic_format_context<_Out, _CharT>& __fc) const
@@ -6031,6 +6135,7 @@ namespace __format
       // We deviate from standard, that declares this as template accepting
       // unconstrained FormatContext type, which seems unimplementable.
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        format(__maybe_const_tuple& __t,
               basic_format_context<_Out, _CharT>& __fc) const
@@ -6194,6 +6299,7 @@ namespace __format
       template<ranges::input_range _Rg, typename _Out>
        requires formattable<ranges::range_reference_t<_Rg>, _CharT> &&
                 same_as<remove_cvref_t<ranges::range_reference_t<_Rg>>, _Tp>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        format(_Rg&& __rg, basic_format_context<_Out, _CharT>& __fc) const
        {
@@ -6206,6 +6312,7 @@ namespace __format
 
     private:
       template<ranges::input_range _Rg, typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        _M_format(_Rg& __rg, basic_format_context<_Out, _CharT>& __fc) const
        {
@@ -6223,6 +6330,7 @@ namespace __format
 
 
       template<ranges::input_range _Rg, typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        _M_format_elems(_Rg& __rg,
                        basic_format_context<_Out, _CharT>& __fc) const
@@ -6322,6 +6430,7 @@ namespace __format
       // We deviate from standard, that declares this as template accepting
       // unconstrained FormatContext type, which seems unimplementable.
       template<typename _Out>
+       _GLIBCXX26_CONSTEXPR
        typename basic_format_context<_Out, _CharT>::iterator
        format(__format::__maybe_const_range<_Rg, _CharT>& __rg,
               basic_format_context<_Out, _CharT>& __fc) const
diff --git a/libstdc++-v3/testsuite/std/format/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..943a57cc5f8
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/constexpr.cc
@@ -0,0 +1,156 @@
+// { dg-do compile { target c++26 } }
+
+#include <format>
+#include <string>
+#include <string_view>
+#include <tuple>
+#include <vector>
+#include <testsuite_hooks.h>
+
+// 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());
diff --git a/libstdc++-v3/testsuite/std/format/debug.cc 
b/libstdc++-v3/testsuite/std/format/debug.cc
index 43e930c579e..1e17ff17ef5 100644
--- a/libstdc++-v3/testsuite/std/format/debug.cc
+++ b/libstdc++-v3/testsuite/std/format/debug.cc
@@ -1,26 +1,32 @@
-// { dg-options "-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32LE 
-DUNICODE_ENC" { target le } }
-// { dg-options "-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32BE 
-DUNICODE_ENC" { target be } }
+// { dg-options "-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32LE 
-DUNICODE_ENC -fconstexpr-ops-limit=500000000" { target le } }
+// { dg-options "-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32BE 
-DUNICODE_ENC -fconstexpr-ops-limit=500000000" { target be } }
 // { dg-do run { target c++23 } }
 // { dg-require-effective-target 4byte_wchar_t }
 // { dg-add-options no_pch }
 // { dg-timeout-factor 2 }
 
+#if __cplusplus >= 202400L
+# define constexpr26 constexpr
+#else
+# define constexpr26
+#endif
+
 #include <format>
 #include <testsuite_hooks.h>
 
-std::string
+constexpr26 std::string
 fdebug(char t)
 { return std::format("{:?}", t); }
 
-std::wstring
+constexpr26 std::wstring
 fdebug(wchar_t t)
 { return std::format(L"{:?}", t); }
 
-std::string
+constexpr26 std::string
 fdebug(std::string_view t)
 { return std::format("{:?}", t); }
 
-std::wstring
+constexpr26 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
+constexpr26 void
 test_basic_escapes()
 {
   std::basic_string<CharT> res;
@@ -72,7 +78,7 @@ test_basic_escapes()
 }
 
 template<typename CharT>
-void
+constexpr26 void
 test_ascii_escapes()
 {
   std::basic_string<CharT> res;
@@ -89,7 +95,7 @@ test_ascii_escapes()
 }
 
 template<typename CharT>
-void
+constexpr26 void
 test_extended_ascii()
 {
   std::basic_string<CharT> res;
@@ -117,7 +123,7 @@ test_extended_ascii()
 }
 
 template<typename CharT>
-void
+constexpr26 void
 test_unicode_escapes()
 {
 #if UNICODE_ENC
@@ -166,7 +172,7 @@ test_unicode_escapes()
 }
 
 template<typename CharT>
-void
+constexpr26 void
 test_grapheme_extend()
 {
 #if UNICODE_ENC
@@ -192,7 +198,7 @@ test_grapheme_extend()
 }
 
 template<typename CharT>
-void
+constexpr26 void
 test_replacement_char()
 {
 #if UNICODE_ENC
@@ -206,7 +212,7 @@ test_replacement_char()
 #endif // UNICODE_ENC
 }
 
-void
+constexpr26 void
 test_ill_formed_utf8_seq()
 {
 #if UNICODE_ENC
@@ -244,7 +250,7 @@ test_ill_formed_utf8_seq()
 #endif // UNICODE_ENC
 }
 
-void
+constexpr26 void
 test_ill_formed_utf32()
 {
 #if UNICODE_ENC
@@ -269,7 +275,7 @@ test_ill_formed_utf32()
 }
 
 template<typename CharT>
-void
+constexpr26 void
 test_fill()
 {
   std::basic_string<CharT> res;
@@ -315,7 +321,7 @@ test_fill()
 }
 
 template<typename CharT>
-void
+constexpr26 void
 test_prec()
 {
   std::basic_string<CharT> res;
@@ -341,7 +347,8 @@ test_prec()
 #endif // UNICODE_ENC
 }
 
-bool strip_quote(std::string_view& v)
+constexpr26 bool
+strip_quote(std::string_view& v)
 {
   if (!v.starts_with('"'))
     return false;
@@ -349,7 +356,8 @@ bool strip_quote(std::string_view& v)
   return true;
 }
 
-bool strip_quotes(std::string_view& v)
+constexpr26 bool
+strip_quotes(std::string_view& v)
 {
   if (!v.starts_with('"') || !v.ends_with('"'))
     return false;
@@ -358,7 +366,8 @@ bool strip_quotes(std::string_view& v)
   return true;
 }
 
-bool strip_prefix(std::string_view& v, size_t n, char c)
+constexpr26 bool
+strip_prefix(std::string_view& v, size_t n, char c)
 {
   size_t pos = v.find_first_not_of(c);
   if (pos == std::string_view::npos)
@@ -369,7 +378,8 @@ bool strip_prefix(std::string_view& v, size_t n, char c)
   return true;
 }
 
-void test_padding()
+constexpr26 void
+test_padding()
 {
   std::string res;
   std::string_view resv;
@@ -719,7 +729,8 @@ void test_padding()
 #endif // UNICODE_ENC
 }
 
-void test_char_as_wchar()
+constexpr26 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
+  constexpr26 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
+constexpr26 void
 test_formatter_str()
 {
   CharT buf[]{ 'a', 'b', 'c', 0 };
@@ -770,7 +782,7 @@ test_formatter_str()
 }
 
 template<typename CharT>
-void
+constexpr26 void
 test_formatter_arr()
 {
   std::basic_string<CharT> res;
@@ -786,7 +798,7 @@ test_formatter_arr()
 }
 
 template<typename CharT, typename SrcT>
-void
+constexpr26 void
 test_formatter_char()
 {
   DebugWrapper<SrcT> in{ 'a' };
@@ -795,7 +807,7 @@ test_formatter_char()
 }
 
 template<typename CharT>
-void
+constexpr26 void
 test_formatters()
 {
   test_formatter_char<CharT, CharT>();
@@ -806,7 +818,7 @@ test_formatters()
   test_formatter_arr<CharT>();
 }
 
-void
+constexpr26 void
 test_formatters_c()
 {
   test_formatters<char>();
@@ -814,7 +826,8 @@ test_formatters_c()
   test_formatter_char<wchar_t, char>();
 }
 
-int main()
+constexpr26 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;
+}
+
+#if __cplusplus >= 202400L
+static_assert(test_all());
+#endif
+
+int main()
+{
+  test_all();
 }
diff --git a/libstdc++-v3/testsuite/std/format/functions/format.cc 
b/libstdc++-v3/testsuite/std/format/functions/format.cc
index d342114083e..12253242833 100644
--- a/libstdc++-v3/testsuite/std/format/functions/format.cc
+++ b/libstdc++-v3/testsuite/std/format/functions/format.cc
@@ -3,6 +3,12 @@
 // { dg-add-options no_pch }
 // { dg-additional-options "-DUNICODE" { target 4byte_wchar_t } }
 
+#if __cplusplus >= 202400L
+# define constexpr26 constexpr
+#else
+# define constexpr26
+#endif
+
 #include <format>
 
 #ifndef __cpp_lib_format
@@ -41,7 +47,7 @@
 #include <cstdio>
 #include <testsuite_hooks.h>
 
-void
+constexpr26 void
 test_no_args()
 {
   std::string s;
@@ -55,7 +61,7 @@ test_no_args()
   VERIFY( s == "128bpm }" );
 }
 
-void
+constexpr26 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
+constexpr26 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
+constexpr26 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
+constexpr26 void
 test_width()
 {
   std::string s;
@@ -317,7 +330,7 @@ test_width()
   }
 }
 
-void
+constexpr26 void
 test_char()
 {
   std::string s;
@@ -347,7 +360,7 @@ test_char()
   VERIFY( s == "11110000 11110000 240 360 f0 F0" );
 }
 
-void
+constexpr26 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
+constexpr26 void
 test_minmax()
 {
   auto check = []<typename T, typename U = std::make_unsigned_t<T>>(T, U = 0) {
@@ -422,7 +441,7 @@ test_minmax()
 #endif
 }
 
-void
+constexpr26 void
 test_p1652r1() // printf corner cases in std::format
 {
   std::string s;
@@ -436,27 +455,33 @@ test_p1652r1() // printf corner cases in std::format
   s = std::format("{:c}", c);
   VERIFY( s == "A" );
 
-  // Problem 3: "-000nan" is not a floating point value
-  double nan = std::numeric_limits<double>::quiet_NaN();
-  try {
-    s = std::vformat("{:0=6}", std::make_format_args(nan));
-    VERIFY( false );
-  } catch (const std::format_error&) {
-  }
-
-  s = std::format("{:06}", nan);
-  VERIFY( s == "   nan" );
+  if (!std::is_constant_evaluated())
+    {
+      // Problem 3: "-000nan" is not a floating point value
+      double nan = std::numeric_limits<double>::quiet_NaN();
+      try {
+       s = std::vformat("{:0=6}", std::make_format_args(nan));
+       VERIFY( false );
+      } catch (const std::format_error&) {
+      }
+  
+      s = std::format("{:06}", nan);
+      VERIFY( s == "   nan" );
+    }
 
   // Problem 4: bool needs a type format specifier
   s = std::format("{:s}", true);
   VERIFY( s == "true" );
 
-  // Problem 5: double does not roundtrip float
-  s = std::format("{}", 3.31f);
-  VERIFY( s == "3.31" );
+  if (!std::is_constant_evaluated())
+    {
+      // Problem 5: double does not roundtrip float
+      s = std::format("{}", 3.31f);
+      VERIFY( s == "3.31" );
+    }
 }
 
-void
+constexpr26 void
 test_pointer()
 {
   void* p = nullptr;
@@ -477,28 +502,31 @@ test_pointer()
   s = std::format("{:o<4},{:o>5},{:o^7}", p, pc, nullptr); // fill+align+width
   VERIFY( s == "0x0o,oo0x0,oo0x0oo" );
 
-  pc = p = &s;
-  str_int = std::format("{:#x}", reinterpret_cast<std::uintptr_t>(p));
-  s = std::format("{} {} {}", p, pc, nullptr);
-  VERIFY( s == (str_int + ' ' + str_int + " 0x0") );
-  str_int = std::format("{:#20x}", reinterpret_cast<std::uintptr_t>(p));
-  s = std::format("{:20} {:20p}", p, pc);
-  VERIFY( s == (str_int + ' ' + str_int) );
+  if (!std::is_constant_evaluated())
+    {
+      pc = p = &s;
+      str_int = std::format("{:#x}", reinterpret_cast<std::uintptr_t>(p));
+      s = std::format("{} {} {}", p, pc, nullptr);
+      VERIFY( s == (str_int + ' ' + str_int + " 0x0") );
+      str_int = std::format("{:#20x}", reinterpret_cast<std::uintptr_t>(p));
+      s = std::format("{:20} {:20p}", p, pc);
+      VERIFY( s == (str_int + ' ' + str_int) );
 
 #if __cpp_lib_format >= 202304L
-  // P2510R3 Formatting pointers
-  s = std::format("{:06} {:07P} {:08p}", (void*)0, (const void*)0, nullptr);
-  VERIFY( s == "0x0000 0X00000 0x000000" );
-  str_int = std::format("{:#016x}", reinterpret_cast<std::uintptr_t>(p));
-  s = std::format("{:016} {:016}", p, pc);
-  VERIFY( s == (str_int + ' ' + str_int) );
-  str_int = std::format("{:#016X}", reinterpret_cast<std::uintptr_t>(p));
-  s = std::format("{:016P} {:016P}", p, pc);
-  VERIFY( s == (str_int + ' ' + str_int) );
+      // P2510R3 Formatting pointers
+      s = std::format("{:06} {:07P} {:08p}", (void*)0, (const void*)0, 
nullptr);
+      VERIFY( s == "0x0000 0X00000 0x000000" );
+      str_int = std::format("{:#016x}", reinterpret_cast<std::uintptr_t>(p));
+      s = std::format("{:016} {:016}", p, pc);
+      VERIFY( s == (str_int + ' ' + str_int) );
+      str_int = std::format("{:#016X}", reinterpret_cast<std::uintptr_t>(p));
+      s = std::format("{:016P} {:016P}", p, pc);
+      VERIFY( s == (str_int + ' ' + str_int) );
 #endif
+    }
 }
 
-void
+constexpr26 void
 test_bool()
 {
   std::string s;
@@ -519,7 +547,7 @@ test_bool()
   VERIFY( s == "0 0x1 0X0" );
 }
 
-void
+constexpr26 void
 test_unicode()
 {
 #ifdef UNICODE
@@ -579,13 +607,13 @@ test_unicode()
 #endif
 }
 
-int main()
+constexpr26 bool
+test_all()
 {
   test_no_args();
   test_unescaped();
   test_std_examples();
   test_alternate_forms();
-  test_locale();
   test_width();
   test_char();
   test_wchar();
@@ -594,4 +622,21 @@ int main()
   test_pointer();
   test_bool();
   test_unicode();
+
+  if (!std::is_constant_evaluated())
+    {
+      test_infnan();
+      test_locale();
+    }
+
+  return true;
+}
+
+#if __cplusplus >= 202400L
+static_assert(test_all());
+#endif
+
+int main()
+{
+  test_all();
 }
diff --git a/libstdc++-v3/testsuite/std/format/functions/format_to.cc 
b/libstdc++-v3/testsuite/std/format/functions/format_to.cc
index 94e6262bc66..5ad64ae4061 100644
--- a/libstdc++-v3/testsuite/std/format/functions/format_to.cc
+++ b/libstdc++-v3/testsuite/std/format/functions/format_to.cc
@@ -1,5 +1,11 @@
 // { dg-do run { target c++20 } }
 
+#if __cplusplus >= 202400L
+# define constexpr26 constexpr
+#else
+# define constexpr26
+#endif
+
 #include <format>
 #include <locale>
 #include <vector>
@@ -11,17 +17,20 @@ struct punct : std::numpunct<char>
   std::string do_grouping() const override { return "\2"; }
 };
 
-void
+constexpr26 void
 test()
 {
   char buf[32] = { };
   auto out = std::format_to(buf, "test");
   VERIFY( out == buf+4 );
 
-  std::locale loc({}, new punct);
-  auto out2 = std::format_to(buf, loc, "{:Ld}", 12345);
-  VERIFY( out2 == buf+7 );
-  VERIFY( std::string_view(buf, out2 - buf) == "1,23,45" );
+  if (!std::is_constant_evaluated())
+    {
+      std::locale loc({}, new punct);
+      auto out2 = std::format_to(buf, loc, "{:Ld}", 12345);
+      VERIFY( out2 == buf+7 );
+      VERIFY( std::string_view(buf, out2 - buf) == "1,23,45" );
+    }
 }
 
 struct wpunct : std::numpunct<wchar_t>
@@ -29,17 +38,20 @@ struct wpunct : std::numpunct<wchar_t>
   std::string do_grouping() const override { return "\2"; }
 };
 
-void
+constexpr26 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
+constexpr26 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
+constexpr26 void
 test_pr110917()
 {
   // PR libstdc++/110917
@@ -90,10 +102,22 @@ test_pr110917()
   VERIFY( ! std::memcmp(buf, "abc 123", 7) );
 }
 
-int main()
+constexpr26 bool
+test_all()
 {
   test();
   test_wchar();
   test_move_only();
   test_pr110917();
+
+  return true;
+}
+
+#if __cplusplus >= 202400L
+static_assert(test_all());
+#endif
+
+int main()
+{
+  test_all();
 }
diff --git a/libstdc++-v3/testsuite/std/format/functions/size.cc 
b/libstdc++-v3/testsuite/std/format/functions/size.cc
index 1ece4108d85..78c5ccc778a 100644
--- a/libstdc++-v3/testsuite/std/format/functions/size.cc
+++ b/libstdc++-v3/testsuite/std/format/functions/size.cc
@@ -1,10 +1,16 @@
 // { dg-do run { target c++20 } }
 
+#if __cplusplus >= 202400L
+# define constexpr26 constexpr
+#else
+# define constexpr26
+#endif
+
 #include <format>
 #include <string>
 #include <testsuite_hooks.h>
 
-void
+constexpr26 void
 test()
 {
   auto n = std::formatted_size("");
@@ -24,7 +30,7 @@ test()
   VERIFY( n == 5 );
 }
 
-void
+constexpr26 void
 test_wchar()
 {
   auto n = std::formatted_size(L"");
@@ -44,8 +50,19 @@ test_wchar()
   VERIFY( n == 5 );
 }
 
-int main()
+constexpr26 bool
+test_all()
 {
   test();
   test_wchar();
+  return true;
+}
+
+#if __cplusplus >= 202400L
+static_assert(test_all());
+#endif
+
+int main()
+{
+  test_all();
 }
diff --git a/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc 
b/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc
index 1450fbaebc5..48795440d13 100644
--- a/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc
+++ b/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc
@@ -1,5 +1,11 @@
 // { dg-do run { target c++23 } }
 
+#if __cplusplus >= 202400L
+# define constexpr26 constexpr
+#else
+# define constexpr26
+#endif
+
 #include <deque>
 #include <flat_map>
 #include <flat_set>
@@ -64,7 +70,8 @@ struct CustFormat : std::vector<T>
 template<typename T, std::range_format rf>
 constexpr auto std::format_kind<CustFormat<T, rf>> = rf;
 
-void test_override()
+constexpr26 bool
+test_override()
 {
   CustFormat<int, std::range_format::disabled> disabledf;
   static_assert( !std::formattable<decltype(disabledf), char> );
@@ -88,8 +95,14 @@ void test_override()
   VERIFY( std::format("{}", debugf) == R"("abcd")" );
   // Support precision as string do
   VERIFY( std::format("{:.3}", debugf) == R"("ab)" );
+
+  return true;
 }
 
+#if __cplusplus >= 202400L
+static_assert(test_override());
+#endif
+
 int main()
 {
   test_override();
diff --git a/libstdc++-v3/testsuite/std/format/ranges/formatter.cc 
b/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
index a50c5b1033f..d732cdf66ad 100644
--- a/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
+++ b/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
@@ -1,5 +1,11 @@
 // { dg-do run { target c++23 } }
 
+#if __cplusplus >= 202400L
+# define constexpr26 constexpr
+#else
+# define constexpr26
+#endif
+
 #include <flat_map>
 #include <format>
 #include <testsuite_hooks.h>
@@ -32,7 +38,7 @@ struct std::formatter<MyVector<T, Formatter>, CharT>
   { return _formatter.parse(pc);  }
 
   template<typename Out>
-  typename std::basic_format_context<Out, CharT>::iterator
+  constexpr26 std::basic_format_context<Out, CharT>::iterator
   format(const MyVector<T, Formatter>& mv,
         std::basic_format_context<Out, CharT>& fc) const
   { return _formatter.format(mv, fc); }
@@ -42,7 +48,7 @@ private:
 };
 
 template<typename CharT, template<typename, typename> class Formatter>
-void
+constexpr26 void
 test_default()
 {
   MyVector<int, Formatter> vec{1, 2, 3};
@@ -94,7 +100,7 @@ test_default()
 }
 
 template<typename CharT, template<typename, typename> class Formatter>
-void
+constexpr26 void
 test_override()
 {
   MyVector<CharT, Formatter> vc{'a', 'b', 'c', 'd'};
@@ -115,7 +121,8 @@ test_override()
 }
 
 template<template<typename, typename> class Formatter>
-void test_outputs()
+constexpr26 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
+constexpr26 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()
+constexpr26 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()
+constexpr26 void
+test_nonblocking()
 {
   static_assert(!std::enable_nonlocking_formatter_optimization<
                  Range<int>>);
 }
 
-int main()
+constexpr26 bool
+test_all()
 {
   test_outputs<std::range_formatter>();
   test_outputs<VectorFormatter>();
@@ -179,4 +189,15 @@ int main()
   test_nonblocking<std::span>();
   test_nonblocking<std::vector>();
   test_nonblocking<MyVector>();
+
+  return true;
+}
+
+#if __cplusplus >= 202400L
+static_assert(test_all());
+#endif
+
+int main()
+{
+  test_all();
 }
diff --git a/libstdc++-v3/testsuite/std/format/ranges/sequence.cc 
b/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
index 7fb65f9c551..a3fd3df5099 100644
--- a/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
+++ b/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
@@ -1,7 +1,13 @@
 // { dg-do run { target c++23 } }
-// { dg-options "-fexec-charset=UTF-8" }
+// { dg-options "-fexec-charset=UTF-8 -fconstexpr-ops-limit=5000000000" }
 // { dg-timeout-factor 2 }
 
+#if __cplusplus >= 202400L
+# define constexpr26 constexpr
+#else
+# define constexpr26
+#endif
+
 #include <array>
 #include <format>
 #include <list>
@@ -19,7 +25,7 @@ static_assert(!std::formattable<std::vector<NotFormattable>, 
char>);
 static_assert(!std::formattable<std::span<NotFormattable>, wchar_t>);
 
 template<typename... Args>
-bool
+constexpr26 bool
 is_format_string_for(const char* str, Args&&... args)
 {
   try {
@@ -31,7 +37,7 @@ is_format_string_for(const char* str, Args&&... args)
 }
 
 template<typename... Args>
-bool
+constexpr26 bool
 is_format_string_for(const wchar_t* str, Args&&... args)
 {
   try {
@@ -43,7 +49,8 @@ is_format_string_for(const wchar_t* str, Args&&... args)
 }
 
 template<typename Rg, typename CharT>
-bool is_range_formatter_spec_for(CharT const* spec, Rg&& rg)
+constexpr26 bool
+is_range_formatter_spec_for(CharT const* spec, Rg&& rg)
 {
   using V = std::remove_cvref_t<std::ranges::range_reference_t<Rg>>;
   std::range_formatter<V, CharT> fmt;
@@ -56,7 +63,7 @@ bool is_range_formatter_spec_for(CharT const* spec, Rg&& rg)
   }
 }
 
-void
+constexpr26 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()
+constexpr26 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()
+constexpr26 void
+test_output_cont()
 {
   test_output<char, Cont&, Cont>();
   test_output<wchar_t, Cont const&, Cont>();
 }
 
 template<typename View>
-void test_output_view()
+constexpr26 void
+test_output_view()
 {
   test_output<char, View, int[3]>();
   test_output<wchar_t, View, int[3]>();
 }
 
-void
+constexpr26 void
 test_outputs()
 {
   using namespace __gnu_test;
   test_output_cont<std::vector<int>>();
-  test_output_cont<std::list<int>>();
+
+  if (!std::is_constant_evaluated())
+    test_output_cont<std::list<int>>();
+
   test_output_cont<std::array<int, 3>>();
 
   test_output_view<std::span<int>>();
@@ -185,7 +198,7 @@ test_outputs()
   test_output_view<test_forward_range<const int>>();
 }
 
-void
+constexpr26 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)
+constexpr26 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)
+constexpr26 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)
+constexpr26 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)
+constexpr26 bool
+strip_prefix(std::string_view& v, size_t n, char c)
 {
   size_t pos = v.find_first_not_of(c);
   if (pos == std::string_view::npos)
@@ -241,7 +258,8 @@ bool strip_prefix(std::string_view& v, size_t n, char c)
   return true;
 }
 
-void test_padding()
+constexpr26 void
+test_padding()
 {
   std::string res;
   std::string_view resv;
@@ -323,10 +341,22 @@ void test_padding()
   VERIFY( check_elems(resv, false) );
 }
 
-int main()
+constexpr26 bool
+test_all()
 {
   test_format_string();
   test_outputs();
   test_nested();
   test_padding();
+  
+  return true;
+}
+
+#if __cplusplus >= 202400L
+static_assert(test_all());
+#endif
+
+int main()
+{
+  test_all();
 }
diff --git a/libstdc++-v3/testsuite/std/format/runtime_format.cc 
b/libstdc++-v3/testsuite/std/format/runtime_format.cc
index f2bfa5b434d..cb1c7a09bc8 100644
--- a/libstdc++-v3/testsuite/std/format/runtime_format.cc
+++ b/libstdc++-v3/testsuite/std/format/runtime_format.cc
@@ -3,7 +3,7 @@
 #include <format>
 #include <testsuite_hooks.h>
 
-void
+constexpr void
 test_char()
 {
   std::string fmt = "{}";
@@ -11,7 +11,7 @@ test_char()
   VERIFY( s == "123" );
 }
 
-void
+constexpr void
 test_wchar()
 {
   std::wstring fmt = L"{:#o}";
@@ -19,7 +19,7 @@ test_wchar()
   VERIFY( s == L"0710" );
 }
 
-void
+constexpr void
 test_internal_api()
 {
   // Using _Runtime_format_string directly works even in C++20 mode.
@@ -40,9 +40,18 @@ 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;
+}
+
+static_assert(test_all());
+
+int main()
+{
+  test_all();
 }
diff --git a/libstdc++-v3/testsuite/std/format/string.cc 
b/libstdc++-v3/testsuite/std/format/string.cc
index ee987a15ec3..684e54ad080 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" }
+
+#if __cplusplus >= 202400L
+# define constexpr26 constexpr
+#else
+# define constexpr26
+#endif
 
 #include <format>
 #include <testsuite_hooks.h>
 
 template<typename... Args>
-bool
+constexpr26 bool
 is_format_string_for(const char* str, Args&&... args)
 {
   try {
@@ -16,7 +23,7 @@ is_format_string_for(const char* str, Args&&... args)
 }
 
 template<typename... Args>
-bool
+constexpr26 bool
 is_format_string_for(const wchar_t* str, Args&&... args)
 {
   try {
@@ -27,7 +34,7 @@ is_format_string_for(const wchar_t* str, Args&&... args)
   }
 }
 
-void
+constexpr26 void
 test_no_args()
 {
   VERIFY( is_format_string_for("") );
@@ -42,7 +49,7 @@ test_no_args()
   VERIFY( ! is_format_string_for("{{{{{") );
 }
 
-void
+constexpr26 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
+constexpr26 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
+constexpr26 void
 test_pr110862()
 {
   try {
@@ -178,7 +193,7 @@ test_pr110862()
   }
 }
 
-void
+constexpr26 void
 test_pr110974()
 {
   try {
@@ -197,11 +212,23 @@ test_pr110974()
   }
 }
 
-int main()
+constexpr26 bool
+test_all()
 {
   test_no_args();
   test_indexing();
   test_format_spec();
   test_pr110862();
   test_pr110974();
+
+  return true;
+}
+
+#if __cplusplus >= 202400L
+static_assert(test_all());
+#endif
+
+int main()
+{
+  test_all();
 }
diff --git a/libstdc++-v3/testsuite/std/format/tuple.cc 
b/libstdc++-v3/testsuite/std/format/tuple.cc
index eace82730f0..1bb1635d62b 100644
--- a/libstdc++-v3/testsuite/std/format/tuple.cc
+++ b/libstdc++-v3/testsuite/std/format/tuple.cc
@@ -2,6 +2,12 @@
 // { dg-options "-fexec-charset=UTF-8" }
 // { dg-timeout-factor 2 }
 
+#if __cplusplus >= 202400L
+# define constexpr26 constexpr
+#else
+# define constexpr26
+#endif
+
 #include <format>
 #include <string>
 #include <testsuite_hooks.h>
@@ -15,7 +21,7 @@ static_assert( !std::formattable<std::pair<int, 
NotFormattable>, char> );
 static_assert( !std::formattable<std::tuple<int, NotFormattable, int>, 
wchar_t> );
 
 template<typename... Args>
-bool
+constexpr26 bool
 is_format_string_for(const char* str, Args&&... args)
 {
   try {
@@ -27,7 +33,7 @@ is_format_string_for(const char* str, Args&&... args)
 }
 
 template<typename... Args>
-bool
+constexpr26 bool
 is_format_string_for(const wchar_t* str, Args&&... args)
 {
   try {
@@ -41,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
+constexpr26 void
 test_format_string()
 {
   // invalid format stringss
@@ -123,7 +129,8 @@ void test_multi()
 }
 
 template<typename CharT, typename Tuple>
-void test_empty()
+constexpr26 void
+test_empty()
 {
   std::basic_string<CharT> res;
 
@@ -142,7 +149,8 @@ void test_empty()
 }
 
 template<typename CharT, typename Pair>
-void test_pair()
+constexpr26 void
+test_pair()
 {
   using Ft = std::remove_cvref_t<std::tuple_element_t<0, Pair>>;
   using St = std::remove_cvref_t<std::tuple_element_t<1, Pair>>;
@@ -167,7 +175,8 @@ void test_pair()
 }
 
 template<typename CharT, template<typename, typename> class PairT>
-void test_pair_e()
+constexpr26 void
+test_pair_e()
 {
   test_pair<CharT, PairT<int, std::basic_string<CharT>>>();
   test_pair<CharT, PairT<int, const CharT*>>();
@@ -196,7 +205,7 @@ struct std::formatter<MyPair<Pair>, CharT>
   { return _formatter.parse(pc);  }
 
   template<typename Out>
-  typename std::basic_format_context<Out, CharT>::iterator
+  constexpr26 typename std::basic_format_context<Out, CharT>::iterator
   format(const MyPair<Pair>& mp,
         std::basic_format_context<Out, CharT>& fc) const
   { return _formatter.format(mp, fc); }
@@ -206,7 +215,8 @@ private:
 };
 
 template<typename CharT, template<typename, typename> class PairT>
-void test_custom()
+constexpr26 void
+test_custom()
 {
   std::basic_string<CharT> res;
   MyPair<PairT<int, const CharT*>> c1(1, WIDEN("abc"));
@@ -228,9 +238,12 @@ void test_custom()
 }
 
 template<typename CharT>
-void test_outputs()
+constexpr26 void
+test_outputs()
 {
-  test_multi<CharT>();
+  if (!std::is_constant_evaluated())
+    test_multi<CharT>();
+
   test_empty<CharT, std::tuple<>>();
   test_pair_e<CharT, std::pair>();
   test_pair_e<CharT, std::tuple>();
@@ -238,7 +251,8 @@ void test_outputs()
   test_custom<CharT, std::tuple>();
 }
 
-void test_nested()
+constexpr26 void
+test_nested()
 {
   std::string res;
   std::tuple<std::tuple<>, std::pair<int, std::string>> tt{{}, {1, "abc"}};
@@ -251,7 +265,8 @@ void test_nested()
   VERIFY( res == R"((): (1, "abc"))" );
 }
 
-bool strip_quote(std::string_view& v)
+constexpr26 bool
+strip_quote(std::string_view& v)
 {
   if (!v.starts_with('"'))
     return false;
@@ -259,7 +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)
+constexpr26 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)
+constexpr26 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)
+constexpr26 bool
+strip_prefix(std::string_view& v, size_t n, char c)
 {
   size_t pos = v.find_first_not_of(c);
   if (pos == std::string_view::npos)
@@ -291,7 +309,8 @@ bool strip_prefix(std::string_view& v, size_t n, char c)
   return true;
 }
 
-void test_padding()
+constexpr26 void
+test_padding()
 {
   std::string res;
   std::string_view resv;
@@ -351,13 +370,14 @@ struct std::formatter<Custom, CharT>
   { return pc.begin();  }
 
   template<typename Out>
-  typename std::basic_format_context<Out, CharT>::iterator
+  constexpr26 typename std::basic_format_context<Out, CharT>::iterator
   format(Custom, const std::basic_format_context<Out, CharT>& fc) const
   { return fc.out(); }
 };
 
 template<template<typename...> typename Tuple>
-void test_nonblocking()
+constexpr26 void
+test_nonblocking()
 {
   static_assert(std::enable_nonlocking_formatter_optimization<
                  Tuple<int, float>>);
@@ -374,7 +394,8 @@ void test_nonblocking()
                  Tuple<Custom&, float&>>);
 }
 
-int main()
+constexpr26 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;
+}
+
+#if __cplusplus >= 202400L
+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

Reply via email to