diff --git a/libcxx/include/__format/formatter_bool.h b/libcxx/include/__format/formatter_bool.h
--- a/libcxx/include/__format/formatter_bool.h
+++ b/libcxx/include/__format/formatter_bool.h
@@ -13,15 +13,18 @@
 #include <__algorithm/copy.h>
 #include <__availability>
 #include <__config>
+#include <__debug>
 #include <__format/format_error.h>
 #include <__format/format_fwd.h>
+#include <__format/format_parse_context.h>
 #include <__format/formatter.h>
 #include <__format/formatter_integral.h>
 #include <__format/parser_std_format_spec.h>
+#include <__utility/unreachable.h>
 #include <string_view>
 
 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
-#include <locale>
+#  include <locale>
 #endif
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -32,101 +35,39 @@
 
 #if _LIBCPP_STD_VER > 17
 
-namespace __format_spec {
-
-template <class _CharT>
-class _LIBCPP_TEMPLATE_VIS __parser_bool : public __parser_integral<_CharT> {
+template <__formatter::__char_type _CharT>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<bool, _CharT> {
 public:
-  _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx)
-      -> decltype(__parse_ctx.begin()) {
-    auto __it = __parser_integral<_CharT>::__parse(__parse_ctx);
-
-    switch (this->__type) {
-    case _Flags::_Type::__default:
-      this->__type = _Flags::_Type::__string;
-      [[fallthrough]];
-    case _Flags::_Type::__string:
-      this->__handle_bool();
-      break;
+  _LIBCPP_HIDE_FROM_ABI constexpr auto
+  parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) {
+    auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_integral);
+    __format_spec::__process_parsed_bool(__parser_);
+    return __result;
+  }
 
-    case _Flags::_Type::__binary_lower_case:
-    case _Flags::_Type::__binary_upper_case:
-    case _Flags::_Type::__octal:
-    case _Flags::_Type::__decimal:
-    case _Flags::_Type::__hexadecimal_lower_case:
-    case _Flags::_Type::__hexadecimal_upper_case:
-      this->__handle_integer();
-      break;
+  _LIBCPP_HIDE_FROM_ABI auto format(bool __value, auto& __ctx) const -> decltype(__ctx.out()) {
+    switch (__parser_.__type_) {
+    case __format_spec::__type::__string:
+      return __formatter::__format_bool(__value, __ctx, __parser_.__get_parsed_std_specifications(__ctx));
+
+    case __format_spec::__type::__binary_lower_case:
+    case __format_spec::__type::__binary_upper_case:
+    case __format_spec::__type::__octal:
+    case __format_spec::__type::__decimal:
+    case __format_spec::__type::__hexadecimal_lower_case:
+    case __format_spec::__type::__hexadecimal_upper_case:
+      // Promotes bool to an integral type. This reduces the number of
+      // instantiations of __format_integer reducing code size.
+      return __formatter::__format_integer(
+          static_cast<unsigned>(__value), __ctx, __parser_.__get_parsed_std_specifications(__ctx));
 
     default:
-      __throw_format_error(
-          "The format-spec type has a type not supported for a bool argument");
+      _LIBCPP_ASSERT(false, "The parse function should have validated the type");
+      __libcpp_unreachable();
     }
-
-    return __it;
   }
-};
-
-template <class _CharT>
-struct _LIBCPP_TEMPLATE_VIS __bool_strings;
-
-template <>
-struct _LIBCPP_TEMPLATE_VIS __bool_strings<char> {
-  static constexpr string_view __true{"true"};
-  static constexpr string_view __false{"false"};
-};
-
-#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
-template <>
-struct _LIBCPP_TEMPLATE_VIS __bool_strings<wchar_t> {
-  static constexpr wstring_view __true{L"true"};
-  static constexpr wstring_view __false{L"false"};
-};
-#endif
-
-template <class _CharT>
-using __formatter_bool = __formatter_integral<__parser_bool<_CharT>>;
 
-} //namespace __format_spec
-
-// [format.formatter.spec]/2.3
-// For each charT, for each cv-unqualified arithmetic type ArithmeticT other
-// than char, wchar_t, char8_t, char16_t, or char32_t, a specialization
-
-template <__formatter::__char_type _CharT>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<bool, _CharT>
-    : public __format_spec::__formatter_bool<_CharT> {
-  using _Base = __format_spec::__formatter_bool<_CharT>;
-
-  _LIBCPP_HIDE_FROM_ABI auto format(bool __value, auto& __ctx)
-      -> decltype(__ctx.out()) {
-    if (this->__type != __format_spec::_Flags::_Type::__string)
-      return _Base::format(static_cast<unsigned char>(__value), __ctx);
-
-    if (this->__width_needs_substitution())
-      this->__substitute_width_arg_id(__ctx.arg(this->__width));
-
-#ifndef _LIBCPP_HAS_NO_LOCALIZATION
-    if (this->__locale_specific_form) {
-      const auto& __np = use_facet<numpunct<_CharT>>(__ctx.locale());
-      basic_string<_CharT> __str = __value ? __np.truename() : __np.falsename();
-      return __formatter::__write_unicode(
-          __ctx.out(), basic_string_view<_CharT>{__str}, this->__width, -1,
-          this->__fill, this->__alignment);
-    }
-#endif
-    basic_string_view<_CharT> __str =
-        __value ? __format_spec::__bool_strings<_CharT>::__true
-                : __format_spec::__bool_strings<_CharT>::__false;
-
-    // The output only uses ASCII so every character is one column.
-    unsigned __size = __str.size();
-    if (__size >= this->__width)
-      return _VSTD::copy(__str.begin(), __str.end(), __ctx.out());
-
-    return __formatter::__write(__ctx.out(), __str.begin(), __str.end(), __size,
-                                this->__width, this->__fill, this->__alignment);
-  }
+  __format_spec::__parser<_CharT> __parser_;
 };
 
 #endif //_LIBCPP_STD_VER > 17
diff --git a/libcxx/include/__format/formatter_char.h b/libcxx/include/__format/formatter_char.h
--- a/libcxx/include/__format/formatter_char.h
+++ b/libcxx/include/__format/formatter_char.h
@@ -11,12 +11,16 @@
 #define _LIBCPP___FORMAT_FORMATTER_CHAR_H
 
 #include <__availability>
+#include <__concepts/same_as.h>
 #include <__config>
-#include <__format/format_error.h>
 #include <__format/format_fwd.h>
+#include <__format/format_parse_context.h>
 #include <__format/formatter.h>
 #include <__format/formatter_integral.h>
+#include <__format/formatter_output.h>
 #include <__format/parser_std_format_spec.h>
+#include <__type_traits/conditional.h>
+#include <__type_traits/is_signed.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -26,69 +30,52 @@
 
 #if _LIBCPP_STD_VER > 17
 
-namespace __format_spec {
-
-template <class _CharT>
-class _LIBCPP_TEMPLATE_VIS __parser_char : public __parser_integral<_CharT> {
+template <__formatter::__char_type _CharT>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_char {
 public:
-  _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx)
-      -> decltype(__parse_ctx.begin()) {
-    auto __it = __parser_integral<_CharT>::__parse(__parse_ctx);
-
-    switch (this->__type) {
-    case _Flags::_Type::__default:
-      this->__type = _Flags::_Type::__char;
-      [[fallthrough]];
-    case _Flags::_Type::__char:
-      this->__handle_char();
-      break;
-
-    case _Flags::_Type::__binary_lower_case:
-    case _Flags::_Type::__binary_upper_case:
-    case _Flags::_Type::__octal:
-    case _Flags::_Type::__decimal:
-    case _Flags::_Type::__hexadecimal_lower_case:
-    case _Flags::_Type::__hexadecimal_upper_case:
-      this->__handle_integer();
-      break;
-
-    default:
-      __throw_format_error(
-          "The format-spec type has a type not supported for a char argument");
-    }
-
-    return __it;
+  _LIBCPP_HIDE_FROM_ABI constexpr auto
+  parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) {
+    auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_integral);
+    __format_spec::__process_parsed_char(__parser_);
+    return __result;
   }
-};
 
-template <class _CharT>
-using __formatter_char = __formatter_integral<__parser_char<_CharT>>;
+  _LIBCPP_HIDE_FROM_ABI auto format(_CharT __value, auto& __ctx) const -> decltype(__ctx.out()) {
+    if (__parser_.__type_ == __format_spec::__type::__char)
+      return __formatter::__format_char(__value, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx));
+
+    if constexpr (sizeof(_CharT) <= sizeof(int))
+      // Promotes _CharT to an integral type. This reduces the number of
+      // instantiations of __format_integer reducing code size.
+      return __formatter::__format_integer(
+          static_cast<conditional_t<is_signed_v<_CharT>, int, unsigned>>(__value),
+          __ctx,
+          __parser_.__get_parsed_std_specifications(__ctx));
+    else
+      return __formatter::__format_integer(__value, __ctx, __parser_.__get_parsed_std_specifications(__ctx));
+  }
 
-} // namespace __format_spec
+  _LIBCPP_HIDE_FROM_ABI auto format(char __value, auto& __ctx) const -> decltype(__ctx.out())
+    requires(same_as<_CharT, wchar_t>)
+  {
+    return format(static_cast<wchar_t>(__value), __ctx);
+  }
 
-// [format.formatter.spec]/2.1 The specializations
+  __format_spec::__parser<_CharT> __parser_;
+};
 
 template <>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<char, char>
-    : public __format_spec::__formatter_char<char> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<char, char> : public __formatter_char<char> {};
 
-#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+#  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 template <>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<char, wchar_t>
-    : public __format_spec::__formatter_char<wchar_t> {
-  using _Base = __format_spec::__formatter_char<wchar_t>;
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<char, wchar_t> : public __formatter_char<wchar_t> {};
 
-  _LIBCPP_HIDE_FROM_ABI auto format(char __value, auto& __ctx)
-      -> decltype(__ctx.out()) {
-    return _Base::format(static_cast<wchar_t>(__value), __ctx);
-  }
+template <>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<wchar_t, wchar_t> : public __formatter_char<wchar_t> {
 };
 
-template <>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
-    formatter<wchar_t, wchar_t>
-    : public __format_spec::__formatter_char<wchar_t> {};
-#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
+#  endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
 
 #endif //_LIBCPP_STD_VER > 17
 
diff --git a/libcxx/include/__format/formatter_floating_point.h b/libcxx/include/__format/formatter_floating_point.h
--- a/libcxx/include/__format/formatter_floating_point.h
+++ b/libcxx/include/__format/formatter_floating_point.h
@@ -447,7 +447,7 @@
     if (__digits <= __grouping[0])
       __grouping.clear();
     else
-      __grouping = __determine_grouping(__digits, __grouping);
+      __grouping = __formatter::__determine_grouping(__digits, __grouping);
   }
 
   size_t __size = __result.__last - __buffer.begin() + // Formatted string
diff --git a/libcxx/include/__format/formatter_integer.h b/libcxx/include/__format/formatter_integer.h
--- a/libcxx/include/__format/formatter_integer.h
+++ b/libcxx/include/__format/formatter_integer.h
@@ -11,147 +11,120 @@
 #define _LIBCPP___FORMAT_FORMATTER_INTEGER_H
 
 #include <__availability>
+#include <__concepts/arithmetic.h>
 #include <__config>
-#include <__format/format_error.h>
+#include <__format/format_error.h> // TODO FMT Remove after adding 128-bit support
 #include <__format/format_fwd.h>
+#include <__format/format_parse_context.h>
 #include <__format/formatter.h>
 #include <__format/formatter_integral.h>
+#include <__format/formatter_output.h>
 #include <__format/parser_std_format_spec.h>
-#include <limits>
+#include <limits> // TODO FMT Remove after adding 128-bit support
+#include <type_traits>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
 #endif
 
-_LIBCPP_PUSH_MACROS
+_LIBCPP_PUSH_MACROS // TODO FMT Remove after adding 128-bit support
 #include <__undef_macros>
 
-_LIBCPP_BEGIN_NAMESPACE_STD
+    _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER > 17
 
