diff --git a/libcxx/docs/Cxx2aStatusPaperStatus.csv b/libcxx/docs/Cxx2aStatusPaperStatus.csv
--- a/libcxx/docs/Cxx2aStatusPaperStatus.csv
+++ b/libcxx/docs/Cxx2aStatusPaperStatus.csv
@@ -157,7 +157,7 @@
 "`P1871 <https://wg21.link/P1871>`__","LWG","Should concepts be enabled or disabled?","Belfast","* *",""
 "`P1872 <https://wg21.link/P1872>`__","LWG","span should have size_type, not index_type","Belfast","|Complete|","10.0"
 "`P1878 <https://wg21.link/P1878>`__","LWG","Constraining Readable Types","Belfast","* *",""
-"`P1892 <https://wg21.link/P1892>`__","LWG","Extended locale-specific presentation specifiers for std::format","Belfast","* *",""
+"`P1892 <https://wg21.link/P1892>`__","LWG","Extended locale-specific presentation specifiers for std::format","Belfast","|In Progress|",""
 "`P1902 <https://wg21.link/P1902>`__","LWG","Missing feature-test macros 2018-2019","Belfast","* *",""
 "`P1959 <https://wg21.link/P1959>`__","LWG","Remove std::weak_equality and std::strong_equality","Belfast","* *",""
 "`P1960 <https://wg21.link/P1960>`__","LWG","NB Comment Changes Reviewed by SG1","Belfast","* *",""
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -14,6 +14,7 @@
   __format/format_fwd.h
   __format/format_parse_context.h
   __format/format_string.h
+  __format/parser_std_format_spec.h
   __format/formatter.h
   __function_like.h
   __functional_03
diff --git a/libcxx/include/__format/formatter.h b/libcxx/include/__format/formatter.h
--- a/libcxx/include/__format/formatter.h
+++ b/libcxx/include/__format/formatter.h
@@ -11,6 +11,7 @@
 #define _LIBCPP___FORMAT_FORMATTER_H
 
 #include <__config>