-namespace __format_spec {
+    template <__formatter::__char_type _CharT>
+    struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_integer {
 
-template <class _CharT>
-class _LIBCPP_TEMPLATE_VIS __parser_integer : public __parser_integral<_CharT> {
 public:
-  _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx)
-      -> decltype(__parse_ctx.begin()) {
-    auto __it = __parser_integral<_CharT>::__parse(__parse_ctx);
-
-    switch (this->__type) {
-    case _Flags::_Type::__default:
-      this->__type = _Flags::_Type::__decimal;
-      [[fallthrough]];
-
-    case _Flags::_Type::__binary_lower_case:
-    case _Flags::_Type::__binary_upper_case:
-    case _Flags::_Type::__octal:
-    case _Flags::_Type::__decimal:
-    case _Flags::_Type::__hexadecimal_lower_case:
-    case _Flags::_Type::__hexadecimal_upper_case:
-      this->__handle_integer();
-      break;
-
-    case _Flags::_Type::__char:
-      this->__handle_char();
-      break;
-
-    default:
-      __throw_format_error("The format-spec type has a type not supported for "
-                           "an integer argument");
-    }
-    return __it;
+  _LIBCPP_HIDE_FROM_ABI constexpr auto
+  parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) {
+    auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_integral);
+    __format_spec::__process_parsed_integer(__parser_);
+    return __result;
   }
-};
 
-template <class _CharT>
-using __formatter_integer = __formatter_integral<__parser_integer<_CharT>>;
+  template <integral _Tp>
+  _LIBCPP_HIDE_FROM_ABI auto format(_Tp __value, auto& __ctx) const -> decltype(__ctx.out()) {
+    __format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx);
+
+    if (__specs.__std_.__type_ == __format_spec::__type::__char)
+      return __formatter::__format_char(__value, __ctx.out(), __specs);
 
-} // namespace __format_spec
+    using _Type = __make_32_64_or_128_bit_t<_Tp>;
+    static_assert(!is_same<_Type, void>::value, "unsupported integral type used in __formatter_integer::__format");
+
+    // Reduce the number of instantiation of the integer formatter
+    return __formatter::__format_integer(static_cast<_Type>(__value), __ctx, __specs);
+  }
 
-// [format.formatter.spec]/2.3
-// For each charT, for each cv-unqualified arithmetic type ArithmeticT other
-// than char, wchar_t, char8_t, char16_t, or char32_t, a specialization
+  __format_spec::__parser<_CharT> __parser_;
+};
 
 // Signed integral types.
 template <__formatter::__char_type _CharT>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
-    formatter<signed char, _CharT>
-    : public __format_spec::__formatter_integer<_CharT> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<signed char, _CharT>
+    : public __formatter_integer<_CharT> {};
 template <__formatter::__char_type _CharT>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<short, _CharT>
-    : public __format_spec::__formatter_integer<_CharT> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<short, _CharT> : public __formatter_integer<_CharT> {
+};
 template <__formatter::__char_type _CharT>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<int, _CharT>
-    : public __format_spec::__formatter_integer<_CharT> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<int, _CharT> : public __formatter_integer<_CharT> {};
 template <__formatter::__char_type _CharT>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<long, _CharT>
-    : public __format_spec::__formatter_integer<_CharT> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<long, _CharT> : public __formatter_integer<_CharT> {};
 template <__formatter::__char_type _CharT>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
-    formatter<long long, _CharT>
-    : public __format_spec::__formatter_integer<_CharT> {};
-#ifndef _LIBCPP_HAS_NO_INT128
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<long long, _CharT>
+    : public __formatter_integer<_CharT> {};
+#  ifndef _LIBCPP_HAS_NO_INT128
 template <__formatter::__char_type _CharT>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