+#include <__format/parser_std_format_spec.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #pragma GCC system_header
diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h
new file mode 100644
--- /dev/null
+++ b/libcxx/include/__format/parser_std_format_spec.h
@@ -0,0 +1,640 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___FORMAT_PARSER_STD_FORMAT_SPEC_H
+#define _LIBCPP___FORMAT_PARSER_STD_FORMAT_SPEC_H
+
+#include <__config>
+#include <__debug>
+#include <__format/format_error.h>
+#include <__format/format_string.h>
+#include <concepts>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER > 17
+
+// TODO FMT Remove this once we require compilers with proper C++20 support.
+// If the compiler has no concepts support, the format header will be disabled.
+// Without concepts support enable_if needs to be used and that too much effort
+// to support compilers with partial C++20 support.
+#if !defined(_LIBCPP_HAS_NO_CONCEPTS) &&                                       \
+    !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED)
+
+namespace __format_spec {
+
+/**
+ * Contains the flags for the std-format-spec.
+ *
+ * Some format-options can only be used for specific C++types and may depend on
+ * the selected format-type.
+ * * The C++type filtering can be done using the proper policies for
+ *   @ref __parser_std.
+ * * The format-type filtering needs to be done post parsing in the parser
+ *   derived from @ref __parser_std.
+ */
+class _LIBCPP_TYPE_VIS _Flags {
+public:
+  enum class _LIBCPP_ENUM_VIS _Alignment : uint8_t {
+    /**
+     * No alignment is set in the format string.
+     *
+     * Zero-padding is ignored when an alignment is selected.
+     * The default alignment depends on the selected format-type.
+     */
+    __default,
+    __left,
+    __center,
+    __right
+  };
+  enum class _LIBCPP_ENUM_VIS _Sign : uint8_t {
+    /**
+     * No sign is set in the format string.
+     *
+     * The sign isn't allowed for certain format-types.
+     * This default is used to detect whether the user set the flag. For some
+     * types the user isn't allowed to set the value. This value behaves the
+     * same as setting __minus.
+     */
+    __default,
+    __minus,
+    __plus,
+    __space
+  };
+
+  _Alignment __alignment : 2 {_Alignment::__default};
+  _Sign __sign : 2 {_Sign::__default};
+  uint8_t __alternate_form : 1 {false};
+  uint8_t __zero_padding : 1 {false};
+  uint8_t __locale_specific_form : 1 {false};
+
+  enum class _LIBCPP_ENUM_VIS _Type : uint8_t {
+    __default,
+    __string,
+    __binary_lower_case,
+    __binary_upper_case,
+    __octal,
+    __decimal,
+    __hexadecimal_lower_case,
+    __hexadecimal_upper_case,
+    __pointer,
+    __char,
+    __float_hexadecimal_lower_case,
+    __float_hexadecimal_upper_case,
+    __scientific_lower_case,
+    __scientific_upper_case,
+    __fixed,
+    __general_lower_case,
+    __general_upper_case
+  };
+
+  _Type __type{_Type::__default};
+};
+
+namespace __detail {
+template <class _CharT>
+[[nodiscard]] _LIBCPP_INLINE_VISIBILITY constexpr bool
+__parse_alignment(_CharT __c, _Flags& __flags) noexcept {
+  switch (__c) {
+  case _CharT('<'):
+    __flags.__alignment = _Flags::_Alignment::__left;
+    return true;
+
+  case _CharT('^'):
+    __flags.__alignment = _Flags::_Alignment::__center;
+    return true;
+
+  case _CharT('>'):
+    __flags.__alignment = _Flags::_Alignment::__right;
+    return true;
+  }
+  return false;
+}
+} // namespace __detail
+
+template <class _CharT>
+class _LIBCPP_TEMPLATE_VIS __parser_fill_align {
+public:
+  _CharT __fill{_CharT(' ')};
+
+protected:
+  [[nodiscard]] _LIBCPP_INLINE_VISIBILITY constexpr const _CharT*
+  __consume(const _CharT* __begin, const _CharT* __end, size_t __n) {
+    __begin += __n;
+    if (__begin == __end)
+      __throw_format_error(
+          "End of input while parsing format-spec fill-and-align");
+    return __begin;
+  }
+
+  [[nodiscard]] _LIBCPP_INLINE_VISIBILITY constexpr const _CharT*
+  __parse(const _CharT* __begin, const _CharT* __end, _Flags& __flags) {
+    if (__begin + 1 != __end) {
+      if (__detail::__parse_alignment(*(__begin + 1), __flags)) {
+        if (*__begin == _CharT('{') || *__begin == _CharT('}'))
+          __throw_format_error(
+              "Format-spec contains an invalid fill character");
+        __fill = *__begin;
+        return __consume(__begin, __end, 2);
+      }
+    }
+
+    if (__detail::__parse_alignment(*__begin, __flags))
+      return __consume(__begin, __end, 1);
+
+    return __begin;
+  }
+};
+
+class _LIBCPP_TYPE_VIS __parser_sign {
+protected:
+  template <class _CharT>
+  [[nodiscard]] static _LIBCPP_INLINE_VISIBILITY constexpr const _CharT*
+  __parse(const _CharT* __begin, const _CharT* __end, _Flags& __flags) {
+    switch (*__begin) {
+    case _CharT('-'):
+      __flags.__sign = _Flags::_Sign::__minus;
+      break;
+    case _CharT('+'):
+      __flags.__sign = _Flags::_Sign::__plus;
+      break;
+    case _CharT(' '):
+      __flags.__sign = _Flags::_Sign::__space;
+      break;
+    default:
+      return __begin;
+    }
+    ++__begin;
+    if (__begin == __end)
+      __throw_format_error("End of input while parsing format-spec sign");
+
+    return __begin;
+  }
+};
+
+class _LIBCPP_TYPE_VIS __parser_no_sign {
+protected:
+  template <class _CharT>
+  [[nodiscard]] static _LIBCPP_INLINE_VISIBILITY constexpr const _CharT*
+  __parse(const _CharT* __begin, const _CharT*, _Flags&) {
+    switch (*__begin) {
+    case _CharT('+'):
+    case _CharT('-'):
+    case _CharT(' '):
+      __throw_format_error("Format-spec sign not allowed");
+    }
+
+    return __begin;
+  }
+};
+
+class _LIBCPP_TYPE_VIS __parser_alternate_form {
+protected:
+  template <class _CharT>
+  [[nodiscard]] static _LIBCPP_INLINE_VISIBILITY constexpr const _CharT*
+  __parse(const _CharT* __begin, const _CharT* __end, _Flags& __flags) {
+    if (*__begin == _CharT('#')) {
+      __flags.__alternate_form = true;
+      ++__begin;
+      if (__begin == __end)
+        __throw_format_error(
+            "End of input while parsing format-spec alternate form");
+    }
+
+    return __begin;
+  }
+};
+
+class _LIBCPP_TYPE_VIS __parser_no_alternate_form {
+protected:
+  template <class _CharT>
+  [[nodiscard]] static _LIBCPP_INLINE_VISIBILITY constexpr const _CharT*
+  __parse(const _CharT* __begin, const _CharT*, _Flags&) {
+    if (*__begin == _CharT('#'))
+      __throw_format_error("Format-spec alternate form not allowed");
+
+    return __begin;
+  }
+};
+
+class _LIBCPP_TYPE_VIS __parser_zero_padding {
+protected:
+  template <class _CharT>
+  [[nodiscard]] static _LIBCPP_INLINE_VISIBILITY constexpr const _CharT*
+  __parse(const _CharT* __begin, const _CharT* __end, _Flags& __flags) {
+    if (*__begin == _CharT('0')) {
+      __flags.__zero_padding = true;
+      ++__begin;
+      if (__begin == __end)
+        __throw_format_error(
+            "End of input while parsing format-spec zero-padding");
+    }
+
+    return __begin;
+  }
+};
+
+class _LIBCPP_TYPE_VIS __parser_no_zero_padding {
+protected:
+  template <class _CharT>
+  [[nodiscard]] static _LIBCPP_INLINE_VISIBILITY constexpr const _CharT*
+  __parse(const _CharT* __begin, const _CharT*, _Flags&) {
+    if (*__begin == _CharT('0'))
+      __throw_format_error("Format-spec zero-padding not allowed");
+
+    return __begin;
+  }
+};
+
+template <class _CharT>
+[[nodiscard]] _LIBCPP_INLINE_VISIBILITY constexpr pair<const _CharT*, uint32_t>
+__parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) {
+
+  // This function is a wrapper to call the real parser. But it does the
+  // validation for the pre-conditions and post-conditions.
+  if (__begin == __end)
+    __throw_format_error("End of input while parsing format-spec arg-id");
+
+  pair<const _CharT*, uint32_t> __r =
+      __format::__parse_arg_id(__begin, __end, __parse_ctx);
+
+  if (*__r.first == _CharT(':'))
+    __throw_format_error(
+        "Format-spec arg-id shouldn't contain its own format-spec");
+
+  if (*__r.first != _CharT('}'))
+    __throw_format_error("Format-spec arg-id should terminate at a '}'");
+
+  ++__r.first;
+  if (__r.first == __end)
+    __throw_format_error("End of input while parsing format-spec arg-id");
+
+  return __r;
+}
+
+template <class _Context>
+[[nodiscard]] _LIBCPP_INLINE_VISIBILITY constexpr uint32_t
+__substitute_arg_id(basic_format_arg<_Context> __arg) {
+  return visit_format_arg(
+      [](auto __arg) -> uint32_t {
+        using _Type = decay_t<decltype(__arg)>;
+        if constexpr (integral<_Type>) {
+          if constexpr (signed_integral<_Type>) {
+            if (__arg < 0)
+              __throw_format_error("Format-spec arg-id replacement "
+                                   "shouldn't contain a negative value");
+          }
+
+          using _CT = common_type_t<_Type, decltype(__format::__number_max)>;
+          if (static_cast<_CT>(__arg) >
+              static_cast<_CT>(__format::__number_max))
+            __throw_format_error("Format-spec arg-id replacement "
+                                 "exceeds maximum supported value");
+          return __arg;
+        } else
+          __throw_format_error("Format-spec arg-id replacement "
+                               "argument isn't an integral type");
+      },
+      __arg);
+}
+
+class _LIBCPP_TYPE_VIS __parser_width {
+public:
+  // The width can either contain a real width or and arg-id of the argument
+  // for the width. It would be possible to store it in an int32_t and use
+  // negative values for a real with and the other values for an arg-id. This
+  // would be possible since 0 isn't a valid width. However 0 is a valid
+  // precision. To keep the formats identical the switching between value and
+  // arg-id uses a separate bit.
+  uint32_t __width : 31 {0};
+  uint32_t __width_as_arg : 1 {0};
+
+protected:
+  template <class _CharT>
+  [[nodiscard]] _LIBCPP_INLINE_VISIBILITY constexpr const _CharT*
+  __parse(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) {
+    if (*__begin == _CharT('0'))
+      __throw_format_error(
+          "Format-spec width should not contain a leading zero");
+
+    if (*__begin == _CharT('{')) {
+      pair<const _CharT*, unsigned> __r =
+          __parse_arg_id(++__begin, __end, __parse_ctx);
+      __width = __r.second;
+      __width_as_arg = 1;
+      return __r.first;
+    }
+
+    if (*__begin < _CharT('0') || *__begin > _CharT('9'))
+      return __begin;
+
+    pair<const _CharT*, unsigned> __r =
+        __format::__parse_number(__begin, __end);
+    __width = __r.second;
+    _LIBCPP_ASSERT(__width != 0,
+                   "A zero value isn't allowed and should be impossible, "
+                   "due to validations in this function");
+    return __r.first;
+  }
+
+  void _LIBCPP_INLINE_VISIBILITY constexpr __substitute_width_arg_id(
+      auto&& __arg) {
+    _LIBCPP_ASSERT(
+        __width_as_arg == 1,
+        "Substitute width called without when no substitution is required.");
+    // The clearing of the flag isn't required but looks better when debugging
+    // the code.
+    __width_as_arg = 0;
+    __width = __substitute_arg_id(__arg);
+    if (__width == 0)
+      __throw_format_error(
+          "Format-spec width replacement should contain a positive value");
+  }
+};
+
+class _LIBCPP_TYPE_VIS __parser_precision {
+public:
+  uint32_t __precision : 31 {__format::__number_max};
+  uint32_t __precision_as_arg : 1 {0};
+
+protected:
+  template <class _CharT>
+  [[nodiscard]] _LIBCPP_INLINE_VISIBILITY constexpr const _CharT*
+  __parse(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) {
+    if (*__begin != _CharT('.'))
+      return __begin;
+
+    ++__begin;
+    if (__begin == __end)
+      __throw_format_error("End of input while parsing format-spec precision");
+
+    if (*__begin == _CharT('0')) {
+      ++__begin;
+      if (__begin == __end)
+        __throw_format_error(
+            "Unexpected end of format string while parsing arg-id");
+      if (*__begin >= '0' && *__begin <= '9')
+        __throw_format_error(
+            "Format-spec precision should not contain a leading zero");
+
+      __precision = 0;
+      return __begin;
+    }
+
+    if (*__begin == _CharT('{')) {
+      pair<const _CharT*, unsigned> __arg_id =
+          __parse_arg_id(++__begin, __end, __parse_ctx);
+      __precision = __arg_id.second;
+      __precision_as_arg = 1;
+      return __arg_id.first;
+    }
+
+    if (*__begin < _CharT('0') || *__begin > _CharT('9'))
+      __throw_format_error(
+          "Format-spec precision doesn't contain a value or arg-id");
+
+    pair<const _CharT*, unsigned> __r =
+        __format::__parse_number(__begin, __end);
+    __precision = __r.second;
+    return __r.first;
+  }
+
+  void _LIBCPP_INLINE_VISIBILITY constexpr __substitute_precision_arg_id(
+      auto __arg) {
+    _LIBCPP_ASSERT(__precision_as_arg == 1,
+                   "Substitute precision called without when no substitution "
+                   "is required.");
+    // The clearing of the flag isn't required but looks better when debugging
+    // the code.
+    __precision_as_arg = 0;
+    __precision = __substitute_arg_id(__arg);
+  }
+};
+
+class _LIBCPP_TYPE_VIS __parser_no_precision {
+protected:
+  template <class _CharT>
+  [[nodiscard]] _LIBCPP_INLINE_VISIBILITY constexpr const _CharT*
+  __parse(const _CharT* __begin, const _CharT*, auto&) {
+    if (*__begin == _CharT('.'))
+      __throw_format_error("Format-spec precision not allowed");
+
+    return __begin;
+  }
+};
+
+class _LIBCPP_TYPE_VIS __parser_locale_specific_form {
+protected:
+  template <class _CharT>
+  [[nodiscard]] static _LIBCPP_INLINE_VISIBILITY constexpr const _CharT*
+  __parse(const _CharT* __begin, const _CharT* __end, _Flags& __flags) {
+    if (*__begin == _CharT('L')) {
+      __flags.__locale_specific_form = true;
+      ++__begin;
+      if (__begin == __end)
+        __throw_format_error(
+            "End of input while parsing format-spec locale-specific form");
+    }
+
+    return __begin;
+  }
+};
+
+class _LIBCPP_TYPE_VIS __parser_no_locale_specific_form {
+protected:
+  template <class _CharT>
+  [[nodiscard]] static _LIBCPP_INLINE_VISIBILITY constexpr const _CharT*
+  __parse(const _CharT* __begin, const _CharT*, _Flags&) {
+    if (*__begin == _CharT('L'))
+      __throw_format_error("Format-spec locale-specific form not allowed");
+
+    return __begin;
+  }
+};
+
+/** Parses the type and validates the presence of the final '}'. */
+class _LIBCPP_TYPE_VIS __parser_type {
+protected:
+  template <class _CharT>
+  [[nodiscard]] static _LIBCPP_INLINE_VISIBILITY constexpr const _CharT*
+  __parse(const _CharT* __begin, const _CharT* __end, _Flags& __flags) {
+    if (*__begin != _CharT('}')) {
+      // Determines the type. It does not validate whether the selected type
+      // is valid. Most formatters have optional fields that are only allowed
+      // for certain types. These parsers need to do validation after the
+      // type has been parsed. So its easier to implement the validation for
+      // all types in the specific parse function.
+      switch (*__begin++) {
+      case 'A':
+        __flags.__type = _Flags::_Type::__float_hexadecimal_upper_case;
+        break;
+      case 'B':
+        __flags.__type = _Flags::_Type::__binary_upper_case;
+        break;
+      case 'E':
+        __flags.__type = _Flags::_Type::__scientific_upper_case;
+        break;
+      case 'F':
+        __flags.__type = _Flags::_Type::__fixed;
+        break;
+      case 'G':
+        __flags.__type = _Flags::_Type::__general_upper_case;
+        break;
+      case 'X':
+        __flags.__type = _Flags::_Type::__hexadecimal_upper_case;
+        break;
+      case 'a':
+        __flags.__type = _Flags::_Type::__float_hexadecimal_lower_case;
+        break;
+      case 'b':
+        __flags.__type = _Flags::_Type::__binary_lower_case;
+        break;
+      case 'c':
+        __flags.__type = _Flags::_Type::__char;
+        break;
+      case 'd':
+        __flags.__type = _Flags::_Type::__decimal;
+        break;
+      case 'e':
+        __flags.__type = _Flags::_Type::__scientific_lower_case;
+        break;
+      case 'f':
+        __flags.__type = _Flags::_Type::__fixed;
+        break;
+      case 'g':
+        __flags.__type = _Flags::_Type::__general_lower_case;
+        break;
+      case 'o':
+        __flags.__type = _Flags::_Type::__octal;
+        break;
+      case 'p':
+        __flags.__type = _Flags::_Type::__pointer;
+        break;
+      case 's':
+        __flags.__type = _Flags::_Type::__string;
+        break;
+      case 'x':
+        __flags.__type = _Flags::_Type::__hexadecimal_lower_case;
+        break;
+      default:
+        __throw_format_error("Format-spec type has an unknown type");
+      }
+
+      if (__begin == __end)
+        __throw_format_error("End of input while parsing format-spec type");
+    }
+
+    if (*__begin != _CharT('}'))
+      __throw_format_error("Format-spec should end with a '}'");
+
+    return __begin;
+  }
+};
+
+/**
+ * The parser for the std-format-space.
+ *
+ * The class is a policy based class. The order of the inheritance is picked to
+ * have the minimal padding for all subclasses.
+ *
+ * @note The standard doesn't mandate parsing to be constexpr this is an
+ * extension. https://wg21.link/P2216 will mandate the parsing happens at
+ * compile time.
+ */
+template <class _CharT,
+          class _ParserPrecision,          //
+          class _ParserSign,               //
+          class _ParserAlternateForm,      //
+          class _ParserZeroPadding,        //
+          class _ParserLocaleSpecificForm> //
+class _LIBCPP_TEMPLATE_VIS __parser_std
+    : public __parser_width,              // provides __width(|as_arg)
+      public _ParserPrecision,            // provides __precision(|as_arg)
+      public __parser_fill_align<_CharT>, // provides __fill and uses __flags
+      public _Flags,                      // provides __flags
+      private _ParserSign,                // uses __flags
+      private _ParserAlternateForm,       // uses __flags
+      private _ParserZeroPadding,         // uses __flags
+      private _ParserLocaleSpecificForm,  // uses __flags
+      private __parser_type               // uses __flags
+{
+public:
+  using char_type = _CharT;
+
+  /**
+   * The low-level std-format-spec parse function.
+   *
+   * @pre __begin points at the beginning of the std-format-spec. This means
+   * directly after the ':'.
+   * @pre The std-format-spec is terminated by a '}'. The standard allows to
+   * terminate at __parse_ctx.end(), but the replacement string shall end with
+   * a '}'. Since the parser doesn't first scan for the terminating '}' it
+   * should be there.
+   *
+   * @returns The iterator pointing at '}'.
+   */
+  [[nodiscard]] auto
+      _LIBCPP_INLINE_VISIBILITY constexpr parse(auto& __parse_ctx)
+          -> decltype(__parse_ctx.begin()) {
+    auto __begin = __parse_ctx.begin();
+    auto __end = __parse_ctx.end();
+
+    _LIBCPP_ASSERT(__begin != __end,
+                   "Caller should validate this precondition");
+    __begin = __parser_fill_align<_CharT>::__parse(__begin, __end,
+                                                   static_cast<_Flags&>(*this));
+    _LIBCPP_ASSERT(__begin != __end,
+                   "__parser_fill_align violates its post-condition");
+
+    __begin = _ParserSign::__parse(__begin, __end, static_cast<_Flags&>(*this));
+    _LIBCPP_ASSERT(__begin != __end, "_ParserSign violates its post-condition");
+    __begin = _ParserAlternateForm::__parse(__begin, __end,
+                                            static_cast<_Flags&>(*this));
+    _LIBCPP_ASSERT(__begin != __end,
+                   "_ParserAlternateForm violates its post-condition");
+    __begin = _ParserZeroPadding::__parse(__begin, __end,
+                                          static_cast<_Flags&>(*this));
+    _LIBCPP_ASSERT(__begin != __end,
+                   " _ParserZeroPadding violates its post-condition");
+    __begin = __parser_width::__parse(__begin, __end, __parse_ctx);
+    _LIBCPP_ASSERT(__begin != __end,
+                   "__parser_width violates its post-condition");
+    __begin = _ParserPrecision::__parse(__begin, __end, __parse_ctx);
+    _LIBCPP_ASSERT(__begin != __end,
+                   "_ParserPrecision violates its post-condition");
+    __begin = _ParserLocaleSpecificForm::__parse(__begin, __end,
+                                                 static_cast<_Flags&>(*this));
+    _LIBCPP_ASSERT(__begin != __end,
+                   "_ParserLocaleSpecificForm violates its post-condition");
+    __begin =
+        __parser_type::__parse(__begin, __end, static_cast<_Flags&>(*this));
+    _LIBCPP_ASSERT(__begin != __end,
+                   "__parser_type violates its post-condition");
+    return __begin;
+  }
+};
+
+} // namespace __format_spec
+
+#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED)
+
+#endif //_LIBCPP_STD_VER > 17
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___FORMAT_PARSER_STD_FORMAT_SPEC_H
diff --git a/libcxx/include/format b/libcxx/include/format
--- a/libcxx/include/format
+++ b/libcxx/include/format
@@ -282,6 +282,7 @@
 #include <__format/format_error.h>
 #include <__format/format_parse_context.h>
 #include <__format/format_string.h>