-    formatter<__int128_t, _CharT>
-    : public __format_spec::__formatter_integer<_CharT> {
-  using _Base = __format_spec::__formatter_integer<_CharT>;
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<__int128_t, _CharT>
+    : public __formatter_integer<_CharT> {
+  using _Base = __formatter_integer<_CharT>;
 
-  _LIBCPP_HIDE_FROM_ABI auto format(__int128_t __value, auto& __ctx)
-      -> decltype(__ctx.out()) {
+  _LIBCPP_HIDE_FROM_ABI auto format(__int128_t __value, auto& __ctx) const -> decltype(__ctx.out()) {
     // TODO FMT Implement full 128 bit support.
     using _To = long long;
-    if (__value < numeric_limits<_To>::min() ||
-        __value > numeric_limits<_To>::max())
-      __throw_format_error("128-bit value is outside of implemented range");
+    if (__value < numeric_limits<_To>::min() || __value > numeric_limits<_To>::max())
+      std::__throw_format_error("128-bit value is outside of implemented range");
 
     return _Base::format(static_cast<_To>(__value), __ctx);
   }
 };
-#endif
+#  endif
 
 // Unsigned integral types.
 template <__formatter::__char_type _CharT>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
-    formatter<unsigned char, _CharT>
-    : public __format_spec::__formatter_integer<_CharT> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<unsigned char, _CharT>
+    : public __formatter_integer<_CharT> {};
 template <__formatter::__char_type _CharT>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
-    formatter<unsigned short, _CharT>
-    : public __format_spec::__formatter_integer<_CharT> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<unsigned short, _CharT>
+    : public __formatter_integer<_CharT> {};
 template <__formatter::__char_type _CharT>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
-    formatter<unsigned, _CharT>
-    : public __format_spec::__formatter_integer<_CharT> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<unsigned, _CharT>
+    : public __formatter_integer<_CharT> {};
 template <__formatter::__char_type _CharT>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
-    formatter<unsigned long, _CharT>
-    : public __format_spec::__formatter_integer<_CharT> {};
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<unsigned long, _CharT>
+    : public __formatter_integer<_CharT> {};
 template <__formatter::__char_type _CharT>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
-    formatter<unsigned long long, _CharT>
-    : public __format_spec::__formatter_integer<_CharT> {};
-#ifndef _LIBCPP_HAS_NO_INT128
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<unsigned long long, _CharT>
+    : public __formatter_integer<_CharT> {};
+#  ifndef _LIBCPP_HAS_NO_INT128
 template <__formatter::__char_type _CharT>
-struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT
-    formatter<__uint128_t, _CharT>
-    : public __format_spec::__formatter_integer<_CharT> {
-  using _Base = __format_spec::__formatter_integer<_CharT>;
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<__uint128_t, _CharT>
+    : public __formatter_integer<_CharT> {
+  using _Base = __formatter_integer<_CharT>;
 
-  _LIBCPP_HIDE_FROM_ABI auto format(__uint128_t __value, auto& __ctx)
-      -> decltype(__ctx.out()) {
+  _LIBCPP_HIDE_FROM_ABI auto format(__uint128_t __value, auto& __ctx) const -> decltype(__ctx.out()) {
     // TODO FMT Implement full 128 bit support.
     using _To = unsigned long long;
-    if (__value < numeric_limits<_To>::min() ||
-        __value > numeric_limits<_To>::max())
-      __throw_format_error("128-bit value is outside of implemented range");
+    if (__value < numeric_limits<_To>::min() || __value > numeric_limits<_To>::max())
+      std::__throw_format_error("128-bit value is outside of implemented range");
 
     return _Base::format(static_cast<_To>(__value), __ctx);
   }
 };
-#endif
+#  endif
 
 #endif //_LIBCPP_STD_VER > 17
 
diff --git a/libcxx/include/__format/formatter_integral.h b/libcxx/include/__format/formatter_integral.h
--- a/libcxx/include/__format/formatter_integral.h
+++ b/libcxx/include/__format/formatter_integral.h
@@ -10,25 +10,20 @@
 #ifndef _LIBCPP___FORMAT_FORMATTER_INTEGRAL_H
 #define _LIBCPP___FORMAT_FORMATTER_INTEGRAL_H
 
-#include <__algorithm/copy.h>
-#include <__algorithm/copy_n.h>
-#include <__algorithm/fill_n.h>
-#include <__algorithm/transform.h>
-#include <__assert>
+#include <__concepts/arithmetic.h>
+#include <__concepts/same_as.h>
 #include <__config>
 #include <__format/format_error.h>
-#include <__format/format_fwd.h>
-#include <__format/formatter.h>
+#include <__format/formatter.h> // for __char_type TODO FMT Move the concept?
+#include <__format/formatter_output.h>
 #include <__format/parser_std_format_spec.h>
 #include <__utility/unreachable.h>
-#include <array>
 #include <charconv>
-#include <concepts>
 #include <limits>
 #include <string>
 
 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
-#include <locale>
+#  include <locale>
 #endif
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -42,91 +37,30 @@
 
 #if _LIBCPP_STD_VER > 17
 
-/**
- * Integral formatting classes.
- *
- * There are two types used here:
- * * C++-type, the type as used in C++.
- * * format-type, the output type specified in the std-format-spec.
- *
- * Design of the integral formatters consists of several layers.
- * * @ref __parser_integral The basic std-format-spec parser for all integral
- *   classes. This parser does the basic sanity checks. It also contains some
- *   helper functions that are nice to have available for all parsers.
- * * A C++-type specific parser. These parsers must derive from
- *   @ref __parser_integral. Their task is to validate whether the parsed
- *   std-format-spec is valid for the C++-type and selected format-type. After
- *   validation they need to make sure all members are properly set. For
- *   example, when the alignment hasn't changed it needs to set the proper
- *   default alignment for the format-type. The following parsers are available:
- *   - @ref __parser_integer
- *   - @ref __parser_char
- *   - @ref __parser_bool
- * * A general formatter for all integral types @ref __formatter_integral. This
- *   formatter can handle all formatting of integers and characters. The class
- *   derives from the proper formatter.
- *   Note the boolean string format-type isn't supported in this class.
- * * A typedef C++-type group combining the @ref __formatter_integral with a
- *   parser:
- *   * @ref __formatter_integer
- *   * @ref __formatter_char
- *   * @ref __formatter_bool
- * * Then every C++-type has its own formatter specializations. They inherit
- *   from the C++-type group typedef. Most specializations need nothing else.
- *   Others need some additional specializations in this class.
- */
-namespace __format_spec {
-
-/** Wrapper around @ref to_chars, returning the output pointer. */
-template <integral _Tp>
-_LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last,
-                                        _Tp __value, int __base) {
-  // TODO FMT Evaluate code overhead due to not calling the internal function
-  // directly. (Should be zero overhead.)
-  to_chars_result __r = _VSTD::to_chars(__first, __last, __value, __base);
-  _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small");
-  return __r.ptr;
-}
-
-/**
- * Helper to determine the buffer size to output a integer in Base @em x.
- *
- * There are several overloads for the supported bases. The function uses the
- * base as template argument so it can be used in a constant expression.
- */
-template <unsigned_integral _Tp, size_t _Base>
-_LIBCPP_HIDE_FROM_ABI constexpr size_t __buffer_size() noexcept
-    requires(_Base == 2) {
-  return numeric_limits<_Tp>::digits // The number of binary digits.
-         + 2                         // Reserve space for the '0[Bb]' prefix.
-         + 1;                        // Reserve space for the sign.
-}
+namespace __formatter {
 
-template <unsigned_integral _Tp, size_t _Base>
-_LIBCPP_HIDE_FROM_ABI constexpr size_t __buffer_size() noexcept
-    requires(_Base == 8) {
-  return numeric_limits<_Tp>::digits // The number of binary digits.
-             / 3                     // Adjust to octal.
-         + 1                         // Turn floor to ceil.
-         + 1                         // Reserve space for the '0' prefix.
-         + 1;                        // Reserve space for the sign.
-}
+//
+// Generic
+//
 
-template <unsigned_integral _Tp, size_t _Base>
-_LIBCPP_HIDE_FROM_ABI constexpr size_t __buffer_size() noexcept
-    requires(_Base == 10) {
-  return numeric_limits<_Tp>::digits10 // The floored value.
-         + 1                           // Turn floor to ceil.
-         + 1;                          // Reserve space for the sign.
-}
+_LIBCPP_HIDE_FROM_ABI inline char* __insert_sign(char* __buf, bool __negative, __format_spec::__sign __sign) {
+  if (__negative)
+    *__buf++ = '-';
+  else
+    switch (__sign) {
+    case __format_spec::__sign::__default:
+    case __format_spec::__sign::__minus:
+      // No sign added.
+      break;
+    case __format_spec::__sign::__plus:
+      *__buf++ = '+';
+      break;
+    case __format_spec::__sign::__space:
+      *__buf++ = ' ';
+      break;
+    }
 
-template <unsigned_integral _Tp, size_t _Base>
-_LIBCPP_HIDE_FROM_ABI constexpr size_t __buffer_size() noexcept
-    requires(_Base == 16) {
-  return numeric_limits<_Tp>::digits // The number of binary digits.
-             / 4                     // Adjust to hexadecimal.
-         + 2                         // Reserve space for the '0[Xx]' prefix.
-         + 1;                        // Reserve space for the sign.
+  return __buf;
 }
 
 /**
@@ -144,8 +78,7 @@
  * @note The grouping field of the locale is always a @c std::string,
  * regardless whether the @c std::numpunct's type is @c char or @c wchar_t.
  */
-_LIBCPP_HIDE_FROM_ABI inline string
-__determine_grouping(ptrdiff_t __size, const string& __grouping) {
+_LIBCPP_HIDE_FROM_ABI inline string __determine_grouping(ptrdiff_t __size, const string& __grouping) {
   _LIBCPP_ASSERT(!__grouping.empty() && __size > __grouping[0],
                  "The slow grouping formatting is used while there will be no "
                  "separators written");
@@ -175,278 +108,253 @@
   __libcpp_unreachable();
 }
 
-template <class _Parser>
-requires __formatter::__char_type<typename _Parser::char_type>
-class _LIBCPP_TEMPLATE_VIS __formatter_integral : public _Parser {
-public:
-  using _CharT = typename _Parser::char_type;
-
-  template <integral _Tp>
-  _LIBCPP_HIDE_FROM_ABI auto format(_Tp __value, auto& __ctx)
-      -> decltype(__ctx.out()) {
-    if (this->__width_needs_substitution())
-      this->__substitute_width_arg_id(__ctx.arg(this->__width));
-
-    if (this->__type == _Flags::_Type::__char)
-      return __format_as_char(__value, __ctx);
+//
+// Char
+//
 
-    if constexpr (unsigned_integral<_Tp>)
-      return __format_unsigned_integral(__value, false, __ctx);
-    else {
-      // Depending on the std-format-spec string the sign and the value
-      // might not be outputted together:
-      // - alternate form may insert a prefix string.
-      // - zero-padding may insert additional '0' characters.
-      // Therefore the value is processed as a positive unsigned value.
-      // The function @ref __insert_sign will a '-' when the value was negative.
-      auto __r = __to_unsigned_like(__value);
-      bool __negative = __value < 0;
-      if (__negative)
-        __r = __complement(__r);
-
-      return __format_unsigned_integral(__r, __negative, __ctx);
+template <__formatter::__char_type _CharT>
+_LIBCPP_HIDE_FROM_ABI auto __format_char(
+    integral auto __value,
+    output_iterator<const _CharT&> auto __out_it,
+    __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) {
+  using _Tp = decltype(__value);
+  if constexpr (!same_as<_CharT, _Tp>) {
+    // cmp_less and cmp_greater can't be used for character types.
+    if constexpr (signed_integral<_CharT> == signed_integral<_Tp>) {
+      if (__value < numeric_limits<_CharT>::min() || __value > numeric_limits<_CharT>::max())
+        std::__throw_format_error("Integral value outside the range of the char type");
+    } else if constexpr (signed_integral<_CharT>) {
+      // _CharT is signed _Tp is unsigned
+      if (__value > static_cast<make_unsigned_t<_CharT>>(numeric_limits<_CharT>::max()))
+        std::__throw_format_error("Integral value outside the range of the char type");
+    } else {
+      // _CharT is unsigned _Tp is signed
+      if (__value < 0 || static_cast<make_unsigned_t<_Tp>>(__value) > numeric_limits<_CharT>::max())
+        std::__throw_format_error("Integral value outside the range of the char type");
     }
   }
 
-private:
-  /** Generic formatting for format-type c. */
-  _LIBCPP_HIDE_FROM_ABI auto __format_as_char(integral auto __value,
-                                              auto& __ctx)
-      -> decltype(__ctx.out()) {
-    if (this->__alignment == _Flags::_Alignment::__default)
-      this->__alignment = _Flags::_Alignment::__right;
-
-    using _Tp = decltype(__value);
-    if constexpr (!same_as<_CharT, _Tp>) {
-      // cmp_less and cmp_greater can't be used for character types.
-      if constexpr (signed_integral<_CharT> == signed_integral<_Tp>) {
-        if (__value < numeric_limits<_CharT>::min() ||
-            __value > numeric_limits<_CharT>::max())
-          __throw_format_error(
-              "Integral value outside the range of the char type");
-      } else if constexpr (signed_integral<_CharT>) {
-        // _CharT is signed _Tp is unsigned
-        if (__value >
-            static_cast<make_unsigned_t<_CharT>>(numeric_limits<_CharT>::max()))
-          __throw_format_error(
-              "Integral value outside the range of the char type");
-      } else {
-        // _CharT is unsigned _Tp is signed
-        if (__value < 0 || static_cast<make_unsigned_t<_Tp>>(__value) >
-                               numeric_limits<_CharT>::max())
-          __throw_format_error(
-              "Integral value outside the range of the char type");
-      }
-    }
+  const auto __c = static_cast<_CharT>(__value);
+  return __formatter::__write(_VSTD::addressof(__c), _VSTD::addressof(__c) + 1, _VSTD::move(__out_it), __specs);
+}
 
-    const auto __c = static_cast<_CharT>(__value);
-    return __write(_VSTD::addressof(__c), _VSTD::addressof(__c) + 1,
-                   __ctx.out());
-  }
+//
+// Integer
+//
 
-  /**
-   * Generic formatting for format-type bBdoxX.
-   *
-   * This small wrapper allocates a buffer with the required size. Then calls
-   * the real formatter with the buffer and the prefix for the base.
-   */
-  _LIBCPP_HIDE_FROM_ABI auto
-  __format_unsigned_integral(unsigned_integral auto __value, bool __negative,
-                             auto& __ctx) -> decltype(__ctx.out()) {
-    switch (this->__type) {
-    case _Flags::_Type::__binary_lower_case: {
-      array<char, __buffer_size<decltype(__value), 2>()> __array;
-      return __format_unsigned_integral(__array.begin(), __array.end(), __value,
-                                        __negative, 2, __ctx, "0b");
-    }
-    case _Flags::_Type::__binary_upper_case: {
-      array<char, __buffer_size<decltype(__value), 2>()> __array;
-      return __format_unsigned_integral(__array.begin(), __array.end(), __value,
-                                        __negative, 2, __ctx, "0B");
-    }
-    case _Flags::_Type::__octal: {
-      // Octal is special; if __value == 0 there's no prefix.
-      array<char, __buffer_size<decltype(__value), 8>()> __array;
-      return __format_unsigned_integral(__array.begin(), __array.end(), __value,
-                                        __negative, 8, __ctx,
-                                        __value != 0 ? "0" : nullptr);
-    }
-    case _Flags::_Type::__decimal: {
-      array<char, __buffer_size<decltype(__value), 10>()> __array;
-      return __format_unsigned_integral(__array.begin(), __array.end(), __value,
-                                        __negative, 10, __ctx, nullptr);
-    }
-    case _Flags::_Type::__hexadecimal_lower_case: {
-      array<char, __buffer_size<decltype(__value), 16>()> __array;
-      return __format_unsigned_integral(__array.begin(), __array.end(), __value,
-                                        __negative, 16, __ctx, "0x");
-    }
-    case _Flags::_Type::__hexadecimal_upper_case: {
-      array<char, __buffer_size<decltype(__value), 16>()> __array;
-      return __format_unsigned_integral(__array.begin(), __array.end(), __value,
-                                        __negative, 16, __ctx, "0X");
-    }
-    default:
-      _LIBCPP_ASSERT(false, "The parser should have validated the type");
-      __libcpp_unreachable();
-    }
-  }
+/** Wrapper around @ref to_chars, returning the output pointer. */
+template <integral _Tp>
+_LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value, int __base) {
+  // TODO FMT Evaluate code overhead due to not calling the internal function
+  // directly. (Should be zero overhead.)
+  to_chars_result __r = _VSTD::to_chars(__first, __last, __value, __base);
+  _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small");
+  return __r.ptr;
+}
 
-  template <class _Tp>
-  requires(same_as<char, _Tp> || same_as<wchar_t, _Tp>) _LIBCPP_HIDE_FROM_ABI
-      auto __write(const _Tp* __first, const _Tp* __last, auto __out_it)
-          -> decltype(__out_it) {
+/**
+ * Helper to determine the buffer size to output a integer in Base @em x.
+ *
+ * There are several overloads for the supported bases. The function uses the
+ * base as template argument so it can be used in a constant expression.
+ */
+template <unsigned_integral _Tp, size_t _Base>
+consteval size_t __buffer_size() noexcept
+  requires(_Base == 2)
+{
+  return numeric_limits<_Tp>::digits // The number of binary digits.
+       + 2                           // Reserve space for the '0[Bb]' prefix.
+       + 1;                          // Reserve space for the sign.
+}
 
-    unsigned __size = __last - __first;
-    if (this->__type != _Flags::_Type::__hexadecimal_upper_case) [[likely]] {
-      if (__size >= this->__width)
-        return _VSTD::copy(__first, __last, _VSTD::move(__out_it));
+template <unsigned_integral _Tp, size_t _Base>
+consteval size_t __buffer_size() noexcept
+  requires(_Base == 8)
+{
+  return numeric_limits<_Tp>::digits // The number of binary digits.
+           / 3                       // Adjust to octal.
+       + 1                           // Turn floor to ceil.
+       + 1                           // Reserve space for the '0' prefix.
+       + 1;                          // Reserve space for the sign.
+}
 
-      return __formatter::__write(_VSTD::move(__out_it), __first, __last,
-                                  __size, this->__width, this->__fill,
-                                  this->__alignment);
-    }
+template <unsigned_integral _Tp, size_t _Base>
+consteval size_t __buffer_size() noexcept
+  requires(_Base == 10)
+{
+  return numeric_limits<_Tp>::digits10 // The floored value.
+       + 1                             // Turn floor to ceil.
+       + 1;                            // Reserve space for the sign.
+}
+
+template <unsigned_integral _Tp, size_t _Base>
+consteval size_t __buffer_size() noexcept
+  requires(_Base == 16)
+{
+  return numeric_limits<_Tp>::digits // The number of binary digits.
+           / 4                       // Adjust to hexadecimal.
+       + 2                           // Reserve space for the '0[Xx]' prefix.
+       + 1;                          // Reserve space for the sign.
+}
 
-    // this->__type == _Flags::_Type::__hexadecimal_upper_case
-    // This means all characters in the range [a-f] need to be changed to their
-    // uppercase representation. The transformation is done as transformation
-    // in the output routine instead of before. This avoids another pass over
-    // the data.
-    // TODO FMT See whether it's possible to do this transformation during the
-    // conversion. (This probably requires changing std::to_chars' alphabet.)
-    if (__size >= this->__width)
-      return _VSTD::transform(__first, __last, _VSTD::move(__out_it),
-                              __hex_to_upper);
-
-    return __formatter::__write(_VSTD::move(__out_it), __first, __last, __size,
-                                __hex_to_upper, this->__width, this->__fill,
-                                this->__alignment);
+template <unsigned_integral _Tp, class _CharT>
+_LIBCPP_HIDE_FROM_ABI auto __format_integer(
+    _Tp __value,
+    auto& __ctx,
+    __format_spec::__parsed_specifications<_CharT> __specs,
+    bool __negative,
+    char* __begin,
+    char* __end,
+    const char* __prefix,
+    int __base) -> decltype(__ctx.out()) {
+  _LIBCPP_ASSERT(
+      __specs.__alignment_ != __format_spec::__alignment::__default,
+      "the caller should adjust the default to the value required by the type");
+
+  char* __first = __formatter::__insert_sign(__begin, __negative, __specs.__std_.__sign_);
+  if (__specs.__std_.__alternate_form_ && __prefix)
+    while (*__prefix)
+      *__first++ = *__prefix++;
+
+  char* __last = __formatter::__to_buffer(__first, __end, __value, __base);
+
+#  ifndef _LIBCPP_HAS_NO_LOCALIZATION
+  if (__specs.__std_.__locale_specific_form_) {
+    const auto& __np  = use_facet<numpunct<_CharT>>(__ctx.locale());
+    string __grouping = __np.grouping();
+    ptrdiff_t __size  = __last - __first;
+    // Writing the grouped form has more overhead than the normal output
+    // routines. If there will be no separators written the locale-specific
+    // form is identical to the normal routine. Test whether to grouped form
+    // is required.
+    if (!__grouping.empty() && __size > __grouping[0])
+      return __formatter::__write_using_decimal_separators(
+          __ctx.out(),
+          __begin,
+          __first,
+          __last,
+          __formatter::__determine_grouping(__size, __grouping),
+          __np.thousands_sep(),
+          __specs);
+  }
+#  endif
+  auto __out_it = __ctx.out();
+  if (__specs.__alignment_ != __format_spec::__alignment::__zero_padding)
+    __first = __begin;
+  else {
+    // __buf contains [sign][prefix]data
+    //                              ^ location of __first
+    // The zero padding is done like:
+    // - Write [sign][prefix]
+    // - Write data right aligned with '0' as fill character.
+    __out_it             = _VSTD::copy(__begin, __first, _VSTD::move(__out_it));
+    __specs.__alignment_ = __format_spec::__alignment::__right;
+    __specs.__fill_      = _CharT('0');
+    int32_t __size       = __first - __begin;
+
+    __specs.__width_ -= _VSTD::min(__size, __specs.__width_);
   }
 
-  _LIBCPP_HIDE_FROM_ABI auto
-  __format_unsigned_integral(char* __begin, char* __end,
-                             unsigned_integral auto __value, bool __negative,
-                             int __base, auto& __ctx, const char* __prefix)
-      -> decltype(__ctx.out()) {
-    char* __first = __insert_sign(__begin, __negative, this->__sign);
-    if (this->__alternate_form && __prefix)
-      while (*__prefix)
-        *__first++ = *__prefix++;
-
-    char* __last = __to_buffer(__first, __end, __value, __base);
-#ifndef _LIBCPP_HAS_NO_LOCALIZATION
-    if (this->__locale_specific_form) {
-      const auto& __np = use_facet<numpunct<_CharT>>(__ctx.locale());
-      string __grouping = __np.grouping();
-      ptrdiff_t __size = __last - __first;
-      // Writing the grouped form has more overhead than the normal output
-      // routines. If there will be no separators written the locale-specific
-      // form is identical to the normal routine. Test whether to grouped form
-      // is required.
-      if (!__grouping.empty() && __size > __grouping[0])
-        return __format_grouping(__ctx.out(), __begin, __first, __last,
-                                 __determine_grouping(__size, __grouping),
-                                 __np.thousands_sep());
-    }
-#endif
-    auto __out_it = __ctx.out();
-    if (this->__alignment != _Flags::_Alignment::__default)
-      __first = __begin;
-    else {
-      // __buf contains [sign][prefix]data
-      //                              ^ location of __first
-      // The zero padding is done like:
-      // - Write [sign][prefix]
-      // - Write data right aligned with '0' as fill character.
-      __out_it = _VSTD::copy(__begin, __first, _VSTD::move(__out_it));
-      this->__alignment = _Flags::_Alignment::__right;
-      this->__fill = _CharT('0');
-      uint32_t __size = __first - __begin;
-      this->__width -= _VSTD::min(__size, this->__width);
-    }
+  if (__specs.__std_.__type_ != __format_spec::__type::__hexadecimal_upper_case) [[likely]]
+    return __formatter::__write(__first, __last, __ctx.out(), __specs);
+
+  return __formatter::__write_transformed(__first, __last, __ctx.out(), __specs, __formatter::__hex_to_upper);
+}
 
-    return __write(__first, __last, _VSTD::move(__out_it));
+template <unsigned_integral _Tp, class _CharT>
+_LIBCPP_HIDE_FROM_ABI auto __format_integer(
+    _Tp __value, auto& __ctx, __format_spec::__parsed_specifications<_CharT> __specs, bool __negative = false)
+    -> decltype(__ctx.out()) {
+  switch (__specs.__std_.__type_) {
+  case __format_spec::__type::__binary_lower_case: {
+    array<char, __formatter::__buffer_size<decltype(__value), 2>()> __array;
+    return __formatter::__format_integer(__value, __ctx, __specs, __negative, __array.begin(), __array.end(), "0b", 2);
   }
+  case __format_spec::__type::__binary_upper_case: {
+    array<char, __formatter::__buffer_size<decltype(__value), 2>()> __array;
+    return __formatter::__format_integer(__value, __ctx, __specs, __negative, __array.begin(), __array.end(), "0B", 2);
+  }
+  case __format_spec::__type::__octal: {
+    // Octal is special; if __value == 0 there's no prefix.
+    array<char, __formatter::__buffer_size<decltype(__value), 8>()> __array;
+    return __formatter::__format_integer(
+        __value, __ctx, __specs, __negative, __array.begin(), __array.end(), __value != 0 ? "0" : nullptr, 8);
+  }
+  case __format_spec::__type::__decimal: {
+    array<char, __formatter::__buffer_size<decltype(__value), 10>()> __array;
+    return __formatter::__format_integer(
+        __value, __ctx, __specs, __negative, __array.begin(), __array.end(), nullptr, 10);
+  }
+  case __format_spec::__type::__hexadecimal_lower_case: {
+    array<char, __formatter::__buffer_size<decltype(__value), 16>()> __array;
+    return __formatter::__format_integer(__value, __ctx, __specs, __negative, __array.begin(), __array.end(), "0x", 16);
+  }
+  case __format_spec::__type::__hexadecimal_upper_case: {
+    array<char, __formatter::__buffer_size<decltype(__value), 16>()> __array;
+    return __formatter::__format_integer(__value, __ctx, __specs, __negative, __array.begin(), __array.end(), "0X", 16);
+  }
+  default:
+    _LIBCPP_ASSERT(false, "The parse function should have validated the type");
+    __libcpp_unreachable();
+  }
+}
 
-#ifndef _LIBCPP_HAS_NO_LOCALIZATION
-  /** Format's the locale-specific form's groupings. */
-  template <class _OutIt, class _CharT>
-  _LIBCPP_HIDE_FROM_ABI _OutIt
-  __format_grouping(_OutIt __out_it, const char* __begin, const char* __first,
-                    const char* __last, string&& __grouping, _CharT __sep) {
-
-    // TODO FMT This function duplicates some functionality of the normal
-    // output routines. Evaluate whether these parts can be efficiently
-    // combined with the existing routines.
-
-    unsigned __size = (__first - __begin) +    // [sign][prefix]
-                      (__last - __first) +     // data
-                      (__grouping.size() - 1); // number of separator characters
-
-    __formatter::__padding_size_result __padding = {0, 0};
-    if (this->__alignment == _Flags::_Alignment::__default) {
-      // Write [sign][prefix].
-      __out_it = _VSTD::copy(__begin, __first, _VSTD::move(__out_it));
-
-      if (this->__width > __size) {
-        // Write zero padding.
-        __padding.__before = this->__width - __size;
-        __out_it = _VSTD::fill_n(_VSTD::move(__out_it), this->__width - __size,
-                                 _CharT('0'));
-      }
-    } else {
-      if (this->__width > __size) {
-        // Determine padding and write padding.
-        __padding = __formatter::__padding_size(__size, this->__width,
-                                                this->__alignment);
-
-        __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before,
-                                 this->__fill);
-      }
-      // Write [sign][prefix].
-      __out_it = _VSTD::copy(__begin, __first, _VSTD::move(__out_it));
-    }
+template <signed_integral _Tp, class _CharT>
+_LIBCPP_HIDE_FROM_ABI auto
+__format_integer(_Tp __value, auto& __ctx, __format_spec::__parsed_specifications<_CharT> __specs)
+    -> decltype(__ctx.out()) {
+  // Depending on the std-format-spec string the sign and the value
+  // might not be outputted together:
+  // - alternate form may insert a prefix string.
+  // - zero-padding may insert additional '0' characters.
+  // Therefore the value is processed as a positive unsigned value.
+  // The function @ref __insert_sign will a '-' when the value was negative.
+  auto __r        = std::__to_unsigned_like(__value);
+  bool __negative = __value < 0;
+  if (__negative)
+    __r = __complement(__r);
+
+  return __formatter::__format_integer(__r, __ctx, __specs, __negative);
+}
 
-    auto __r = __grouping.rbegin();
-    auto __e = __grouping.rend() - 1;
-    _LIBCPP_ASSERT(__r != __e, "The slow grouping formatting is used while "
-                               "there will be no separators written.");
-    // The output is divided in small groups of numbers to write:
-    // - A group before the first separator.
-    // - A separator and a group, repeated for the number of separators.
-    // - A group after the last separator.
-    // This loop achieves that process by testing the termination condition
-    // midway in the loop.
-    //
-    // TODO FMT This loop evaluates the loop invariant `this->__type !=
-    // _Flags::_Type::__hexadecimal_upper_case` for every iteration. (This test
-    // happens in the __write call.) Benchmark whether making two loops and
-    // hoisting the invariant is worth the effort.
-    while (true) {
-      if (this->__type == _Flags::_Type::__hexadecimal_upper_case) {
-        __last = __first + *__r;
-        __out_it = _VSTD::transform(__first, __last, _VSTD::move(__out_it),
-                                    __hex_to_upper);
-        __first = __last;
-      } else {
-        __out_it = _VSTD::copy_n(__first, *__r, _VSTD::move(__out_it));
-        __first += *__r;
-      }
-
-      if (__r == __e)
-        break;
-
-      ++__r;
-      *__out_it++ = __sep;
-    }
+//
+// Formatter arithmetic (bool)
+//
 
-    return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after,
-                         this->__fill);
-  }
-#endif // _LIBCPP_HAS_NO_LOCALIZATION
+template <class _CharT>
+struct _LIBCPP_TEMPLATE_VIS __bool_strings;
+
+template <>
+struct _LIBCPP_TEMPLATE_VIS __bool_strings<char> {
+  static constexpr string_view __true{"true"};
+  static constexpr string_view __false{"false"};
+};
+
+#  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+template <>
+struct _LIBCPP_TEMPLATE_VIS __bool_strings<wchar_t> {
+  static constexpr wstring_view __true{L"true"};
+  static constexpr wstring_view __false{L"false"};
 };
+#  endif
+
+template <class _CharT>
+_LIBCPP_HIDE_FROM_ABI auto
+__format_bool(bool __value, auto& __ctx, __format_spec::__parsed_specifications<_CharT> __specs)
+    -> decltype(__ctx.out()) {
+#  ifndef _LIBCPP_HAS_NO_LOCALIZATION
+  if (__specs.__std_.__locale_specific_form_) {
+    const auto& __np           = use_facet<numpunct<_CharT>>(__ctx.locale());
+    basic_string<_CharT> __str = __value ? __np.truename() : __np.falsename();
+    return __formatter::__write_unicode_no_precision(basic_string_view<_CharT>{__str}, __ctx.out(), __specs);
+  }
+#  endif
+  basic_string_view<_CharT> __str =
+      __value ? __formatter::__bool_strings<_CharT>::__true : __formatter::__bool_strings<_CharT>::__false;
+  return __formatter::__write(__str.begin(), __str.end(), __ctx.out(), __specs);
+}
 
-} // namespace __format_spec
+} // namespace __formatter
 
 #endif //_LIBCPP_STD_VER > 17
 
diff --git a/libcxx/include/__format/formatter_pointer.h b/libcxx/include/__format/formatter_pointer.h
--- a/libcxx/include/__format/formatter_pointer.h
+++ b/libcxx/include/__format/formatter_pointer.h
@@ -49,7 +49,7 @@
     char __buffer[2 + 2 * sizeof(uintptr_t)];
     __buffer[0] = '0';
     __buffer[1] = 'x';
-    char* __last = __to_buffer(__buffer + 2, _VSTD::end(__buffer), reinterpret_cast<uintptr_t>(__ptr), 16);
+    char* __last = __formatter::__to_buffer(__buffer + 2, _VSTD::end(__buffer), reinterpret_cast<uintptr_t>(__ptr), 16);
 
     unsigned __size = __last - __buffer;
     if (__size >= this->__width)
diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h
--- a/libcxx/include/__format/parser_std_format_spec.h
+++ b/libcxx/include/__format/parser_std_format_spec.h
@@ -1400,6 +1400,12 @@
 
 // By not placing this constant in the formatter class it's not duplicated for
 // char and wchar_t.
+inline constexpr __fields __fields_integral{
+    .__sign_                 = true,
+    .__alternate_form_       = true,
+    .__zero_padding_         = true,
+    .__locale_specific_form_ = true,
+    .__type_                 = true};
 inline constexpr __fields __fields_string{.__precision_ = true, .__type_ = true};
 
 enum class _LIBCPP_ENUM_VIS __alignment : uint8_t {
@@ -1840,8 +1846,105 @@
     break;
 
   default:
-    __throw_format_error("The format-spec type has a type not supported for "
-                         "a string argument");
+    std::__throw_format_error("The format-spec type has a type not supported for a string argument");
+  }
+}
+
+template <class _CharT>
+_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_bool_string(__parser<_CharT>& __parser) {
+  if (__parser.__sign_ != __sign::__default)
+    std::__throw_format_error("A sign field isn't allowed in this format-spec");
+
+  if (__parser.__alternate_form_)
+    std::__throw_format_error("An alternate form field isn't allowed in this format-spec");
+
+  if (__parser.__alignment_ == __alignment::__zero_padding)
+    std::__throw_format_error("A zero-padding field isn't allowed in this format-spec");
+
+  if (__parser.__alignment_ == __alignment::__default)
+    __parser.__alignment_ = __alignment::__left;
+}
+
+template <class _CharT>
+_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_char(__parser<_CharT>& __parser) {
+  __format_spec::__process_display_type_bool_string(__parser);
+}
+
+template <class _CharT>
+_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_integer(__parser<_CharT>& __parser) {
+  if (__parser.__alignment_ == __alignment::__default)
+    __parser.__alignment_ = __alignment::__right;
+}
+
+template <class _CharT>
+_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_bool(__parser<_CharT>& __parser) {
+  switch (__parser.__type_) {
+  case __format_spec::__type::__default:
+    __parser.__type_ = __format_spec::__type::__string;
+    [[fallthrough]];
+  case __format_spec::__type::__string:
+    __format_spec::__process_display_type_bool_string(__parser);
+    break;
+
+  case __format_spec::__type::__binary_lower_case:
+  case __format_spec::__type::__binary_upper_case:
+  case __format_spec::__type::__octal:
+  case __format_spec::__type::__decimal:
+  case __format_spec::__type::__hexadecimal_lower_case:
+  case __format_spec::__type::__hexadecimal_upper_case:
+    __process_display_type_integer(__parser);
+    break;
+
+  default:
+    std::__throw_format_error("The format-spec type has a type not supported for a bool argument");
+  }
+}
+
+template <class _CharT>
+_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_char(__parser<_CharT>& __parser) {
+  switch (__parser.__type_) {
+  case __format_spec::__type::__default:
+    __parser.__type_ = __format_spec::__type::__char;
+    [[fallthrough]];
+  case __format_spec::__type::__char:
+    __format_spec::__process_display_type_char(__parser);
+    break;
+
+  case __format_spec::__type::__binary_lower_case:
+  case __format_spec::__type::__binary_upper_case:
+  case __format_spec::__type::__octal:
+  case __format_spec::__type::__decimal:
+  case __format_spec::__type::__hexadecimal_lower_case:
+  case __format_spec::__type::__hexadecimal_upper_case:
+    __format_spec::__process_display_type_integer(__parser);
+    break;
+
+  default:
+    std::__throw_format_error("The format-spec type has a type not supported for a char argument");
+  }
+}
+
+template <class _CharT>
+_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_integer(__parser<_CharT>& __parser) {
+  switch (__parser.__type_) {
+  case __format_spec::__type::__default:
+    __parser.__type_ = __format_spec::__type::__decimal;
+    [[fallthrough]];
+  case __format_spec::__type::__binary_lower_case:
+  case __format_spec::__type::__binary_upper_case:
+  case __format_spec::__type::__octal:
+  case __format_spec::__type::__decimal:
+  case __format_spec::__type::__hexadecimal_lower_case:
+  case __format_spec::__type::__hexadecimal_upper_case:
+    __format_spec::__process_display_type_integer(__parser);
+    break;
+
+  case __format_spec::__type::__char:
+    __format_spec::__process_display_type_char(__parser);
+    break;
+
+  default:
+    std::__throw_format_error("The format-spec type has a type not supported for an integer argument");
   }
 }
 
diff --git a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_bool.pass.cpp b/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_bool.pass.cpp
deleted file mode 100644
--- a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_bool.pass.cpp
+++ /dev/null
@@ -1,380 +0,0 @@
-//===----------------------------------------------------------------------===//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-// UNSUPPORTED: libcpp-has-no-incomplete-format
-
-// <format>
-
-// Tests the parsing of the format string as specified in [format.string.std].
-// It validates whether the std-format-spec is valid for a boolean type.
-
-#include <format>
-#include <cassert>
-#ifndef _LIBCPP_HAS_NO_LOCALIZATION
-# include <iostream>
-#endif
-
-#include "concepts_precision.h"
-#include "test_macros.h"
-#include "make_string.h"
-#include "test_exception.h"
-
-#define CSTR(S) MAKE_CSTRING(CharT, S)
-
-using namespace std::__format_spec;
-
-template <class CharT>
-using Parser = __parser_bool<CharT>;
-
-template <class CharT>
-struct Expected {
-  CharT fill = CharT(' ');
-  _Flags::_Alignment alignment = _Flags::_Alignment::__left;
-  _Flags::_Sign sign = _Flags::_Sign::__default;
-  bool alternate_form = false;
-  bool zero_padding = false;
-  uint32_t width = 0;
-  bool width_as_arg = false;
-  bool locale_specific_form = false;
-  _Flags::_Type type = _Flags::_Type::__string;
-};
-
-template <class CharT>
-constexpr void test(Expected<CharT> expected, size_t size,
-                    std::basic_string_view<CharT> fmt) {
-  // Initialize parser with sufficient arguments to avoid the parsing to fail
-  // due to insufficient arguments.
-  std::basic_format_parse_context<CharT> parse_ctx(fmt,
-                                                   std::__format::__number_max);
-  auto begin = parse_ctx.begin();
-  auto end = parse_ctx.end();
-  Parser<CharT> parser;
-  auto it = parser.parse(parse_ctx);
-
-  assert(begin == parse_ctx.begin());
-  assert(end == parse_ctx.end());
-
-  assert(begin + size == it);
-  assert(parser.__fill == expected.fill);
-  assert(parser.__alignment == expected.alignment);
-  assert(parser.__sign == expected.sign);
-  assert(parser.__alternate_form == expected.alternate_form);
-  assert(parser.__zero_padding == expected.zero_padding);
-  assert(parser.__width == expected.width);
-  assert(parser.__width_as_arg == expected.width_as_arg);
-  assert(parser.__locale_specific_form == expected.locale_specific_form);
-  assert(parser.__type == expected.type);
-}
-
-template <class CharT>
-constexpr void test(Expected<CharT> expected, size_t size, const CharT* f) {
-  // The format-spec is valid if completely consumed or terminates at a '}'.
-  // The valid inputs all end with a '}'. The test is executed twice:
-  // - first with the terminating '}',
-  // - second consuming the entire input.
-  std::basic_string_view<CharT> fmt{f};
-  assert(fmt.back() == CharT('}') && "Pre-condition failure");
-
-  test(expected, size, fmt);
-  fmt.remove_suffix(1);
-  test(expected, size, fmt);
-}
-
-template <class CharT>
-constexpr void test_as_string() {
-
-  test({}, 1, CSTR("s}"));
-
-  // *** Align-fill ***
-  test({.alignment = _Flags::_Alignment::__left}, 1, CSTR("<}"));
-  test({.alignment = _Flags::_Alignment::__center}, 1, "^}");
-  test({.alignment = _Flags::_Alignment::__right}, 1, ">}");
-
-  test({.alignment = _Flags::_Alignment::__left}, 2, CSTR("<s}"));
-  test({.alignment = _Flags::_Alignment::__center}, 2, "^s}");
-  test({.alignment = _Flags::_Alignment::__right}, 2, ">s}");
-
-  test({.fill = CharT('L'), .alignment = _Flags::_Alignment::__left}, 2,
-       CSTR("L<}"));
-  test({.fill = CharT('#'), .alignment = _Flags::_Alignment::__center}, 2,
-       CSTR("#^}"));
-  test({.fill = CharT('0'), .alignment = _Flags::_Alignment::__right}, 2,
-       CSTR("0>}"));
-
-  test({.fill = CharT('L'), .alignment = _Flags::_Alignment::__left}, 3,
-       CSTR("L<s}"));
-  test({.fill = CharT('#'), .alignment = _Flags::_Alignment::__center}, 3,
-       CSTR("#^s}"));
-  test({.fill = CharT('0'), .alignment = _Flags::_Alignment::__right}, 3,
-       CSTR("0>s}"));
-
-  // *** Sign ***
-  test_exception<Parser<CharT>>(
-      "A sign field isn't allowed in this format-spec", CSTR("-}"));
-  test_exception<Parser<CharT>>(
-      "A sign field isn't allowed in this format-spec", CSTR("-s}"));
-
-  // *** Alternate form ***
-  test_exception<Parser<CharT>>(
-      "An alternate form field isn't allowed in this format-spec", CSTR("#}"));
-  test_exception<Parser<CharT>>(
-      "An alternate form field isn't allowed in this format-spec", CSTR("#s}"));
-
-  // *** Zero padding ***
-  test_exception<Parser<CharT>>(
-      "A zero-padding field isn't allowed in this format-spec", CSTR("0}"));
-  test_exception<Parser<CharT>>(
-      "A zero-padding field isn't allowed in this format-spec", CSTR("0s}"));
-
-  // *** Width ***
-  test({.width = 0, .width_as_arg = false}, 0, CSTR("}"));
-  test({.width = 1, .width_as_arg = false}, 1, CSTR("1}"));
-  test({.width = 10, .width_as_arg = false}, 2, CSTR("10}"));
-  test({.width = 1000, .width_as_arg = false}, 4, CSTR("1000}"));
-  test({.width = 1000000, .width_as_arg = false}, 7, CSTR("1000000}"));
-
-  test({.width = 0, .width_as_arg = true}, 2, CSTR("{}}"));
-  test({.width = 0, .width_as_arg = true}, 3, CSTR("{0}}"));
-  test({.width = 1, .width_as_arg = true}, 3, CSTR("{1}}"));
-
-  test_exception<Parser<CharT>>(
-      "A format-spec width field shouldn't have a leading zero", CSTR("00"));
-
-  static_assert(std::__format::__number_max == 2'147'483'647,
-                "Update the assert and the test.");
-  test({.width = 2'147'483'647, .width_as_arg = false}, 10,
-       CSTR("2147483647}"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large", CSTR("2147483648"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large", CSTR("5000000000"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large", CSTR("10000000000"));
-
-  test_exception<Parser<CharT>>("End of input while parsing format-spec arg-id",
-                                CSTR("{"));
-  test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{0"));
-  test_exception<Parser<CharT>>(
-      "The arg-id of the format-spec starts with an invalid character",
-      CSTR("{a"));
-  test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{1"));
-  test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{9"));
-  test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{9:"));
-  test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{9a"));
-
-  static_assert(std::__format::__number_max == 2'147'483'647,
-                "Update the assert and the test.");
-  // Note the static_assert tests whether the arg-id is valid.
-  // Therefore the following should be true arg-id < __format::__number_max.
-  test({.width = 2'147'483'646, .width_as_arg = true}, 12,
-       CSTR("{2147483646}}"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large",
-      CSTR("{2147483648}"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large",
-      CSTR("{5000000000}"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large",
-      CSTR("{10000000000}"));
-
-  // *** Precision ***
-  test_exception<Parser<CharT>>(
-      "The format-spec should consume the input or end with a '}'", CSTR("."));
-  test_exception<Parser<CharT>>(
-      "The format-spec should consume the input or end with a '}'", CSTR(".1"));
-
-  // *** Locale-specific form ***
-  test({.locale_specific_form = true}, 1, CSTR("L}"));
-  test({.locale_specific_form = true}, 2, CSTR("Ls}"));
-}
-
-template <class CharT>
-constexpr void test_as_integer() {
-
-  test({.alignment = _Flags::_Alignment::__right,
-        .type = _Flags::_Type::__decimal},
-       1, CSTR("d}"));
-
-  // *** Align-fill ***
-  test({.alignment = _Flags::_Alignment::__left,
-        .type = _Flags::_Type::__decimal},
-       2, CSTR("<d}"));
-  test({.alignment = _Flags::_Alignment::__center,
-        .type = _Flags::_Type::__decimal},
-       2, "^d}");
-  test({.alignment = _Flags::_Alignment::__right,
-        .type = _Flags::_Type::__decimal},
-       2, ">d}");
-
-  test({.fill = CharT('L'),
-        .alignment = _Flags::_Alignment::__left,
-        .type = _Flags::_Type::__decimal},
-       3, CSTR("L<d}"));
-  test({.fill = CharT('#'),
-        .alignment = _Flags::_Alignment::__center,
-        .type = _Flags::_Type::__decimal},
-       3, CSTR("#^d}"));
-  test({.fill = CharT('0'),
-        .alignment = _Flags::_Alignment::__right,
-        .type = _Flags::_Type::__decimal},
-       3, CSTR("0>d}"));
-
-  // *** Sign ***
-  test({.alignment = _Flags::_Alignment::__right,
-        .sign = _Flags::_Sign::__minus,
-        .type = _Flags::_Type::__decimal},
-       2, CSTR("-d}"));
-  test({.alignment = _Flags::_Alignment::__right,
-        .sign = _Flags::_Sign::__plus,
-        .type = _Flags::_Type::__decimal},
-       2, CSTR("+d}"));
-  test({.alignment = _Flags::_Alignment::__right,
-        .sign = _Flags::_Sign::__space,
-        .type = _Flags::_Type::__decimal},
-       2, CSTR(" d}"));
-
-  // *** Alternate form ***
-  test({.alignment = _Flags::_Alignment::__right,
-        .alternate_form = true,
-        .type = _Flags::_Type::__decimal},
-       2, CSTR("#d}"));
-
-  // *** Zero padding ***
-  test({.alignment = _Flags::_Alignment::__default,
-        .zero_padding = true,
-        .type = _Flags::_Type::__decimal},
-       2, CSTR("0d}"));
-  test({.alignment = _Flags::_Alignment::__center,
-        .type = _Flags::_Type::__decimal},
-       3, CSTR("^0d}"));
-
-  // *** Width ***
-  test({.alignment = _Flags::_Alignment::__right,
-        .width = 0,
-        .width_as_arg = false,
-        .type = _Flags::_Type::__decimal},
-       1, CSTR("d}"));
-  test({.alignment = _Flags::_Alignment::__right,
-        .width = 1,
-        .width_as_arg = false,
-        .type = _Flags::_Type::__decimal},
-       2, CSTR("1d}"));
-  test({.alignment = _Flags::_Alignment::__right,
-        .width = 10,
-        .width_as_arg = false,
-        .type = _Flags::_Type::__decimal},
-       3, CSTR("10d}"));
-  test({.alignment = _Flags::_Alignment::__right,
-        .width = 1000,
-        .width_as_arg = false,
-        .type = _Flags::_Type::__decimal},
-       5, CSTR("1000d}"));
-  test({.alignment = _Flags::_Alignment::__right,
-        .width = 1000000,
-        .width_as_arg = false,
-        .type = _Flags::_Type::__decimal},
-       8, CSTR("1000000d}"));
-
-  test({.alignment = _Flags::_Alignment::__right,
-        .width = 0,
-        .width_as_arg = true,
-        .type = _Flags::_Type::__decimal},
-       3, CSTR("{}d}"));
-  test({.alignment = _Flags::_Alignment::__right,
-        .width = 0,
-        .width_as_arg = true,
-        .type = _Flags::_Type::__decimal},
-       4, CSTR("{0}d}"));
-  test({.alignment = _Flags::_Alignment::__right,
-        .width = 1,
-        .width_as_arg = true,
-        .type = _Flags::_Type::__decimal},
-       4, CSTR("{1}d}"));
-
-  // *** Precision ***
-  test_exception<Parser<CharT>>(
-      "The format-spec should consume the input or end with a '}'", CSTR("."));
-  test_exception<Parser<CharT>>(
-      "The format-spec should consume the input or end with a '}'", CSTR(".1"));
-
-  // *** Locale-specific form ***
-  test({.alignment = _Flags::_Alignment::__right,
-        .locale_specific_form = true,
-        .type = _Flags::_Type::__decimal},
-       2, CSTR("Ld}"));
-}
-
-template <class CharT>
-constexpr void test() {
-  Parser<CharT> parser;
-
-  assert(parser.__fill == CharT(' '));
-  assert(parser.__alignment == _Flags::_Alignment::__default);
-  assert(parser.__sign == _Flags::_Sign::__default);
-  assert(parser.__alternate_form == false);
-  assert(parser.__zero_padding == false);
-  assert(parser.__width == 0);
-  assert(parser.__width_as_arg == false);
-  static_assert(!has_precision<decltype(parser)>);
-  static_assert(!has_precision_as_arg<decltype(parser)>);
-  assert(parser.__locale_specific_form == false);
-  assert(parser.__type == _Flags::_Type::__default);
-
-  test({}, 0, CSTR("}"));
-
-  test_as_string<CharT>();
-  test_as_integer<CharT>();
-
-  // *** Type ***
-  {
-    const char* expected =
-        "The format-spec type has a type not supported for a bool argument";
-    test_exception<Parser<CharT>>(expected, CSTR("A}"));
-    test_exception<Parser<CharT>>(expected, CSTR("E}"));
-    test_exception<Parser<CharT>>(expected, CSTR("F}"));
-    test_exception<Parser<CharT>>(expected, CSTR("G}"));
-    test_exception<Parser<CharT>>(expected, CSTR("a}"));
-    test_exception<Parser<CharT>>(expected, CSTR("c}"));
-    test_exception<Parser<CharT>>(expected, CSTR("e}"));
-    test_exception<Parser<CharT>>(expected, CSTR("f}"));
-    test_exception<Parser<CharT>>(expected, CSTR("g}"));
-    test_exception<Parser<CharT>>(expected, CSTR("p}"));
-  }
-
-  // **** General ***
-  test_exception<Parser<CharT>>(
-      "The format-spec should consume the input or end with a '}'", CSTR("ss"));
-}
-
-constexpr bool test() {
-  test<char>();
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
-#endif
-
-  return true;
-}
-
-int main(int, char**) {
-#ifndef _WIN32
-  // Make sure the parsers match the expectations. The layout of the
-  // subobjects is chosen to minimize the size required.
-  static_assert(sizeof(Parser<char>) == 2 * sizeof(uint32_t));
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  static_assert(
-      sizeof(Parser<wchar_t>) ==
-      (sizeof(wchar_t) <= 2 ? 2 * sizeof(uint32_t) : 3 * sizeof(uint32_t)));
-#endif
-#endif // _WIN32
-
-  test();
-  static_assert(test());
-
-  return 0;
-}
diff --git a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_char.pass.cpp b/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_char.pass.cpp
deleted file mode 100644
--- a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_char.pass.cpp
+++ /dev/null
@@ -1,450 +0,0 @@
-//===----------------------------------------------------------------------===//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-// UNSUPPORTED: libcpp-has-no-incomplete-format
-
-// <format>
-
-// Tests the parsing of the format string as specified in [format.string.std].
-// It validates whether the std-format-spec is valid for a char type.
-
-#include <format>
-#include <cassert>
-#ifndef _LIBCPP_HAS_NO_LOCALIZATION
-# include <iostream>
-#endif
-
-#include "concepts_precision.h"
-#include "test_macros.h"
-#include "make_string.h"
-#include "test_exception.h"
-
-#define CSTR(S) MAKE_CSTRING(CharT, S)
-
-using namespace std::__format_spec;
-
-template <class CharT>
-using Parser = __parser_char<CharT>;
-
-template <class CharT>
-struct Expected {
-  CharT fill = CharT(' ');
-  _Flags::_Alignment alignment = _Flags::_Alignment::__left;
-  _Flags::_Sign sign = _Flags::_Sign::__default;
-  bool alternate_form = false;
-  bool zero_padding = false;
-  uint32_t width = 0;
-  bool width_as_arg = false;
-  bool locale_specific_form = false;
-  _Flags::_Type type = _Flags::_Type::__char;
-};
-
-template <class CharT>
-constexpr void test(Expected<CharT> expected, size_t size,
-                    std::basic_string_view<CharT> fmt) {
-  // Initialize parser with sufficient arguments to avoid the parsing to fail
-  // due to insufficient arguments.
-  std::basic_format_parse_context<CharT> parse_ctx(fmt,
-                                                   std::__format::__number_max);
-  auto begin = parse_ctx.begin();
-  auto end = parse_ctx.end();
-  Parser<CharT> parser;
-  auto it = parser.parse(parse_ctx);
-
-  assert(begin == parse_ctx.begin());
-  assert(end == parse_ctx.end());
-
-  assert(begin + size == it);
-  assert(parser.__fill == expected.fill);
-  assert(parser.__alignment == expected.alignment);
-  assert(parser.__sign == expected.sign);
-  assert(parser.__alternate_form == expected.alternate_form);
-  assert(parser.__zero_padding == expected.zero_padding);
-  assert(parser.__width == expected.width);
-  assert(parser.__width_as_arg == expected.width_as_arg);
-  assert(parser.__locale_specific_form == expected.locale_specific_form);
-  assert(parser.__type == expected.type);
-}
-
-template <class CharT>
-constexpr void test(Expected<CharT> expected, size_t size, const CharT* f) {
-  // The format-spec is valid if completely consumed or terminates at a '}'.
-  // The valid inputs all end with a '}'. The test is executed twice:
-  // - first with the terminating '}',
-  // - second consuming the entire input.
-  std::basic_string_view<CharT> fmt{f};
-  assert(fmt.back() == CharT('}') && "Pre-condition failure");
-
-  test(expected, size, fmt);
-  fmt.remove_suffix(1);
-  test(expected, size, fmt);
-}
-
-template <class CharT>
-constexpr void test_as_char() {
-
-  test({}, 1, CSTR("c}"));
-
-  // *** Align-fill ***
-  test({.alignment = _Flags::_Alignment::__left}, 1, CSTR("<}"));
-  test({.alignment = _Flags::_Alignment::__center}, 1, "^}");
-  test({.alignment = _Flags::_Alignment::__right}, 1, ">}");
-
-  test({.alignment = _Flags::_Alignment::__left}, 2, CSTR("<c}"));
-  test({.alignment = _Flags::_Alignment::__center}, 2, "^c}");
-  test({.alignment = _Flags::_Alignment::__right}, 2, ">c}");
-
-  test({.fill = CharT('L'), .alignment = _Flags::_Alignment::__left}, 2,
-       CSTR("L<}"));
-  test({.fill = CharT('#'), .alignment = _Flags::_Alignment::__center}, 2,
-       CSTR("#^}"));
-  test({.fill = CharT('0'), .alignment = _Flags::_Alignment::__right}, 2,
-       CSTR("0>}"));
-
-  test({.fill = CharT('L'), .alignment = _Flags::_Alignment::__left}, 3,
-       CSTR("L<c}"));
-  test({.fill = CharT('#'), .alignment = _Flags::_Alignment::__center}, 3,
-       CSTR("#^c}"));
-  test({.fill = CharT('0'), .alignment = _Flags::_Alignment::__right}, 3,
-       CSTR("0>c}"));
-
-  // *** Sign ***
-  test_exception<Parser<CharT>>(
-      "A sign field isn't allowed in this format-spec", CSTR("-"));
-  test_exception<Parser<CharT>>(
-      "A sign field isn't allowed in this format-spec", CSTR("+"));
-  test_exception<Parser<CharT>>(
-      "A sign field isn't allowed in this format-spec", CSTR(" "));
-
-  test_exception<Parser<CharT>>(
-      "A sign field isn't allowed in this format-spec", CSTR("-c"));
-  test_exception<Parser<CharT>>(
-      "A sign field isn't allowed in this format-spec", CSTR("+c"));
-  test_exception<Parser<CharT>>(
-      "A sign field isn't allowed in this format-spec", CSTR(" c"));
-
-  // *** Alternate form ***
-  test_exception<Parser<CharT>>(
-      "An alternate form field isn't allowed in this format-spec", CSTR("#}"));
-  test_exception<Parser<CharT>>(
-      "An alternate form field isn't allowed in this format-spec", CSTR("#c}"));
-
-  // *** Zero padding ***
-  test_exception<Parser<CharT>>(
-      "A zero-padding field isn't allowed in this format-spec", CSTR("0}"));
-  test_exception<Parser<CharT>>(
-      "A zero-padding field isn't allowed in this format-spec", CSTR("0c}"));
-
-  // *** Width ***
-  test({.width = 0, .width_as_arg = false}, 0, CSTR("}"));
-  test({.width = 1, .width_as_arg = false}, 1, CSTR("1}"));
-  test({.width = 10, .width_as_arg = false}, 2, CSTR("10}"));
-  test({.width = 1000, .width_as_arg = false}, 4, CSTR("1000}"));
-  test({.width = 1000000, .width_as_arg = false}, 7, CSTR("1000000}"));
-
-  test({.width = 0, .width_as_arg = true}, 2, CSTR("{}}"));
-  test({.width = 0, .width_as_arg = true}, 3, CSTR("{0}}"));
-  test({.width = 1, .width_as_arg = true}, 3, CSTR("{1}}"));
-
-  test_exception<Parser<CharT>>(
-      "A format-spec width field shouldn't have a leading zero", CSTR("00"));
-
-  static_assert(std::__format::__number_max == 2'147'483'647,
-                "Update the assert and the test.");
-  test({.width = 2'147'483'647, .width_as_arg = false}, 10,
-       CSTR("2147483647}"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large", CSTR("2147483648"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large", CSTR("5000000000"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large", CSTR("10000000000"));
-
-  test_exception<Parser<CharT>>("End of input while parsing format-spec arg-id",
-                                CSTR("{"));
-  test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{0"));
-  test_exception<Parser<CharT>>(
-      "The arg-id of the format-spec starts with an invalid character",
-      CSTR("{a"));
-  test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{1"));
-  test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{9"));
-  test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{9:"));
-  test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{9a"));
-
-  static_assert(std::__format::__number_max == 2'147'483'647,
-                "Update the assert and the test.");
-  // Note the static_assert tests whether the arg-id is valid.
-  // Therefore the following should be true arg-id < __format::__number_max.
-  test({.width = 2'147'483'646, .width_as_arg = true}, 12,
-       CSTR("{2147483646}}"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large",
-      CSTR("{2147483648}"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large",
-      CSTR("{5000000000}"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large",
-      CSTR("{10000000000}"));
-
-  // *** Precision ***
-  test_exception<Parser<CharT>>(
-      "The format-spec should consume the input or end with a '}'", CSTR("."));
-  test_exception<Parser<CharT>>(
-      "The format-spec should consume the input or end with a '}'", CSTR(".1"));
-
-  // *** Locale-specific form ***
-  // Note the flag is allowed, but has no effect.
-  test({.locale_specific_form = true}, 1, CSTR("L}"));
-  test({.locale_specific_form = true}, 2, CSTR("Lc}"));
-}
-
-template <class CharT>
-constexpr void test_as_integer() {
-
-  test({.alignment = _Flags::_Alignment::__right,
-        .type = _Flags::_Type::__decimal},
-       1, CSTR("d}"));
-
-  // *** Align-fill ***
-  test({.alignment = _Flags::_Alignment::__left,
-        .type = _Flags::_Type::__decimal},
-       2, CSTR("<d}"));
-  test({.alignment = _Flags::_Alignment::__center,
-        .type = _Flags::_Type::__decimal},
-       2, "^d}");
-  test({.alignment = _Flags::_Alignment::__right,
-        .type = _Flags::_Type::__decimal},
-       2, ">d}");
-
-  test({.fill = CharT('L'),
-        .alignment = _Flags::_Alignment::__left,
-        .type = _Flags::_Type::__decimal},
-       3, CSTR("L<d}"));
-  test({.fill = CharT('#'),
-        .alignment = _Flags::_Alignment::__center,
-        .type = _Flags::_Type::__decimal},
-       3, CSTR("#^d}"));
-  test({.fill = CharT('0'),
-        .alignment = _Flags::_Alignment::__right,
-        .type = _Flags::_Type::__decimal},
-       3, CSTR("0>d}"));
-
-  // *** Sign ***
-  test({.alignment = _Flags::_Alignment::__right,
-        .sign = _Flags::_Sign::__minus,
-        .type = _Flags::_Type::__decimal},
-       2, CSTR("-d}"));
-  test({.alignment = _Flags::_Alignment::__right,
-        .sign = _Flags::_Sign::__plus,
-        .type = _Flags::_Type::__decimal},
-       2, CSTR("+d}"));
-  test({.alignment = _Flags::_Alignment::__right,
-        .sign = _Flags::_Sign::__space,
-        .type = _Flags::_Type::__decimal},
-       2, CSTR(" d}"));
-
-  // *** Alternate form ***
-  test({.alignment = _Flags::_Alignment::__right,
-        .alternate_form = true,
-        .type = _Flags::_Type::__decimal},
-       2, CSTR("#d}"));
-
-  // *** Zero padding ***
-  test({.alignment = _Flags::_Alignment::__default,
-        .zero_padding = true,
-        .type = _Flags::_Type::__decimal},
-       2, CSTR("0d}"));
-  test({.alignment = _Flags::_Alignment::__center,
-        .type = _Flags::_Type::__decimal},
-       3, CSTR("^0d}"));
-
-  // *** Width ***
-  test({.alignment = _Flags::_Alignment::__right,
-        .width = 0,
-        .width_as_arg = false,
-        .type = _Flags::_Type::__decimal},
-       1, CSTR("d}"));
-  test({.alignment = _Flags::_Alignment::__right,
-        .width = 1,
-        .width_as_arg = false,
-        .type = _Flags::_Type::__decimal},
-       2, CSTR("1d}"));
-  test({.alignment = _Flags::_Alignment::__right,
-        .width = 10,
-        .width_as_arg = false,
-        .type = _Flags::_Type::__decimal},
-       3, CSTR("10d}"));
-  test({.alignment = _Flags::_Alignment::__right,
-        .width = 1000,
-        .width_as_arg = false,
-        .type = _Flags::_Type::__decimal},
-       5, CSTR("1000d}"));
-  test({.alignment = _Flags::_Alignment::__right,
-        .width = 1000000,
-        .width_as_arg = false,
-        .type = _Flags::_Type::__decimal},
-       8, CSTR("1000000d}"));
-
-  test({.alignment = _Flags::_Alignment::__right,
-        .width = 0,
-        .width_as_arg = true,
-        .type = _Flags::_Type::__decimal},
-       3, CSTR("{}d}"));
-  test({.alignment = _Flags::_Alignment::__right,
-        .width = 0,
-        .width_as_arg = true,
-        .type = _Flags::_Type::__decimal},
-       4, CSTR("{0}d}"));
-  test({.alignment = _Flags::_Alignment::__right,
-        .width = 1,
-        .width_as_arg = true,
-        .type = _Flags::_Type::__decimal},
-       4, CSTR("{1}d}"));
-
-  // *** Precision ***
-  test_exception<Parser<CharT>>(
-      "The format-spec should consume the input or end with a '}'", CSTR("."));
-  test_exception<Parser<CharT>>(
-      "The format-spec should consume the input or end with a '}'", CSTR(".1"));
-
-  // *** Locale-specific form ***
-  test({.alignment = _Flags::_Alignment::__right,
-        .locale_specific_form = true,
-        .type = _Flags::_Type::__decimal},
-       2, CSTR("Ld}"));
-}
-
-template <class CharT>
-constexpr void test() {
-  Parser<CharT> parser;
-
-  assert(parser.__fill == CharT(' '));
-  assert(parser.__alignment == _Flags::_Alignment::__default);
-  assert(parser.__sign == _Flags::_Sign::__default);
-  assert(parser.__alternate_form == false);
-  assert(parser.__zero_padding == false);
-  assert(parser.__width == 0);
-  assert(parser.__width_as_arg == false);
-  static_assert(!has_precision<decltype(parser)>);
-  static_assert(!has_precision_as_arg<decltype(parser)>);
-  assert(parser.__locale_specific_form == false);
-  assert(parser.__type == _Flags::_Type::__default);
-
-  test({}, 0, CSTR("}"));
-
-  test_as_char<CharT>();
-  test_as_integer<CharT>();
-
-  // *** Type ***
-  {
-    const char* unsuported_type =
-        "The format-spec type has a type not supported for a char argument";
-    const char* not_a_type =
-        "The format-spec should consume the input or end with a '}'";
-
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("A}"));
-    test({.alignment = _Flags::_Alignment::__right,
-          .type = _Flags::_Type::__binary_upper_case},
-         1, CSTR("B}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("C}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("D}"));
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("E}"));
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("F}"));
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("G}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("H}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("I}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("J}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("K}"));
-    test({.locale_specific_form = true}, 1, CSTR("L}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("M}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("N}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("O}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("P}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("Q}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("R}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("S}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("T}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("U}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("V}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("W}"));
-    test({.alignment = _Flags::_Alignment::__right,
-          .type = _Flags::_Type::__hexadecimal_upper_case},
-         1, CSTR("X}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("Y}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("Z}"));
-
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("a}"));
-    test({.alignment = _Flags::_Alignment::__right,
-          .type = _Flags::_Type::__binary_lower_case},
-         1, CSTR("b}"));
-    test({.type = _Flags::_Type::__char}, 1, CSTR("c}"));
-    test({.alignment = _Flags::_Alignment::__right,
-          .type = _Flags::_Type::__decimal},
-         1, CSTR("d}"));
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("e}"));
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("f}"));
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("g}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("h}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("i}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("j}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("k}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("l}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("m}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("n}"));
-    test({.alignment = _Flags::_Alignment::__right,
-          .type = _Flags::_Type::__octal},
-         1, CSTR("o}"));
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("p}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("q}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("r}"));
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("s}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("t}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("u}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("v}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("w}"));
-    test({.alignment = _Flags::_Alignment::__right,
-          .type = _Flags::_Type::__hexadecimal_lower_case},
-         1, CSTR("x}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("y}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("z}"));
-  }
-
-  // **** General ***
-  test_exception<Parser<CharT>>(
-      "The format-spec should consume the input or end with a '}'", CSTR("ss"));
-}
-
-constexpr bool test() {
-  test<char>();
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
-#endif
-
-  return true;
-}
-
-int main(int, char**) {
-#ifndef _WIN32
-  // TODO FMT Investigate why this doesn't work.
-  // (Wait until LWG-3576 has been resolved.)
-  // Make sure the parsers match the expectations. The layout of the
-  // subobjects is chosen to minimize the size required.
-  static_assert(sizeof(Parser<char>) == 2 * sizeof(uint32_t));
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  static_assert(
-      sizeof(Parser<wchar_t>) ==
-      (sizeof(wchar_t) <= 2 ? 2 * sizeof(uint32_t) : 3 * sizeof(uint32_t)));
-#endif
-#endif // _WIN32
-
-  test();
-  static_assert(test());
-
-  return 0;
-}
diff --git a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_integer.pass.cpp b/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_integer.pass.cpp
deleted file mode 100644
--- a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_integer.pass.cpp
+++ /dev/null
@@ -1,343 +0,0 @@
-//===----------------------------------------------------------------------===//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-// UNSUPPORTED: libcpp-has-no-incomplete-format
-
-// <format>
-
-// Tests the parsing of the format string as specified in [format.string.std].
-// It validates whether the std-format-spec is valid for an integer type.
-
-#include <format>
-#include <cassert>
-#ifndef _LIBCPP_HAS_NO_LOCALIZATION
-# include <iostream>
-#endif
-
-#include "concepts_precision.h"
-#include "test_macros.h"
-#include "make_string.h"
-#include "test_exception.h"
-
-#define CSTR(S) MAKE_CSTRING(CharT, S)
-
-using namespace std::__format_spec;
-
-template <class CharT>
-using Parser = __parser_integer<CharT>;
-
-template <class CharT>
-struct Expected {
-  CharT fill = CharT(' ');
-  _Flags::_Alignment alignment = _Flags::_Alignment::__right;
-  _Flags::_Sign sign = _Flags::_Sign::__default;
-  bool alternate_form = false;
-  bool zero_padding = false;
-  uint32_t width = 0;
-  bool width_as_arg = false;
-  bool locale_specific_form = false;
-  _Flags::_Type type = _Flags::_Type::__decimal;
-};
-
-template <class CharT>
-constexpr void test(Expected<CharT> expected, size_t size,
-                    std::basic_string_view<CharT> fmt) {
-  // Initialize parser with sufficient arguments to avoid the parsing to fail
-  // due to insufficient arguments.
-  std::basic_format_parse_context<CharT> parse_ctx(fmt,
-                                                   std::__format::__number_max);
-  auto begin = parse_ctx.begin();
-  auto end = parse_ctx.end();
-  Parser<CharT> parser;
-  auto it = parser.parse(parse_ctx);
-
-  assert(begin == parse_ctx.begin());
-  assert(end == parse_ctx.end());
-
-  assert(begin + size == it);
-  assert(parser.__fill == expected.fill);
-  assert(parser.__alignment == expected.alignment);
-  assert(parser.__sign == expected.sign);
-  assert(parser.__alternate_form == expected.alternate_form);
-  assert(parser.__zero_padding == expected.zero_padding);
-  assert(parser.__width == expected.width);
-  assert(parser.__width_as_arg == expected.width_as_arg);
-  assert(parser.__locale_specific_form == expected.locale_specific_form);
-  assert(parser.__type == expected.type);
-}
-
-template <class CharT>
-constexpr void test(Expected<CharT> expected, size_t size, const CharT* f) {
-  // The format-spec is valid if completely consumed or terminates at a '}'.
-  // The valid inputs all end with a '}'. The test is executed twice:
-  // - first with the terminating '}',
-  // - second consuming the entire input.
-  std::basic_string_view<CharT> fmt{f};
-  assert(fmt.back() == CharT('}') && "Pre-condition failure");
-
-  test(expected, size, fmt);
-  fmt.remove_suffix(1);
-  test(expected, size, fmt);
-}
-
-template <class CharT>
-constexpr void test() {
-  Parser<CharT> parser;
-
-  assert(parser.__fill == CharT(' '));
-  assert(parser.__alignment == _Flags::_Alignment::__default);
-  assert(parser.__sign == _Flags::_Sign::__default);
-  assert(parser.__alternate_form == false);
-  assert(parser.__zero_padding == false);
-  assert(parser.__width == 0);
-  assert(parser.__width_as_arg == false);
-  static_assert(!has_precision<decltype(parser)>);
-  static_assert(!has_precision_as_arg<decltype(parser)>);
-  assert(parser.__locale_specific_form == false);
-  assert(parser.__type == _Flags::_Type::__default);
-
-  test({}, 0, CSTR("}"));
-  test({}, 1, CSTR("d}"));
-  test({.alignment = _Flags::_Alignment::__left, .type = _Flags::_Type::__char},
-       1, CSTR("c}"));
-
-  // *** Align-fill ***
-  test({.alignment = _Flags::_Alignment::__left}, 1, CSTR("<}"));
-  test({.alignment = _Flags::_Alignment::__center}, 1, "^}");
-  test({.alignment = _Flags::_Alignment::__right}, 1, ">}");
-
-  test({.fill = CharT('L'), .alignment = _Flags::_Alignment::__left}, 2,
-       CSTR("L<}"));
-  test({.fill = CharT('#'), .alignment = _Flags::_Alignment::__center}, 2,
-       CSTR("#^}"));
-  test({.fill = CharT('0'), .alignment = _Flags::_Alignment::__right}, 2,
-       CSTR("0>}"));
-
-  test_exception<Parser<CharT>>(
-      "The format-spec fill field contains an invalid character", CSTR("{<"));
-  test_exception<Parser<CharT>>(
-      "The format-spec fill field contains an invalid character", CSTR("}<"));
-
-  // *** Sign ***
-  test({.sign = _Flags::_Sign::__minus}, 1, CSTR("-}"));
-  test({.sign = _Flags::_Sign::__plus}, 1, CSTR("+}"));
-  test({.sign = _Flags::_Sign::__space}, 1, CSTR(" }"));
-
-  test({.sign = _Flags::_Sign::__minus}, 2, CSTR("-d}"));
-  test({.sign = _Flags::_Sign::__plus}, 2, CSTR("+d}"));
-  test({.sign = _Flags::_Sign::__space}, 2, CSTR(" d}"));
-
-  test_exception<Parser<CharT>>(
-      "A sign field isn't allowed in this format-spec", CSTR("-c"));
-  test_exception<Parser<CharT>>(
-      "A sign field isn't allowed in this format-spec", CSTR("+c"));
-  test_exception<Parser<CharT>>(
-      "A sign field isn't allowed in this format-spec", CSTR(" c"));
-
-  // *** Alternate form ***
-  test({.alternate_form = true}, 1, CSTR("#}"));
-  test({.alternate_form = true}, 2, CSTR("#d}"));
-  test_exception<Parser<CharT>>(
-      "An alternate form field isn't allowed in this format-spec", CSTR("#c"));
-
-  // *** Zero padding ***
-  // TODO FMT What to do with zero-padding without a width?
-  // [format.string.std]/13
-  //   A zero (0) character preceding the width field pads the field with
-  //   leading zeros (following any indication of sign or base) to the field
-  //   width, except when applied to an infinity or NaN.
-  // Obviously it makes no sense, but should it be allowed or is it a format
-  // errror?
-  test({.alignment = _Flags::_Alignment::__default, .zero_padding = true}, 1,
-       CSTR("0}"));
-  test({.alignment = _Flags::_Alignment::__left, .zero_padding = false}, 2,
-       CSTR("<0}"));
-  test({.alignment = _Flags::_Alignment::__center, .zero_padding = false}, 2,
-       CSTR("^0}"));
-  test({.alignment = _Flags::_Alignment::__right, .zero_padding = false}, 2,
-       CSTR(">0}"));
-
-  test({.alignment = _Flags::_Alignment::__default, .zero_padding = true}, 2,
-       CSTR("0d}"));
-  test({.alignment = _Flags::_Alignment::__left, .zero_padding = false}, 3,
-       CSTR("<0d}"));
-  test({.alignment = _Flags::_Alignment::__center, .zero_padding = false}, 3,
-       CSTR("^0d}"));
-  test({.alignment = _Flags::_Alignment::__right, .zero_padding = false}, 3,
-       CSTR(">0d}"));
-
-  test_exception<Parser<CharT>>(
-      "A zero-padding field isn't allowed in this format-spec", CSTR("0c"));
-  test_exception<Parser<CharT>>(
-      "A zero-padding field isn't allowed in this format-spec", CSTR("<0c"));
-  test_exception<Parser<CharT>>(
-      "A zero-padding field isn't allowed in this format-spec", CSTR("^0c"));
-  test_exception<Parser<CharT>>(
-      "A zero-padding field isn't allowed in this format-spec", CSTR(">0c"));
-
-  // *** Width ***
-  test({.width = 0, .width_as_arg = false}, 0, CSTR("}"));
-  test({.width = 1, .width_as_arg = false}, 1, CSTR("1}"));
-  test({.width = 10, .width_as_arg = false}, 2, CSTR("10}"));
-  test({.width = 1000, .width_as_arg = false}, 4, CSTR("1000}"));
-  test({.width = 1000000, .width_as_arg = false}, 7, CSTR("1000000}"));
-
-  test({.width = 0, .width_as_arg = true}, 2, CSTR("{}}"));
-  test({.width = 0, .width_as_arg = true}, 3, CSTR("{0}}"));
-  test({.width = 1, .width_as_arg = true}, 3, CSTR("{1}}"));
-
-  test_exception<Parser<CharT>>(
-      "A format-spec width field shouldn't have a leading zero", CSTR("00"));
-
-  static_assert(std::__format::__number_max == 2'147'483'647,
-                "Update the assert and the test.");
-  test({.width = 2'147'483'647, .width_as_arg = false}, 10,
-       CSTR("2147483647}"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large", CSTR("2147483648"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large", CSTR("5000000000"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large", CSTR("10000000000"));
-
-  test_exception<Parser<CharT>>("End of input while parsing format-spec arg-id",
-                                CSTR("{"));
-  test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{0"));
-  test_exception<Parser<CharT>>(
-      "The arg-id of the format-spec starts with an invalid character",
-      CSTR("{a"));
-  test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{1"));
-  test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{9"));
-  test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{9:"));
-  test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{9a"));
-
-  static_assert(std::__format::__number_max == 2'147'483'647,
-                "Update the assert and the test.");
-  // Note the static_assert tests whether the arg-id is valid.
-  // Therefore the following should be true arg-id < __format::__number_max.
-  test({.width = 2'147'483'646, .width_as_arg = true}, 12,
-       CSTR("{2147483646}}"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large",
-      CSTR("{2147483648}"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large",
-      CSTR("{5000000000}"));
-  test_exception<Parser<CharT>>(
-      "The numeric value of the format-spec is too large",
-      CSTR("{10000000000}"));
-
-  // *** Precision ***
-  test_exception<Parser<CharT>>(
-      "The format-spec should consume the input or end with a '}'", CSTR("."));
-  test_exception<Parser<CharT>>(
-      "The format-spec should consume the input or end with a '}'", CSTR(".1"));
-
-  // *** Locale-specific form ***
-  test({.locale_specific_form = true}, 1, CSTR("L}"));
-  test({.locale_specific_form = true}, 2, CSTR("Ld}"));
-  // Note the flag is allowed, but has no effect.
-  test({.alignment = _Flags::_Alignment::__left,
-        .locale_specific_form = true,
-        .type = _Flags::_Type::__char},
-       2, CSTR("Lc}"));
-
-  // *** Type ***
-  {
-    const char* unsuported_type =
-        "The format-spec type has a type not supported for an integer argument";
-    const char* not_a_type =
-        "The format-spec should consume the input or end with a '}'";
-
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("A}"));
-    test({.type = _Flags::_Type::__binary_upper_case}, 1, CSTR("B}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("C}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("D}"));
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("E}"));
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("F}"));
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("G}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("H}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("I}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("J}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("K}"));
-    test({.locale_specific_form = true}, 1, CSTR("L}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("M}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("N}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("O}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("P}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("Q}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("R}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("S}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("T}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("U}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("V}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("W}"));
-    test({.type = _Flags::_Type::__hexadecimal_upper_case}, 1, CSTR("X}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("Y}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("Z}"));
-
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("a}"));
-    test({.type = _Flags::_Type::__binary_lower_case}, 1, CSTR("b}"));
-    test({.alignment = _Flags::_Alignment::__left,
-          .type = _Flags::_Type::__char},
-         1, CSTR("c}"));
-    test({.type = _Flags::_Type::__decimal}, 1, CSTR("d}"));
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("e}"));
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("f}"));
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("g}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("h}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("i}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("j}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("k}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("l}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("m}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("n}"));
-    test({.type = _Flags::_Type::__octal}, 1, CSTR("o}"));
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("p}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("q}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("r}"));
-    test_exception<Parser<CharT>>(unsuported_type, CSTR("s}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("t}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("u}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("v}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("w}"));
-    test({.type = _Flags::_Type::__hexadecimal_lower_case}, 1, CSTR("x}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("y}"));
-    test_exception<Parser<CharT>>(not_a_type, CSTR("z}"));
-  }
-  // **** General ***
-  test_exception<Parser<CharT>>(
-      "The format-spec should consume the input or end with a '}'", CSTR("ss"));
-}
-
-constexpr bool test() {
-  test<char>();
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
-#endif
-
-  return true;
-}
-
-int main(int, char**) {
-#ifndef _WIN32
-  // Make sure the parsers match the expectations. The layout of the
-  // subobjects is chosen to minimize the size required.
-  static_assert(sizeof(Parser<char>) == 2 * sizeof(uint32_t));
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  static_assert(
-      sizeof(Parser<wchar_t>) ==
-      (sizeof(wchar_t) <= 2 ? 2 * sizeof(uint32_t) : 3 * sizeof(uint32_t)));
-#endif
-#endif // _WIN32
-
-  test();
-  static_assert(test());
-
-  return 0;
-}