+#include <__format/parser_std_format_spec.h>
 #include <__format/formatter.h>
 #include <concepts>
 #include <string>
diff --git a/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_alternate_form.pass.cpp b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_alternate_form.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_alternate_form.pass.cpp
@@ -0,0 +1,79 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// <format>
+
+// [format.string.std] Standard format specifiers
+// - Tests parsing of the alternate form.
+
+#include <format>
+#include <cassert>
+#include <iostream>
+
+#include "test_macros.h"
+#include "make_string.h"
+
+#define CSTR(S) MAKE_CSTRING(CharT, S)
+
+using namespace std::__format_spec;
+
+template <class CharT>
+using parser = __parser_std<CharT, __parser_no_precision, __parser_no_sign,
+                            __parser_alternate_form, __parser_no_zero_padding,
+                            __parser_no_locale_specific_form>;
+
+#include "test_exception.h" // requires parser
+
+template <class CharT>
+constexpr void test(bool expected, size_t size, const CharT* fmt) {
+  std::basic_format_parse_context<CharT> parse_ctx(fmt);
+  auto begin = parse_ctx.begin();
+  parser<CharT> parser;
+  auto it = parser.parse(parse_ctx);
+
+  assert(begin + size == it);
+  assert(parser.__fill == CharT(' '));
+  assert(parser.__alignment == _Flags::_Alignment::__default);
+  assert(parser.__sign == _Flags::_Sign::__default);
+  assert(parser.__alternate_form == expected);
+  assert(parser.__zero_padding == false);
+  assert(parser.__width == 0);
+  assert(parser.__width_as_arg == false);
+  assert(parser.__locale_specific_form == false);
+  assert(parser.__type == _Flags::_Type::__default);
+}
+
+template <class CharT>
+constexpr void test() {
+  test(false, 0, CSTR("}"));
+  test(true, 1, CSTR("#}"));
+
+  test_exception("End of input while parsing format-spec alternate form",
+                 CSTR("#"));
+}
+
+constexpr bool test() {
+  test<char>();
+  test<wchar_t>();
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+  test<char8_t>();
+#endif
+#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
+  test<char16_t>();
+  test<char32_t>();
+#endif
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_fill_align.pass.cpp b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_fill_align.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_fill_align.pass.cpp
@@ -0,0 +1,96 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// <format>
+
+// [format.string.std] Standard format specifiers
+// - Tests parsing of the fill and alignment.
+
+#include <format>
+#include <cassert>
+#include <iostream>
+
+#include "test_macros.h"
+#include "make_string.h"
+
+#define CSTR(S) MAKE_CSTRING(CharT, S)
+
+using namespace std::__format_spec;
+
+template <class CharT>
+using parser =
+    __parser_std<CharT, __parser_no_precision, __parser_no_sign,
+                 __parser_no_alternate_form, __parser_no_zero_padding,
+                 __parser_no_locale_specific_form>;
+
+#include "test_exception.h" // requires parser
+
+template <class CharT>
+struct Expected {
+  CharT fill;
+  _Flags::_Alignment alignment;
+};
+
+template <class CharT>
+constexpr void test(Expected<CharT> expected, size_t size, const CharT* fmt) {
+  std::basic_format_parse_context<CharT> parse_ctx(fmt);
+  auto begin = parse_ctx.begin();
+  parser<CharT> parser;
+  auto it = parser.parse(parse_ctx);
+
+  assert(begin + size == it);
+  assert(parser.__fill == expected.fill);
+  assert(parser.__alignment == expected.alignment);
+  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);
+  assert(parser.__locale_specific_form == false);
+  assert(parser.__type == _Flags::_Type::__default);
+}
+
+template <class CharT>
+constexpr void test() {
+  test({CharT(' '), _Flags::_Alignment::__default}, 0, CSTR("}"));
+  test({CharT(' '), _Flags::_Alignment::__left}, 1, CSTR("<}"));
+  test({CharT(' '), _Flags::_Alignment::__center}, 1, CSTR("^}"));
+  test({CharT(' '), _Flags::_Alignment::__right}, 1, CSTR(">}"));
+
+  test({CharT('1'), _Flags::_Alignment::__left}, 2, CSTR("1<}"));
+  test({CharT('a'), _Flags::_Alignment::__center}, 2, CSTR("a^}"));
+  test({CharT('#'), _Flags::_Alignment::__right}, 2, CSTR("#>}"));
+
+  test_exception("Format-spec contains an invalid fill character", CSTR("{<}"));
+  test_exception("Format-spec contains an invalid fill character", CSTR("}>}"));
+  test_exception("End of input while parsing format-spec fill-and-align",
+                 CSTR("<"));
+  test_exception("End of input while parsing format-spec fill-and-align",
+                 CSTR("X<"));
+}
+
+constexpr bool test() {
+  test<char>();
+  test<wchar_t>();
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+  test<char8_t>();
+#endif
+#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
+  test<char16_t>();
+  test<char32_t>();
+#endif
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_locale_specific_form.pass.cpp b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_locale_specific_form.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_locale_specific_form.pass.cpp
@@ -0,0 +1,80 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// <format>
+
+// [format.string.std] Standard format specifiers
+// - Tests parsing of the locale-specific form.
+
+#include <format>
+#include <cassert>
+#include <iostream>
+
+#include "test_macros.h"
+#include "make_string.h"
+
+#define CSTR(S) MAKE_CSTRING(CharT, S)
+
+using namespace std::__format_spec;
+
+template <class CharT>
+using parser =
+    __parser_std<CharT, __parser_no_precision, __parser_no_sign,
+                 __parser_no_alternate_form, __parser_no_zero_padding,
+                 __parser_locale_specific_form>;
+
+#include "test_exception.h" // requires parser
+
+template <class CharT>
+constexpr void test(bool expected, size_t size, const CharT* fmt) {
+  std::basic_format_parse_context<CharT> parse_ctx(fmt);
+  auto begin = parse_ctx.begin();
+  parser<CharT> parser;
+  auto it = parser.parse(parse_ctx);
+
+  assert(begin + size == it);
+  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);
+  assert(parser.__locale_specific_form == expected);
+  assert(parser.__type == _Flags::_Type::__default);
+}
+
+template <class CharT>
+constexpr void test() {
+  test(false, 0, CSTR("}"));
+  test(true, 1, CSTR("L}"));
+
+  test_exception("End of input while parsing format-spec locale-specific form",
+                 CSTR("L"));
+}
+
+constexpr bool test() {
+  test<char>();
+  test<wchar_t>();
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+  test<char8_t>();
+#endif
+#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
+  test<char16_t>();
+  test<char32_t>();
+#endif
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_no_alternate_form.pass.cpp b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_no_alternate_form.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_no_alternate_form.pass.cpp
@@ -0,0 +1,77 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// <format>
+
+// [format.string.std] Standard format specifiers
+// - Tests parsing of the alternate form.
+
+#include <format>
+#include <cassert>
+#include <iostream>
+
+#include "test_macros.h"
+#include "make_string.h"
+
+#define CSTR(S) MAKE_CSTRING(CharT, S)
+
+using namespace std::__format_spec;
+
+template <class CharT>
+using parser =
+    __parser_std<CharT, __parser_no_precision, __parser_no_sign,
+                 __parser_no_alternate_form, __parser_no_zero_padding,
+                 __parser_no_locale_specific_form>;
+
+#include "test_exception.h" // requires parser
+
+template <class CharT>
+constexpr void test(const CharT* fmt) {
+  std::basic_format_parse_context<CharT> parse_ctx(fmt);
+  auto begin = parse_ctx.begin();
+  parser<CharT> parser;
+  auto it = parser.parse(parse_ctx);
+
+  assert(begin == it);
+  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);
+  assert(parser.__locale_specific_form == false);
+  assert(parser.__type == _Flags::_Type::__default);
+}
+
+template <class CharT>
+constexpr void test() {
+  test(CSTR("}"));
+  test_exception("Format-spec alternate form not allowed", CSTR("#"));
+}
+
+constexpr bool test() {
+  test<char>();
+  test<wchar_t>();
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+  test<char8_t>();
+#endif
+#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
+  test<char16_t>();
+  test<char32_t>();
+#endif
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_no_locale_specific_form.pass.cpp b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_no_locale_specific_form.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_no_locale_specific_form.pass.cpp
@@ -0,0 +1,77 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// <format>
+
+// [format.string.std] Standard format specifiers
+// - Tests parsing of the locale-specific form.
+
+#include <format>
+#include <cassert>
+#include <iostream>
+
+#include "test_macros.h"
+#include "make_string.h"
+
+#define CSTR(S) MAKE_CSTRING(CharT, S)
+
+using namespace std::__format_spec;
+
+template <class CharT>
+using parser =
+    __parser_std<CharT, __parser_no_precision, __parser_no_sign,
+                 __parser_no_alternate_form, __parser_no_zero_padding,
+                 __parser_no_locale_specific_form>;
+
+#include "test_exception.h" // requires parser
+
+template <class CharT>
+constexpr void test(const CharT* fmt) {
+  std::basic_format_parse_context<CharT> parse_ctx(fmt);
+  auto begin = parse_ctx.begin();
+  parser<CharT> parser;
+  auto it = parser.parse(parse_ctx);
+
+  assert(begin == it);
+  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);
+  assert(parser.__locale_specific_form == false);
+  assert(parser.__type == _Flags::_Type::__default);
+}
+
+template <class CharT>
+constexpr void test() {
+  test(CSTR("}"));
+  test_exception("Format-spec locale-specific form not allowed", CSTR("L"));
+}
+
+constexpr bool test() {
+  test<char>();
+  test<wchar_t>();
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+  test<char8_t>();
+#endif
+#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
+  test<char16_t>();
+  test<char32_t>();
+#endif
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_no_precision.pass.cpp b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_no_precision.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_no_precision.pass.cpp
@@ -0,0 +1,77 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// <format>
+
+// [format.string.std] Standard format specifiers
+// - Tests parsing of the precision.
+
+#include <format>
+#include <cassert>
+#include <iostream>
+
+#include "test_macros.h"
+#include "make_string.h"
+
+#define CSTR(S) MAKE_CSTRING(CharT, S)
+
+using namespace std::__format_spec;
+
+template <class CharT>
+using parser =
+    __parser_std<CharT, __parser_no_precision, __parser_no_sign,
+                 __parser_no_alternate_form, __parser_no_zero_padding,
+                 __parser_no_locale_specific_form>;
+
+#include "test_exception.h" // requires parser
+
+template <class CharT>
+constexpr void test(const CharT* fmt) {
+  std::basic_format_parse_context<CharT> parse_ctx(fmt);
+  auto begin = parse_ctx.begin();
+  parser<CharT> parser;
+  auto it = parser.parse(parse_ctx);
+
+  assert(begin == it);
+  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);
+  assert(parser.__locale_specific_form == false);
+  assert(parser.__type == _Flags::_Type::__default);
+}
+
+template <class CharT>
+constexpr void test() {
+  test(CSTR("}"));
+  test_exception("Format-spec precision not allowed", CSTR("."));
+}
+
+constexpr bool test() {
+  test<char>();
+  test<wchar_t>();
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+  test<char8_t>();
+#endif
+#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
+  test<char16_t>();
+  test<char32_t>();
+#endif
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_no_sign.pass.cpp b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_no_sign.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_no_sign.pass.cpp
@@ -0,0 +1,79 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// <format>
+
+// [format.string.std] Standard format specifiers
+// - Tests parsing of the sign.
+
+#include <format>
+#include <cassert>
+#include <iostream>
+
+#include "test_macros.h"
+#include "make_string.h"
+
+#define CSTR(S) MAKE_CSTRING(CharT, S)
+
+using namespace std::__format_spec;
+
+template <class CharT>
+using parser =
+    __parser_std<CharT, __parser_no_precision, __parser_no_sign,
+                 __parser_no_alternate_form, __parser_no_zero_padding,
+                 __parser_no_locale_specific_form>;
+
+#include "test_exception.h" // requires parser
+
+template <class CharT>
+constexpr void test(const CharT* fmt) {
+  std::basic_format_parse_context<CharT> parse_ctx(fmt);
+  auto begin = parse_ctx.begin();
+  parser<CharT> parser;
+  auto it = parser.parse(parse_ctx);
+
+  assert(begin == it);
+  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);
+  assert(parser.__locale_specific_form == false);
+  assert(parser.__type == _Flags::_Type::__default);
+}
+
+template <class CharT>
+constexpr void test() {
+  test(CSTR("}"));
+  test_exception("Format-spec sign not allowed", CSTR("-"));
+  test_exception("Format-spec sign not allowed", CSTR("+"));
+  test_exception("Format-spec sign not allowed", CSTR(" "));
+}
+
+constexpr bool test() {
+  test<char>();
+  test<wchar_t>();
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+  test<char8_t>();
+#endif
+#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
+  test<char16_t>();
+  test<char32_t>();
+#endif
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_no_zero_padding.pass.cpp b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_no_zero_padding.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_no_zero_padding.pass.cpp
@@ -0,0 +1,77 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// <format>
+
+// [format.string.std] Standard format specifiers
+// - Tests parsing of the zero-padding.
+
+#include <format>
+#include <cassert>
+#include <iostream>
+
+#include "test_macros.h"
+#include "make_string.h"
+
+#define CSTR(S) MAKE_CSTRING(CharT, S)
+
+using namespace std::__format_spec;
+
+template <class CharT>
+using parser =
+    __parser_std<CharT, __parser_no_precision, __parser_no_sign,
+                 __parser_no_alternate_form, __parser_no_zero_padding,
+                 __parser_no_locale_specific_form>;
+
+#include "test_exception.h" // requires parser
+
+template <class CharT>
+constexpr void test(const CharT* fmt) {
+  std::basic_format_parse_context<CharT> parse_ctx(fmt);
+  auto begin = parse_ctx.begin();
+  parser<CharT> parser;
+  auto it = parser.parse(parse_ctx);
+
+  assert(begin == it);
+  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);
+  assert(parser.__locale_specific_form == false);
+  assert(parser.__type == _Flags::_Type::__default);
+}
+
+template <class CharT>
+constexpr void test() {
+  test(CSTR("}"));
+  test_exception("Format-spec zero-padding not allowed", CSTR("0"));
+}
+
+constexpr bool test() {
+  test<char>();
+  test<wchar_t>();
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+  test<char8_t>();
+#endif
+#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
+  test<char16_t>();
+  test<char32_t>();
+#endif
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_precision.pass.cpp b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_precision.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_precision.pass.cpp
@@ -0,0 +1,125 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// <format>
+
+// [format.string.std] Standard format specifiers
+// - Tests parsing of the precision.
+
+#include <format>
+#include <cassert>
+#include <iostream>
+
+#include "test_macros.h"
+#include "make_string.h"
+
+#define CSTR(S) MAKE_CSTRING(CharT, S)
+
+using namespace std::__format_spec;
+
+template <class CharT>
+using parser =
+    __parser_std<CharT, __parser_precision, __parser_no_sign,
+                 __parser_no_alternate_form, __parser_no_zero_padding,
+                 __parser_no_locale_specific_form>;
+
+#include "test_exception.h" // requires parser
+
+struct Expected {
+  uint32_t __precision{0};
+  bool __precision_as_arg{false};
+};
+
+template <class CharT>
+constexpr void test(Expected expected, size_t size, const 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();
+  parser<CharT> parser;
+  auto it = parser.parse(parse_ctx);
+
+  assert(begin + size == it);
+  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 == 0);
+  assert(parser.__precision == expected.__precision);
+  assert(parser.__precision_as_arg == expected.__precision_as_arg);
+  assert(parser.__locale_specific_form == false);
+  assert(parser.__type == _Flags::_Type::__default);
+}
+
+template <class CharT>
+constexpr void test() {
+  test({std::__format::__number_max, 0}, 0, CSTR("}"));
+  test({0, 0}, 2, CSTR(".0}"));
+  test({1, 0}, 2, CSTR(".1}"));
+  test({10, 0}, 3, CSTR(".10}"));
+  test({1000, 0}, 5, CSTR(".1000}"));
+  test({1000000, 0}, 8, CSTR(".1000000}"));
+
+  test({0, 1}, 3, CSTR(".{}}"));
+  test({0, 1}, 4, CSTR(".{0}}"));
+  test({1, 1}, 4, CSTR(".{1}}"));
+
+  test_exception("Format-spec precision should not contain a leading zero",
+                 CSTR(".00"));
+  test_exception("Format-spec precision should not contain a leading zero",
+                 CSTR(".01"));
+  test_exception("Format-spec precision doesn't contain a value or arg-id",
+                 CSTR(".a"));
+  test_exception("Format-spec precision doesn't contain a value or arg-id",
+                 ".:");
+  test_exception("End of input while parsing format-spec numeric value",
+                 CSTR(".1"));
+  static_assert(std::__format::__number_max == 999'999'999,
+                "Update the assert and the test.");
+  test_exception("Format-spec numeric value too large", CSTR(".1000000000}"));
+
+  test_exception("End of input while parsing format-spec arg-id", CSTR(".{"));
+  test_exception("Format-spec arg-id should terminate at a '}'", CSTR(".{0"));
+  test_exception("Format-spec arg-id starts with an invalid character", ".{a");
+  test_exception("End of input while parsing format-spec numeric value",
+                 CSTR(".{1"));
+  test_exception("End of input while parsing format-spec numeric value",
+                 CSTR(".{9"));
+  test_exception("Format-spec arg-id shouldn't contain its own format-spec",
+                 CSTR(".{9:"));
+  test_exception("Format-spec arg-id should terminate at a '}'", CSTR(".{9a"));
+  test_exception("End of input while parsing format-spec arg-id", CSTR(".{1}"));
+
+  static_assert(std::__format::__number_max == 999'999'999,
+                "Update the assert and the test.");
+  test_exception("Format-spec numeric value too large", CSTR(".{1000000000}"));
+}
+
+constexpr bool test() {
+  test<char>();
+  test<wchar_t>();
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+  test<char8_t>();
+#endif
+#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
+  test<char16_t>();
+  test<char32_t>();
+#endif
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_sign.pass.cpp b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_sign.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_sign.pass.cpp
@@ -0,0 +1,81 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// <format>
+
+// [format.string.std] Standard format specifiers
+// - Tests parsing of the sign.
+
+#include <format>
+#include <cassert>
+#include <iostream>
+
+#include "test_macros.h"
+#include "make_string.h"
+
+#define CSTR(S) MAKE_CSTRING(CharT, S)
+
+using namespace std::__format_spec;
+
+template <class CharT>
+using parser =
+    __parser_std<CharT, __parser_no_precision, __parser_sign,
+                 __parser_no_alternate_form, __parser_no_zero_padding,
+                 __parser_no_locale_specific_form>;
+
+#include "test_exception.h" // requires parser
+
+template <class CharT>
+constexpr void test(_Flags::_Sign expected, size_t size, const CharT* fmt) {
+  std::basic_format_parse_context<CharT> parse_ctx(fmt);
+  auto begin = parse_ctx.begin();
+  parser<CharT> parser;
+  auto it = parser.parse(parse_ctx);
+
+  assert(begin + size == it);
+  assert(parser.__fill == CharT(' '));
+  assert(parser.__alignment == _Flags::_Alignment::__default);
+  assert(parser.__sign == expected);
+  assert(parser.__alternate_form == false);
+  assert(parser.__zero_padding == false);
+  assert(parser.__width == 0);
+  assert(parser.__width_as_arg == false);
+  assert(parser.__locale_specific_form == false);
+  assert(parser.__type == _Flags::_Type::__default);
+}
+
+template <class CharT>
+constexpr void test() {
+  test(_Flags::_Sign::__default, 0, CSTR("}"));
+  test(_Flags::_Sign::__minus, 1, CSTR("-}"));
+  test(_Flags::_Sign::__plus, 1, CSTR("+}"));
+  test(_Flags::_Sign::__space, 1, CSTR(" }"));
+
+  test_exception("End of input while parsing format-spec sign", CSTR("-"));
+}
+
+constexpr bool test() {
+  test<char>();
+  test<wchar_t>();
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+  test<char8_t>();
+#endif
+#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
+  test<char16_t>();
+  test<char32_t>();
+#endif
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_type.pass.cpp b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_type.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_type.pass.cpp
@@ -0,0 +1,133 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// <format>
+
+// [format.string.std] Standard format specifiers
+// - Tests parsing of the type.
+
+#include <format>
+#include <cassert>
+#include <iostream>
+
+#include "test_macros.h"
+#include "make_string.h"
+
+#define CSTR(S) MAKE_CSTRING(CharT, S)
+
+using namespace std::__format_spec;
+
+template <class CharT>
+using parser =
+    __parser_std<CharT, __parser_no_precision, __parser_no_sign,
+                 __parser_no_alternate_form, __parser_no_zero_padding,
+                 __parser_no_locale_specific_form>;
+
+#include "test_exception.h" // requires parser
+
+template <class CharT>
+constexpr void test(_Flags::_Type expected, size_t size, const CharT* fmt) {
+  std::basic_format_parse_context<CharT> parse_ctx(fmt);
+  auto begin = parse_ctx.begin();
+  parser<CharT> parser;
+  auto it = parser.parse(parse_ctx);
+
+  assert(begin + size == it);
+  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);
+  assert(parser.__locale_specific_form == false);
+  assert(parser.__type == expected);
+}
+
+template <class CharT>
+constexpr void test() {
+  test(_Flags::_Type::__default, 0, CSTR("}"));
+
+  test(_Flags::_Type::__float_hexadecimal_upper_case, 1, CSTR("A}"));
+  test(_Flags::_Type::__binary_upper_case, 1, CSTR("B}"));
+  test_exception("Format-spec type has an unknown type", CSTR("C"));
+  test_exception("Format-spec type has an unknown type", CSTR("D"));
+  test(_Flags::_Type::__scientific_upper_case, 1, CSTR("E}"));
+  test(_Flags::_Type::__fixed, 1, CSTR("F}"));
+  test(_Flags::_Type::__general_upper_case, 1, CSTR("G}"));
+  test_exception("Format-spec type has an unknown type", CSTR("H"));
+  test_exception("Format-spec type has an unknown type", CSTR("I"));
+  test_exception("Format-spec type has an unknown type", CSTR("J"));
+  test_exception("Format-spec type has an unknown type", CSTR("K"));
+  test_exception("Format-spec locale-specific form not allowed", CSTR("L"));
+  test_exception("Format-spec type has an unknown type", CSTR("M"));
+  test_exception("Format-spec type has an unknown type", CSTR("N"));
+  test_exception("Format-spec type has an unknown type", CSTR("O"));
+  test_exception("Format-spec type has an unknown type", CSTR("P"));
+  test_exception("Format-spec type has an unknown type", CSTR("Q"));
+  test_exception("Format-spec type has an unknown type", CSTR("R"));
+  test_exception("Format-spec type has an unknown type", CSTR("S"));
+  test_exception("Format-spec type has an unknown type", CSTR("T"));
+  test_exception("Format-spec type has an unknown type", CSTR("U"));
+  test_exception("Format-spec type has an unknown type", CSTR("V"));
+  test_exception("Format-spec type has an unknown type", CSTR("W"));
+  test(_Flags::_Type::__hexadecimal_upper_case, 1, CSTR("X}"));
+  test_exception("Format-spec type has an unknown type", CSTR("Y"));
+  test_exception("Format-spec type has an unknown type", CSTR("Z"));
+
+  test(_Flags::_Type::__float_hexadecimal_lower_case, 1, CSTR("a}"));
+  test(_Flags::_Type::__binary_lower_case, 1, CSTR("b}"));
+  test(_Flags::_Type::__char, 1, CSTR("c}"));
+  test(_Flags::_Type::__decimal, 1, CSTR("d}"));
+  test(_Flags::_Type::__scientific_lower_case, 1, CSTR("e}"));
+  test(_Flags::_Type::__fixed, 1, CSTR("f}"));
+  test(_Flags::_Type::__general_lower_case, 1, CSTR("g}"));
+  test_exception("Format-spec type has an unknown type", CSTR("h"));
+  test_exception("Format-spec type has an unknown type", CSTR("i"));
+  test_exception("Format-spec type has an unknown type", CSTR("j"));
+  test_exception("Format-spec type has an unknown type", CSTR("k"));
+  test_exception("Format-spec type has an unknown type", CSTR("l"));
+  test_exception("Format-spec type has an unknown type", CSTR("m"));
+  test_exception("Format-spec type has an unknown type", CSTR("n"));
+  test(_Flags::_Type::__octal, 1, CSTR("o}"));
+  test(_Flags::_Type::__pointer, 1, CSTR("p}"));
+  test_exception("Format-spec type has an unknown type", CSTR("q"));
+  test_exception("Format-spec type has an unknown type", CSTR("r"));
+  test(_Flags::_Type::__string, 1, CSTR("s}"));
+  test_exception<CharT>("Format-spec type has an unknown type", CSTR("t"));
+  test_exception<CharT>("Format-spec type has an unknown type", CSTR("u"));
+  test_exception<CharT>("Format-spec type has an unknown type", CSTR("v"));
+  test_exception<CharT>("Format-spec type has an unknown type", CSTR("w"));
+  test(_Flags::_Type::__hexadecimal_lower_case, 1, CSTR("x}"));
+  test_exception("Format-spec type has an unknown type", CSTR("y"));
+  test_exception("Format-spec type has an unknown type", CSTR("z"));
+
+  test_exception("End of input while parsing format-spec type", CSTR("a"));
+  test_exception("Format-spec should end with a '}'", CSTR("ab"));
+}
+
+constexpr bool test() {
+  test<char>();
+  test<wchar_t>();
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+  test<char8_t>();
+#endif
+#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
+  test<char16_t>();
+  test<char32_t>();
+#endif
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_width.pass.cpp b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_width.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_width.pass.cpp
@@ -0,0 +1,116 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// <format>
+
+// [format.string.std] Standard format specifiers
+// - Tests parsing of the width.
+
+#include <format>
+#include <cassert>
+#include <iostream>
+
+#include "test_macros.h"
+#include "make_string.h"
+
+#define CSTR(S) MAKE_CSTRING(CharT, S)
+
+using namespace std::__format_spec;
+
+template <class CharT>
+using parser = __parser_std<CharT, __parser_no_precision, __parser_no_sign,
+                            __parser_no_alternate_form, __parser_zero_padding,
+                            __parser_no_locale_specific_form>;
+
+#include "test_exception.h" // requires parser
+
+struct Expected {
+  uint32_t __width{0};
+  bool __width_as_arg{false};
+};
+
+template <class CharT>
+constexpr void test(Expected expected, size_t size, const 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();
+  parser<CharT> parser;
+  auto it = parser.parse(parse_ctx);
+
+  assert(begin + size == it);
+  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 == expected.__width);
+  assert(parser.__width_as_arg == expected.__width_as_arg);
+  assert(parser.__locale_specific_form == false);
+  assert(parser.__type == _Flags::_Type::__default);
+}
+
+template <class CharT>
+constexpr void test() {
+  test({0, 0}, 0, CSTR("}"));
+  test({1, 0}, 1, CSTR("1}"));
+  test({10, 0}, 2, CSTR("10}"));
+  test({1000, 0}, 4, CSTR("1000}"));
+  test({1000000, 0}, 7, CSTR("1000000}"));
+
+  test({0, 1}, 2, CSTR("{}}"));
+  test({0, 1}, 3, CSTR("{0}}"));
+  test({1, 1}, 3, CSTR("{1}}"));
+
+  test_exception("Format-spec width should not contain a leading zero",
+                 CSTR("00"));
+  test_exception("End of input while parsing format-spec numeric value",
+                 CSTR("1"));
+  static_assert(std::__format::__number_max == 999'999'999,
+                "Update the assert and the test.");
+  test_exception("Format-spec numeric value too large", CSTR("1000000000}"));
+
+  test_exception("End of input while parsing format-spec arg-id", CSTR("{"));
+  test_exception("Format-spec arg-id should terminate at a '}'", CSTR("{0"));
+  test_exception("Format-spec arg-id starts with an invalid character",
+                 CSTR("{a"));
+  test_exception("End of input while parsing format-spec numeric value",
+                 CSTR("{1"));
+  test_exception("End of input while parsing format-spec numeric value",
+                 CSTR("{9"));
+  test_exception("Format-spec arg-id shouldn't contain its own format-spec",
+                 CSTR("{9:"));
+  test_exception("Format-spec arg-id should terminate at a '}'", CSTR("{9a"));
+  test_exception("End of input while parsing format-spec arg-id", CSTR("{1}"));
+
+  static_assert(std::__format::__number_max == 999'999'999,
+                "Update the assert and the test.");
+  test_exception("Format-spec numeric value too large", CSTR("{1000000000}"));
+}
+
+constexpr bool test() {
+  test<char>();
+  test<wchar_t>();
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+  test<char8_t>();
+#endif
+#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
+  test<char16_t>();
+  test<char32_t>();
+#endif
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_zero_padding.pass.cpp b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_zero_padding.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.string/format.string.std/std_format_spec_zero_padding.pass.cpp
@@ -0,0 +1,79 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// <format>
+
+// [format.string.std] Standard format specifiers
+// - Tests parsing of the zero-padding.
+
+#include <format>
+#include <cassert>
+#include <iostream>
+
+#include "test_macros.h"
+#include "make_string.h"
+
+#define CSTR(S) MAKE_CSTRING(CharT, S)
+
+using namespace std::__format_spec;
+
+template <class CharT>
+using parser = __parser_std<CharT, __parser_no_precision, __parser_no_sign,
+                            __parser_no_alternate_form, __parser_zero_padding,
+                            __parser_no_locale_specific_form>;
+
+#include "test_exception.h" // requires parser
+
+template <class CharT>
+constexpr void test(bool expected, size_t size, const CharT* fmt) {
+  std::basic_format_parse_context<CharT> parse_ctx(fmt);
+  auto begin = parse_ctx.begin();
+  parser<CharT> parser;
+  auto it = parser.parse(parse_ctx);
+
+  assert(begin + size == it);
+  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 == expected);
+  assert(parser.__width == 0);
+  assert(parser.__width_as_arg == false);
+  assert(parser.__locale_specific_form == false);
+  assert(parser.__type == _Flags::_Type::__default);
+}
+
+template <class CharT>
+constexpr void test() {
+  test(false, 0, CSTR("}"));
+  test(true, 1, CSTR("0}"));
+
+  test_exception("End of input while parsing format-spec zero-padding",
+                 CSTR("0"));
+}
+
+constexpr bool test() {
+  test<char>();
+  test<wchar_t>();
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+  test<char8_t>();
+#endif
+#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
+  test<char16_t>();
+  test<char32_t>();
+#endif
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/format/format.string/format.string.std/test_exception.h b/libcxx/test/std/utilities/format/format.string/format.string.std/test_exception.h
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.string/format.string.std/test_exception.h
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_TEST_STD_UTILITIES_FORMAT_FORMAT_STRING_FORMAT_STRING_STD_TEST_EXCEPTION_H
+#define _LIBCPP_TEST_STD_UTILITIES_FORMAT_FORMAT_STRING_FORMAT_STRING_STD_TEST_EXCEPTION_H
+
+// Helper header for the tests in this directory.
+// Note the header isn't freestanding.
+
+namespace detail {
+template <class CharT>
+void test_exception(std::string_view what, const CharT* fmt) {
+  try {
+    std::basic_format_parse_context<CharT> parse_ctx(fmt);
+    (void)parser<CharT>{}.parse(parse_ctx);
+    if constexpr (std::same_as<CharT, char>)
+      std::cerr << "\nFormat string   " << fmt
+                << "\nDidn't throw an exception.\n";
+    assert(false);
+  } catch (std::format_error& e) {
+    if constexpr (std::same_as<CharT, char>)
+      if (e.what() != what)
+        std::cerr << "\nFormat string   " << fmt << "\nExpected exception "
+                  << what << "\nActual exception   " << e.what() << '\n';
+    assert(e.what() == what);
+    return;
+  }
+
+  assert(false);
+}
+} // namespace detail
+
+/**
+ *  Wrapper for the exception tests.
+ *
+ *  When using the real function directly during in a constexpr test and add
+ *  the `std::is_constant_evaluated()` test there the compilation fails. This
+ *  happens since assert calls the non-constexpr function '__assert_fail'.
+ *  Solve this issue with an layer of indirection.
+ */
+template <class CharT>
+constexpr void test_exception(std::string_view what, const CharT* fmt) {
+#ifndef _LIBCPP_NO_EXCEPTIONS
+  if (!std::is_constant_evaluated())
+    detail::test_exception(what, fmt);
+#else
+  (void)what;
+  (void)fmt;
+#endif
+}
+
+#endif // _LIBCPP_TEST_STD_UTILITIES_FORMAT_FORMAT_STRING_FORMAT_STRING_STD_TEST_EXCEPTION_H