[libcxx-commits] [libcxx] af5fc4b - [libc++][format] range-default-formatter for map

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jan 19 11:55:58 PST 2023


Author: Mark de Wever
Date: 2023-01-19T20:55:52+01:00
New Revision: af5fc4b4d827ab00e20323b6025b458edca46906

URL: https://github.com/llvm/llvm-project/commit/af5fc4b4d827ab00e20323b6025b458edca46906
DIFF: https://github.com/llvm/llvm-project/commit/af5fc4b4d827ab00e20323b6025b458edca46906.diff

LOG: [libc++][format] range-default-formatter for map

Implements the range-default-formatter specialization range_format::map.

Implements parts of
- P2286R8 Formatting Ranges
- P2585R0 Improving default container formatting

Depends on D140653

Reviewed By: ldionne, #libc

Differential Revision: https://reviews.llvm.org/D140801

Added: 
    libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.format.pass.cpp
    libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.tests.h
    libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.vformat.pass.cpp
    libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.pass.cpp
    libcxx/test/std/utilities/format/format.range/format.range.fmtmap/parse.pass.cpp

Modified: 
    libcxx/docs/Status/FormatPaper.csv
    libcxx/include/__format/range_default_formatter.h
    libcxx/include/__format/range_formatter.h
    libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.pass.cpp
    libcxx/test/std/containers/container.adaptors/container.adaptors.format/parse.pass.cpp
    libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.pass.cpp
    libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/parse.pass.cpp
    libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
    libcxx/test/std/utilities/format/format.tuple/format.pass.cpp
    libcxx/test/std/utilities/format/format.tuple/parse.pass.cpp
    libcxx/test/std/utilities/format/format.tuple/set_brackets.pass.cpp
    libcxx/test/std/utilities/format/format.tuple/set_separator.pass.cpp
    libcxx/test/support/format.functions.common.h

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/FormatPaper.csv b/libcxx/docs/Status/FormatPaper.csv
index d80346e9d68c5..bee4e6743ea2a 100644
--- a/libcxx/docs/Status/FormatPaper.csv
+++ b/libcxx/docs/Status/FormatPaper.csv
@@ -31,7 +31,9 @@ Section,Description,Dependencies,Assignee,Status,First released version
 `[format.syn] <https://wg21.link/format.syn>`_,"Concept ``formattable``",,Mark de Wever,|Complete|, Clang 16
 `[format.string.std] <https://wg21.link/format.string.std>`_,"std-format-spec ``type`` debug",,Mark de Wever,|Complete|,Clang 16
 `[format.range] <https://wg21.link/format.range>`_,"Formatting for ranges: sequences",,Mark de Wever,|Complete|,Clang 16
-`[format.range] <https://wg21.link/format.range>`_,"Formatting for ranges: associative",,Mark de Wever,,
+`[format.range.fmtmap] <https://wg21.link/format.range.fmtmap>`_,"Formatting for ranges: map",,Mark de Wever,|Complete|,Clang 16
+`[format.range.fmtset] <https://wg21.link/format.range.fmtset>`_,"Formatting for ranges: set",,Mark de Wever,|In Progress|,
+`[format.range.fmtstr] <https://wg21.link/format.range.fmtstr>`_,"Formatting for ranges: strings",,Mark de Wever,|In Progress|,
 `[format.range] <https://wg21.link/format.range>`_,"Formatting for ranges: container adaptors",,Mark de Wever,|Complete|,Clang 16
 `[format.range] <https://wg21.link/format.range>`_,"Formatting for ranges: ``pair`` and ``tuple``",,Mark de Wever,|Complete|,Clang 16
 `[format.range] <https://wg21.link/format.range>`_,"Formatting for ranges: ``vector<bool>``",,Mark de Wever,|Complete|,Clang 16

diff  --git a/libcxx/include/__format/range_default_formatter.h b/libcxx/include/__format/range_default_formatter.h
index 652c021277664..6b0793676433f 100644
--- a/libcxx/include/__format/range_default_formatter.h
+++ b/libcxx/include/__format/range_default_formatter.h
@@ -15,6 +15,7 @@
 #endif
 
 #include <__availability>
+#include <__chrono/statically_widen.h>
 #include <__concepts/same_as.h>
 #include <__config>
 #include <__format/concepts.h>
@@ -132,7 +133,30 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatte
 
 template <ranges::input_range _Rp, class _CharT>
 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter<range_format::map, _Rp, _CharT> {
-  __range_default_formatter() = delete; // TODO FMT Implement
+private:
+  using __maybe_const_map = __fmt_maybe_const<_Rp, _CharT>;
+  using __element_type    = remove_cvref_t<ranges::range_reference_t<__maybe_const_map>>;
+  range_formatter<__element_type, _CharT> __underlying_;
+
+public:
+  _LIBCPP_HIDE_FROM_ABI constexpr __range_default_formatter()
+    requires(__fmt_pair_like<__element_type>)
+  {
+    __underlying_.set_brackets(_LIBCPP_STATICALLY_WIDEN(_CharT, "{"), _LIBCPP_STATICALLY_WIDEN(_CharT, "}"));
+    __underlying_.underlying().set_brackets({}, {});
+    __underlying_.underlying().set_separator(_LIBCPP_STATICALLY_WIDEN(_CharT, ": "));
+  }
+
+  template <class _ParseContext>
+  _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) {
+    return __underlying_.parse(__ctx);
+  }
+
+  template <class _FormatContext>
+  _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator
+  format(__maybe_const_map& __range, _FormatContext& __ctx) const {
+    return __underlying_.format(__range, __ctx);
+  }
 };
 
 template <ranges::input_range _Rp, class _CharT>

diff  --git a/libcxx/include/__format/range_formatter.h b/libcxx/include/__format/range_formatter.h
index f2a4342e2ec66..6188842a6eb48 100644
--- a/libcxx/include/__format/range_formatter.h
+++ b/libcxx/include/__format/range_formatter.h
@@ -132,7 +132,10 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT range_formatter {
     // characters. Which means there will be
     //   (n - 1) * 2 + 1 + 1 = n * 2 character
     // So estimate 8 times the range size as buffer.
-    __format::__retarget_buffer<_CharT> __buffer{8 * ranges::size(__range)};
+    std::size_t __capacity_hint = 0;
+    if constexpr (std::ranges::sized_range<_Rp>)
+      __capacity_hint = 8 * ranges::size(__range);
+    __format::__retarget_buffer<_CharT> __buffer{__capacity_hint};
     basic_format_context<typename __format::__retarget_buffer<_CharT>::__iterator, _CharT> __c{
         __buffer.__make_output_iterator(), __ctx};
 

diff  --git a/libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.pass.cpp b/libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.pass.cpp
index 901c63a008486..8950ece9a57e8 100644
--- a/libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.pass.cpp
@@ -8,6 +8,9 @@
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
 // UNSUPPORTED: libcpp-has-no-incomplete-format
 
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
 // This test requires the dylib support introduced in D92214.
 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}}
 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}}

diff  --git a/libcxx/test/std/containers/container.adaptors/container.adaptors.format/parse.pass.cpp b/libcxx/test/std/containers/container.adaptors/container.adaptors.format/parse.pass.cpp
index 11f08371b5ead..b620279d76079 100644
--- a/libcxx/test/std/containers/container.adaptors/container.adaptors.format/parse.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/container.adaptors.format/parse.pass.cpp
@@ -8,6 +8,9 @@
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
 // UNSUPPORTED: libcpp-has-no-incomplete-format
 
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
 // This test requires the dylib support introduced in D92214.
 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}}
 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}}

diff  --git a/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.pass.cpp
index bb29081dfb898..acb517a068f4c 100644
--- a/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.pass.cpp
@@ -8,6 +8,9 @@
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
 // UNSUPPORTED: libcpp-has-no-incomplete-format
 
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
 // This test requires the dylib support introduced in D92214.
 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}}
 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}}

diff  --git a/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/parse.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/parse.pass.cpp
index c711e25d1cd06..c099cfe1e5965 100644
--- a/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/parse.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/parse.pass.cpp
@@ -8,6 +8,9 @@
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
 // UNSUPPORTED: libcpp-has-no-incomplete-format
 
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
 // This test requires the dylib support introduced in D92214.
 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}}
 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}}

diff  --git a/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp b/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
index cef22792f3aa6..35c355840de6e 100644
--- a/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
@@ -211,14 +211,14 @@ void test_P2286() {
   assert_is_formattable<std::list<int>, CharT>();
 
   assert_is_not_formattable<std::set<int>, CharT>();
-  assert_is_not_formattable<std::map<int, int>, CharT>();
+  assert_is_formattable<std::map<int, int>, CharT>();
   assert_is_not_formattable<std::multiset<int>, CharT>();
-  assert_is_not_formattable<std::multimap<int, int>, CharT>();
+  assert_is_formattable<std::multimap<int, int>, CharT>();
 
   assert_is_not_formattable<std::unordered_set<int>, CharT>();
-  assert_is_not_formattable<std::unordered_map<int, int>, CharT>();
+  assert_is_formattable<std::unordered_map<int, int>, CharT>();
   assert_is_not_formattable<std::unordered_multiset<int>, CharT>();
-  assert_is_not_formattable<std::unordered_multimap<int, int>, CharT>();
+  assert_is_formattable<std::unordered_multimap<int, int>, CharT>();
 
   assert_is_formattable<std::stack<int>, CharT>();
   assert_is_formattable<std::queue<int>, CharT>();

diff  --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.format.pass.cpp b/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.format.pass.cpp
new file mode 100644
index 0000000000000..b2e65ecec084f
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.format.pass.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+// 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, c++20
+// UNSUPPORTED: libcpp-has-no-incomplete-format
+
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
+// This test requires the dylib support introduced in D92214.
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}}
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}}
+
+// <format>
+
+// template<ranges::input_range R, class charT>
+//   struct range-default-formatter<range_format::map, R, charT>
+//
+// template<class... Args>
+//   string format(format_string<Args...> fmt, Args&&... args);
+// template<class... Args>
+//   wstring format(wformat_string<Args...> fmt, Args&&... args);
+
+#include <format>
+#include <cassert>
+
+#include "format.functions.tests.h"
+#include "test_format_string.h"
+#include "test_macros.h"
+#include "assert_macros.h"
+
+auto test = []<class CharT, class... Args>(
+                std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) {
+  std::basic_string<CharT> out = std::format(fmt, std::forward<Args>(args)...);
+  TEST_REQUIRE(
+      out == expected,
+      test_concat_message("\nFormat string   ", fmt, "\nExpected output ", expected, "\nActual output   ", out, '\n'));
+};
+
+auto test_exception = []<class CharT, class... Args>(std::string_view, std::basic_string_view<CharT>, Args&&...) {
+  // After P2216 most exceptions thrown by std::format become ill-formed.
+  // Therefore this tests does nothing.
+};
+
+int main(int, char**) {
+  format_tests<char>(test, test_exception);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  format_tests<wchar_t>(test, test_exception);
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.tests.h b/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.tests.h
new file mode 100644
index 0000000000000..005a2bd36b0a9
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.tests.h
@@ -0,0 +1,841 @@
+//===----------------------------------------------------------------------===//
+// 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 TEST_STD_UTILITIES_FORMAT_FORMAT_RANGE_FORMAT_RANGE_FMTMAP_FORMAT_FUNCTIONS_TESTS_H
+#define TEST_STD_UTILITIES_FORMAT_FORMAT_RANGE_FORMAT_RANGE_FMTMAP_FORMAT_FUNCTIONS_TESTS_H
+
+#include <algorithm>
+#include <format>
+#include <map>
+#include <unordered_map>
+
+#include "format.functions.common.h"
+#include "make_string.h"
+#include "platform_support.h" // locale name macros
+#include "test_macros.h"
+
+//
+// Char
+//
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_char(TestFunction check, ExceptionTest check_exception) {
+  std::map<CharT, CharT> input{{CharT('a'), CharT('A')}, {CharT('c'), CharT('C')}, {CharT('b'), CharT('B')}};
+
+  check(SV("{a: A, b: B, c: C}"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{a: A, b: B, c: C}     "), SV("{:23}"), input);
+  check(SV("{a: A, b: B, c: C}*****"), SV("{:*<23}"), input);
+  check(SV("__{a: A, b: B, c: C}___"), SV("{:_^23}"), input);
+  check(SV("#####{a: A, b: B, c: C}"), SV("{:#>23}"), input);
+
+  check(SV("{a: A, b: B, c: C}     "), SV("{:{}}"), input, 23);
+  check(SV("{a: A, b: B, c: C}*****"), SV("{:*<{}}"), input, 23);
+  check(SV("__{a: A, b: B, c: C}___"), SV("{:_^{}}"), input, 23);
+  check(SV("#####{a: A, b: B, c: C}"), SV("{:#>{}}"), input, 23);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
+
+  // *** n
+  check(SV("__a: A, b: B, c: C___"), SV("{:_^21n}"), input);
+
+  // *** type ***
+  check(SV("__{a: A, b: B, c: C}___"), SV("{:_^23m}"), input); // the m type does the same as the default.
+  check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
+  check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
+
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
+    check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
+
+  // ***** Only underlying has a format-spec
+
+  check(SV("{'a': 'A'     , 'b': 'B'     , 'c': 'C'     }"), SV("{::13}"), input);
+  check(SV("{'a': 'A'*****, 'b': 'B'*****, 'c': 'C'*****}"), SV("{::*<13}"), input);
+  check(SV("{__'a': 'A'___, __'b': 'B'___, __'c': 'C'___}"), SV("{::_^13}"), input);
+  check(SV("{#####'a': 'A', #####'b': 'B', #####'c': 'C'}"), SV("{::#>13}"), input);
+
+  check(SV("{'a': 'A'     , 'b': 'B'     , 'c': 'C'     }"), SV("{::{}}"), input, 13);
+  check(SV("{'a': 'A'*****, 'b': 'B'*****, 'c': 'C'*****}"), SV("{::*<{}}"), input, 13);
+  check(SV("{__'a': 'A'___, __'b': 'B'___, __'c': 'C'___}"), SV("{::_^{}}"), input, 13);
+  check(SV("{#####'a': 'A', #####'b': 'B', #####'c': 'C'}"), SV("{::#>{}}"), input, 13);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:::<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::}<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::{<}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::+}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:: }"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
+
+  // *** type ***
+  check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{::m}"), input);
+  check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{::n}"), input);
+  check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
+  check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
+
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
+    check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
+
+  // ***** Both have a format-spec
+  check(SV("^^{###'a': 'A', ###'b': 'B', ###'c': 'C'}^^^"), SV("{:^^44:#>11}"), input);
+  check(SV("^^{###'a': 'A', ###'b': 'B', ###'c': 'C'}^^^"), SV("{:^^{}:#>11}"), input, 44);
+  check(SV("^^{###'a': 'A', ###'b': 'B', ###'c': 'C'}^^^"), SV("{:^^{}:#>{}}"), input, 44, 11);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>11}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>{}}"), input, 44);
+}
+
+//
+// char -> wchar_t
+//
+
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+template <class TestFunction, class ExceptionTest>
+void test_char_to_wchar(TestFunction check, ExceptionTest check_exception) {
+  std::map<char, char> input{{'a', 'A'}, {'c', 'C'}, {'b', 'B'}};
+
+  using CharT = wchar_t;
+  check(SV("{a: A, b: B, c: C}"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{a: A, b: B, c: C}     "), SV("{:23}"), input);
+  check(SV("{a: A, b: B, c: C}*****"), SV("{:*<23}"), input);
+  check(SV("__{a: A, b: B, c: C}___"), SV("{:_^23}"), input);
+  check(SV("#####{a: A, b: B, c: C}"), SV("{:#>23}"), input);
+
+  check(SV("{a: A, b: B, c: C}     "), SV("{:{}}"), input, 23);
+  check(SV("{a: A, b: B, c: C}*****"), SV("{:*<{}}"), input, 23);
+  check(SV("__{a: A, b: B, c: C}___"), SV("{:_^{}}"), input, 23);
+  check(SV("#####{a: A, b: B, c: C}"), SV("{:#>{}}"), input, 23);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
+
+  // *** n
+  check(SV("__a: A, b: B, c: C___"), SV("{:_^21n}"), input);
+
+  // *** type ***
+  check(SV("__{a: A, b: B, c: C}___"), SV("{:_^23m}"), input); // the m type does the same as the default.
+  check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
+  check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
+
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
+    check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
+
+  // ***** Only underlying has a format-spec
+  check(SV("{'a': 'A'     , 'b': 'B'     , 'c': 'C'     }"), SV("{::13}"), input);
+  check(SV("{'a': 'A'*****, 'b': 'B'*****, 'c': 'C'*****}"), SV("{::*<13}"), input);
+  check(SV("{__'a': 'A'___, __'b': 'B'___, __'c': 'C'___}"), SV("{::_^13}"), input);
+  check(SV("{#####'a': 'A', #####'b': 'B', #####'c': 'C'}"), SV("{::#>13}"), input);
+
+  check(SV("{'a': 'A'     , 'b': 'B'     , 'c': 'C'     }"), SV("{::{}}"), input, 13);
+  check(SV("{'a': 'A'*****, 'b': 'B'*****, 'c': 'C'*****}"), SV("{::*<{}}"), input, 13);
+  check(SV("{__'a': 'A'___, __'b': 'B'___, __'c': 'C'___}"), SV("{::_^{}}"), input, 13);
+  check(SV("{#####'a': 'A', #####'b': 'B', #####'c': 'C'}"), SV("{::#>{}}"), input, 13);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:::<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::}<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::{<}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::+}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:: }"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
+
+  // *** type ***
+  check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{::m}"), input);
+  check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{::n}"), input);
+  check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
+  check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
+
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
+    check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
+
+  // ***** Both have a format-spec
+  check(SV("^^{###'a': 'A', ###'b': 'B', ###'c': 'C'}^^^"), SV("{:^^44:#>11}"), input);
+  check(SV("^^{###'a': 'A', ###'b': 'B', ###'c': 'C'}^^^"), SV("{:^^{}:#>11}"), input, 44);
+  check(SV("^^{###'a': 'A', ###'b': 'B', ###'c': 'C'}^^^"), SV("{:^^{}:#>{}}"), input, 44, 11);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>11}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>{}}"), input, 44);
+}
+#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
+
+//
+// Bool
+//
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_bool(TestFunction check, ExceptionTest check_exception) {
+  // duplicates are stored in order of insertion
+  std::multimap<bool, int> input{{true, 42}, {false, 0}, {true, 1}};
+
+  check(SV("{false: 0, true: 42, true: 1}"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{false: 0, true: 42, true: 1}     "), SV("{:34}"), input);
+  check(SV("{false: 0, true: 42, true: 1}*****"), SV("{:*<34}"), input);
+  check(SV("__{false: 0, true: 42, true: 1}___"), SV("{:_^34}"), input);
+  check(SV("#####{false: 0, true: 42, true: 1}"), SV("{:#>34}"), input);
+
+  check(SV("{false: 0, true: 42, true: 1}     "), SV("{:{}}"), input, 34);
+  check(SV("{false: 0, true: 42, true: 1}*****"), SV("{:*<{}}"), input, 34);
+  check(SV("__{false: 0, true: 42, true: 1}___"), SV("{:_^{}}"), input, 34);
+  check(SV("#####{false: 0, true: 42, true: 1}"), SV("{:#>{}}"), input, 34);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
+
+  // *** n
+  check(SV("__false: 0, true: 42, true: 1___"), SV("{:_^32n}"), input);
+
+  // *** type ***
+  check(SV("__{false: 0, true: 42, true: 1}___"), SV("{:_^34m}"), input); // the m type does the same as the default.
+  check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
+  check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
+
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
+    check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
+
+  // ***** Only underlying has a format-spec
+  check(SV("{false: 0  , true: 42  , true: 1   }"), SV("{::10}"), input);
+  check(SV("{false: 0**, true: 42**, true: 1***}"), SV("{::*<10}"), input);
+  check(SV("{_false: 0_, _true: 42_, _true: 1__}"), SV("{::_^10}"), input);
+  check(SV("{##false: 0, ##true: 42, ###true: 1}"), SV("{::#>10}"), input);
+
+  check(SV("{false: 0  , true: 42  , true: 1   }"), SV("{::{}}"), input, 10);
+  check(SV("{false: 0**, true: 42**, true: 1***}"), SV("{::*<{}}"), input, 10);
+  check(SV("{_false: 0_, _true: 42_, _true: 1__}"), SV("{::_^{}}"), input, 10);
+  check(SV("{##false: 0, ##true: 42, ###true: 1}"), SV("{::#>{}}"), input, 10);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:::<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::}<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::{<}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::+}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:: }"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
+
+  // *** type ***
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>(""))
+    check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
+
+  // ***** Both have a format-spec
+  check(SV("^^{##false: 0, ##true: 42, ###true: 1}^^^"), SV("{:^^41:#>10}"), input);
+  check(SV("^^{##false: 0, ##true: 42, ###true: 1}^^^"), SV("{:^^{}:#>10}"), input, 41);
+  check(SV("^^{##false: 0, ##true: 42, ###true: 1}^^^"), SV("{:^^{}:#>{}}"), input, 41, 10);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>10}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>{}}"), input, 41);
+}
+
+//
+// Integral
+//
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
+  check(SV("{-42: 42, 1: -1, 42: -42}"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{-42: 42, 1: -1, 42: -42}     "), SV("{:30}"), input);
+  check(SV("{-42: 42, 1: -1, 42: -42}*****"), SV("{:*<30}"), input);
+  check(SV("__{-42: 42, 1: -1, 42: -42}___"), SV("{:_^30}"), input);
+  check(SV("#####{-42: 42, 1: -1, 42: -42}"), SV("{:#>30}"), input);
+
+  check(SV("{-42: 42, 1: -1, 42: -42}     "), SV("{:{}}"), input, 30);
+  check(SV("{-42: 42, 1: -1, 42: -42}*****"), SV("{:*<{}}"), input, 30);
+  check(SV("__{-42: 42, 1: -1, 42: -42}___"), SV("{:_^{}}"), input, 30);
+  check(SV("#####{-42: 42, 1: -1, 42: -42}"), SV("{:#>{}}"), input, 30);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
+
+  // *** n
+  check(SV("__-42: 42, 1: -1, 42: -42___"), SV("{:_^28n}"), input);
+
+  // *** type ***
+  check(SV("__{-42: 42, 1: -1, 42: -42}___"), SV("{:_^30m}"), input); // the m type does the same as the default.
+  check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
+  check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
+
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
+    check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
+
+  // ***** Only underlying has a format-spec
+  check(SV("{-42: 42   , 1: -1     , 42: -42   }"), SV("{::10}"), input);
+  check(SV("{-42: 42***, 1: -1*****, 42: -42***}"), SV("{::*<10}"), input);
+  check(SV("{_-42: 42__, __1: -1___, _42: -42__}"), SV("{::_^10}"), input);
+  check(SV("{###-42: 42, #####1: -1, ###42: -42}"), SV("{::#>10}"), input);
+
+  check(SV("{-42: 42   , 1: -1     , 42: -42   }"), SV("{::{}}"), input, 10);
+  check(SV("{-42: 42***, 1: -1*****, 42: -42***}"), SV("{::*<{}}"), input, 10);
+  check(SV("{_-42: 42__, __1: -1___, _42: -42__}"), SV("{::_^{}}"), input, 10);
+  check(SV("{###-42: 42, #####1: -1, ###42: -42}"), SV("{::#>{}}"), input, 10);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:::<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::}<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::{<}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::+}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:: }"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
+
+  // *** type ***
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>(""))
+    check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
+
+  // ***** Both have a format-spec
+  check(SV("^^{###-42: 42, #####1: -1, ###42: -42}^^^"), SV("{:^^41:#>10}"), input);
+  check(SV("^^{###-42: 42, #####1: -1, ###42: -42}^^^"), SV("{:^^{}:#>10}"), input, 41);
+  check(SV("^^{###-42: 42, #####1: -1, ###42: -42}^^^"), SV("{:^^{}:#>{}}"), input, 41, 10);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>10}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>{}}"), input, 41);
+}
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_int(TestFunction check, ExceptionTest check_exception) {
+  test_int<CharT>(check, check_exception, std::map<int, int>{{1, -1}, {42, -42}, {-42, 42}});
+}
+
+//
+// Floating point
+//
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_floating_point(TestFunction check, ExceptionTest check_exception) {
+  std::map<double, double> input{{1.0, -1.0}, {-42, 42}};
+
+  check(SV("{-42: 42, 1: -1}"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{-42: 42, 1: -1}     "), SV("{:21}"), input);
+  check(SV("{-42: 42, 1: -1}*****"), SV("{:*<21}"), input);
+  check(SV("__{-42: 42, 1: -1}___"), SV("{:_^21}"), input);
+  check(SV("#####{-42: 42, 1: -1}"), SV("{:#>21}"), input);
+
+  check(SV("{-42: 42, 1: -1}     "), SV("{:{}}"), input, 21);
+  check(SV("{-42: 42, 1: -1}*****"), SV("{:*<{}}"), input, 21);
+  check(SV("__{-42: 42, 1: -1}___"), SV("{:_^{}}"), input, 21);
+  check(SV("#####{-42: 42, 1: -1}"), SV("{:#>{}}"), input, 21);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
+
+  // *** n
+  check(SV("__-42: 42, 1: -1___"), SV("{:_^19n}"), input);
+
+  // *** type ***
+  check(SV("__{-42: 42, 1: -1}___"), SV("{:_^21m}"), input); // the m type does the same as the default.
+  check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
+  check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
+
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
+    check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
+
+  // ***** Only underlying has a format-spec
+  check(SV("{-42: 42   , 1: -1     }"), SV("{::10}"), input);
+  check(SV("{-42: 42***, 1: -1*****}"), SV("{::*<10}"), input);
+  check(SV("{_-42: 42__, __1: -1___}"), SV("{::_^10}"), input);
+  check(SV("{###-42: 42, #####1: -1}"), SV("{::#>10}"), input);
+
+  check(SV("{-42: 42   , 1: -1     }"), SV("{::{}}"), input, 10);
+  check(SV("{-42: 42***, 1: -1*****}"), SV("{::*<{}}"), input, 10);
+  check(SV("{_-42: 42__, __1: -1___}"), SV("{::_^{}}"), input, 10);
+  check(SV("{###-42: 42, #####1: -1}"), SV("{::#>{}}"), input, 10);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:::<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::}<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::{<}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::+}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:: }"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
+
+  // *** type ***
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>(""))
+    check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
+
+  // ***** Both have a format-spec
+  check(SV("^^{###-42: 42, #####1: -1}^^^"), SV("{:^^29:#>10}"), input);
+  check(SV("^^{###-42: 42, #####1: -1}^^^"), SV("{:^^{}:#>10}"), input, 29);
+  check(SV("^^{###-42: 42, #####1: -1}^^^"), SV("{:^^{}:#>{}}"), input, 29, 10);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>10}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>{}}"), input, 29);
+}
+
+//
+// Pointer
+//
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_pointer(TestFunction check, ExceptionTest check_exception) {
+  std::unordered_map<const void*, std::nullptr_t> input{{0, 0}};
+
+  check(SV("{0x0: 0x0}"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{0x0: 0x0}     "), SV("{:15}"), input);
+  check(SV("{0x0: 0x0}*****"), SV("{:*<15}"), input);
+  check(SV("__{0x0: 0x0}___"), SV("{:_^15}"), input);
+  check(SV("#####{0x0: 0x0}"), SV("{:#>15}"), input);
+
+  check(SV("{0x0: 0x0}     "), SV("{:{}}"), input, 15);
+  check(SV("{0x0: 0x0}*****"), SV("{:*<{}}"), input, 15);
+  check(SV("__{0x0: 0x0}___"), SV("{:_^{}}"), input, 15);
+  check(SV("#####{0x0: 0x0}"), SV("{:#>{}}"), input, 15);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
+
+  // *** n
+  check(SV("__0x0: 0x0___"), SV("{:_^13n}"), input);
+
+  // *** type ***
+  check(SV("__{0x0: 0x0}___"), SV("{:_^15m}"), input); // the m type does the same as the default.
+  check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
+  check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
+
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
+    check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
+
+  // ***** Only underlying has a format-spec
+  check(SV("{0x0: 0x0     }"), SV("{::13}"), input);
+  check(SV("{0x0: 0x0*****}"), SV("{::*<13}"), input);
+  check(SV("{__0x0: 0x0___}"), SV("{::_^13}"), input);
+  check(SV("{#####0x0: 0x0}"), SV("{::#>13}"), input);
+
+  check(SV("{0x0: 0x0     }"), SV("{::{}}"), input, 13);
+  check(SV("{0x0: 0x0*****}"), SV("{::*<{}}"), input, 13);
+  check(SV("{__0x0: 0x0___}"), SV("{::_^{}}"), input, 13);
+  check(SV("{#####0x0: 0x0}"), SV("{::#>{}}"), input, 13);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:::<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::}<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::{<}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::+}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:: }"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
+
+  // *** type ***
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>(""))
+    check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
+
+  // ***** Both have a format-spec
+  check(SV("^^{###0x0: 0x0}^^^"), SV("{:^^18:#>11}"), input);
+  check(SV("^^{###0x0: 0x0}^^^"), SV("{:^^{}:#>11}"), input, 18);
+  check(SV("^^{###0x0: 0x0}^^^"), SV("{:^^{}:#>{}}"), input, 18, 11);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>11}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>{}}"), input, 18);
+}
+
+//
+// String
+//
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_string(TestFunction check, ExceptionTest check_exception) {
+  std::map<std::basic_string<CharT>, std::basic_string<CharT>> input{
+      {STR("hello"), STR("HELLO")}, {STR("world"), STR("WORLD")}};
+
+  check(SV(R"({hello: HELLO, world: WORLD})"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV(R"({hello: HELLO, world: WORLD}     )"), SV("{:33}"), input);
+  check(SV(R"({hello: HELLO, world: WORLD}*****)"), SV("{:*<33}"), input);
+  check(SV(R"(__{hello: HELLO, world: WORLD}___)"), SV("{:_^33}"), input);
+  check(SV(R"(#####{hello: HELLO, world: WORLD})"), SV("{:#>33}"), input);
+
+  check(SV(R"({hello: HELLO, world: WORLD}     )"), SV("{:{}}"), input, 33);
+  check(SV(R"({hello: HELLO, world: WORLD}*****)"), SV("{:*<{}}"), input, 33);
+  check(SV(R"(__{hello: HELLO, world: WORLD}___)"), SV("{:_^{}}"), input, 33);
+  check(SV(R"(#####{hello: HELLO, world: WORLD})"), SV("{:#>{}}"), input, 33);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
+
+  // *** n
+  check(SV(R"(__hello: HELLO, world: WORLD___)"), SV("{:_^31n}"), input);
+
+  // *** type ***
+  check(SV(R"(__{hello: HELLO, world: WORLD}___)"), SV("{:_^33m}"), input);
+  check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
+  check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
+
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
+    check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
+
+  // ***** Only underlying has a format-spec
+  check(SV(R"({"hello": "HELLO"     , "world": "WORLD"     })"), SV("{::21}"), input);
+  check(SV(R"({"hello": "HELLO"*****, "world": "WORLD"*****})"), SV("{::*<21}"), input);
+  check(SV(R"({__"hello": "HELLO"___, __"world": "WORLD"___})"), SV("{::_^21}"), input);
+  check(SV(R"({#####"hello": "HELLO", #####"world": "WORLD"})"), SV("{::#>21}"), input);
+
+  check(SV(R"({"hello": "HELLO"     , "world": "WORLD"     })"), SV("{::{}}"), input, 21);
+  check(SV(R"({"hello": "HELLO"*****, "world": "WORLD"*****})"), SV("{::*<{}}"), input, 21);
+  check(SV(R"({__"hello": "HELLO"___, __"world": "WORLD"___})"), SV("{::_^{}}"), input, 21);
+  check(SV(R"({#####"hello": "HELLO", #####"world": "WORLD"})"), SV("{::#>{}}"), input, 21);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:::<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::}<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::{<}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::+}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:: }"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
+
+  // *** type ***
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>(""))
+    check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
+
+  // ***** Both have a format-spec
+
+  check(SV(R"(^^{#####"hello": "HELLO", #####"world": "WORLD"}^^^)"), SV("{:^^51:#>21}"), input);
+  check(SV(R"(^^{#####"hello": "HELLO", #####"world": "WORLD"}^^^)"), SV("{:^^{}:#>21}"), input, 51);
+  check(SV(R"(^^{#####"hello": "HELLO", #####"world": "WORLD"}^^^)"), SV("{:^^{}:#>{}}"), input, 51, 21);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>21}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>{}}"), input, 51);
+}
+
+//
+// Handle
+//
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_status(TestFunction check, ExceptionTest check_exception) {
+  std::unordered_multimap<status, status> input{{status::foobar, status::foo}, {status::foobar, status::bar}};
+
+  check(SV("{0xaa55: 0xaaaa, 0xaa55: 0x5555}"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{0xaa55: 0xaaaa, 0xaa55: 0x5555}     "), SV("{:37}"), input);
+  check(SV("{0xaa55: 0xaaaa, 0xaa55: 0x5555}*****"), SV("{:*<37}"), input);
+  check(SV("__{0xaa55: 0xaaaa, 0xaa55: 0x5555}___"), SV("{:_^37}"), input);
+  check(SV("#####{0xaa55: 0xaaaa, 0xaa55: 0x5555}"), SV("{:#>37}"), input);
+
+  check(SV("{0xaa55: 0xaaaa, 0xaa55: 0x5555}     "), SV("{:{}}"), input, 37);
+  check(SV("{0xaa55: 0xaaaa, 0xaa55: 0x5555}*****"), SV("{:*<{}}"), input, 37);
+  check(SV("__{0xaa55: 0xaaaa, 0xaa55: 0x5555}___"), SV("{:_^{}}"), input, 37);
+  check(SV("#####{0xaa55: 0xaaaa, 0xaa55: 0x5555}"), SV("{:#>{}}"), input, 37);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
+
+  // *** n
+  check(SV("__0xaa55: 0xaaaa, 0xaa55: 0x5555___"), SV("{:_^35n}"), input);
+
+  // *** type ***
+  check(SV("__{0xaa55: 0xaaaa, 0xaa55: 0x5555}___"), SV("{:_^37}"), input); // the m type does the same as the default.
+  check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
+  check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
+
+  // Underlying can't have a format-spec
+}
+
+//
+// Adaptor
+//
+
+class adaptor {
+  using adaptee = std::map<int, int>;
+
+public:
+  using key_type    = typename adaptee::key_type;
+  using mapped_type = typename adaptee::mapped_type;
+  using iterator    = typename adaptee::iterator;
+
+  iterator begin() { return data_.begin(); }
+  iterator end() { return data_.end(); }
+
+  explicit adaptor(std::map<int, int>&& data) : data_(std::move(data)) {}
+
+private:
+  adaptee data_;
+};
+
+static_assert(std::format_kind<adaptor> == std::range_format::map);
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_adaptor(TestFunction check, ExceptionTest check_exception) {
+  test_int<CharT>(check, check_exception, adaptor{std::map<int, int>{{1, -1}, {42, -42}, {-42, 42}}});
+}
+
+//
+// Driver
+//
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void format_tests(TestFunction check, ExceptionTest check_exception) {
+  test_char<CharT>(check, check_exception);
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+  if (std::same_as<CharT, wchar_t>) // avoid testing twice
+    test_char_to_wchar(check, check_exception);
+#endif
+  test_bool<CharT>(check, check_exception);
+  test_int<CharT>(check, check_exception);
+  test_floating_point<CharT>(check, check_exception);
+  test_pointer<CharT>(check, check_exception);
+  test_string<CharT>(check, check_exception);
+
+  test_status<CharT>(check, check_exception);
+
+  test_adaptor<CharT>(check, check_exception);
+}
+
+#endif // TEST_STD_UTILITIES_FORMAT_FORMAT_RANGE_FORMAT_RANGE_FMTMAP_FORMAT_FUNCTIONS_TESTS_H

diff  --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.vformat.pass.cpp b/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.vformat.pass.cpp
new file mode 100644
index 0000000000000..27b88057b63ac
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.vformat.pass.cpp
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+// 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, c++20
+// UNSUPPORTED: libcpp-has-no-incomplete-format
+
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
+// This test requires the dylib support introduced in D92214.
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}}
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}}
+
+// <format>
+
+// template<ranges::input_range R, class charT>
+//   struct range-default-formatter<range_format::map, R, charT>
+//
+// string vformat(string_view fmt, format_args args);
+// wstring vformat(wstring_view fmt, wformat_args args);
+
+#include <format>
+#include <cassert>
+
+#include "format.functions.tests.h"
+#include "test_macros.h"
+#include "assert_macros.h"
+
+auto test = []<class CharT, class... Args>(
+                std::basic_string_view<CharT> expected, std::basic_string_view<CharT> fmt, Args&&... args) {
+  std::basic_string<CharT> out = std::vformat(fmt, std::make_format_args<context_t<CharT>>(args...));
+  TEST_REQUIRE(
+      out == expected,
+      test_concat_message("\nFormat string   ", fmt, "\nExpected output ", expected, "\nActual output   ", out, '\n'));
+};
+
+auto test_exception =
+    []<class CharT, class... Args>(
+        [[maybe_unused]] std::string_view what,
+        [[maybe_unused]] std::basic_string_view<CharT> fmt,
+        [[maybe_unused]] Args&&... args) {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+      try {
+        TEST_IGNORE_NODISCARD std::vformat(fmt, std::make_format_args<context_t<CharT>>(args...));
+        TEST_FAIL(test_concat_message("\nFormat string   ", fmt, "\nDidn't throw an exception.\n"));
+      } catch (const std::format_error& e) {
+        TEST_LIBCPP_REQUIRE(
+            e.what() == what,
+            test_concat_message(
+                "\nFormat string   ", fmt, "\nExpected exception ", what, "\nActual exception   ", e.what(), '\n'));
+
+        return;
+      }
+      assert(false);
+#endif
+    };
+
+int main(int, char**) {
+  format_tests<char>(test, test_exception);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  format_tests<wchar_t>(test, test_exception);
+#endif
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.pass.cpp b/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.pass.cpp
new file mode 100644
index 0000000000000..0001618bd3482
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.pass.cpp
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+// 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, c++20
+// UNSUPPORTED: libcpp-has-no-incomplete-format
+
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
+// This test requires the dylib support introduced in D92214.
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}}
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}}
+
+// <format>
+
+// template<ranges::input_range R, class charT>
+//   struct range-default-formatter<range_format::map, R, charT>
+
+// template<class FormatContext>
+//   typename FormatContext::iterator
+//     format(const T& ref, FormatContext& ctx) const;
+
+// Note this tests the basics of this function. It's tested in more detail in
+// the format.functions test.
+
+#include <cassert>
+#include <concepts>
+#include <format>
+#include <map>
+
+#include "test_format_context.h"
+#include "test_macros.h"
+#include "make_string.h"
+
+#define SV(S) MAKE_STRING_VIEW(CharT, S)
+
+template <class StringViewT>
+void test_format(StringViewT expected, std::map<int, int> arg) {
+  using CharT      = typename StringViewT::value_type;
+  using String     = std::basic_string<CharT>;
+  using OutIt      = std::back_insert_iterator<String>;
+  using FormatCtxT = std::basic_format_context<OutIt, CharT>;
+
+  std::formatter<std::map<int, int>, CharT> formatter;
+
+  String result;
+  OutIt out             = std::back_inserter(result);
+  FormatCtxT format_ctx = test_format_context_create<OutIt, CharT>(out, std::make_format_args<FormatCtxT>(arg));
+  formatter.format(arg, format_ctx);
+  assert(result == expected);
+}
+
+template <class CharT>
+void test_fmt() {
+  test_format(SV("{1: 42}"), std::map<int, int>{{1, 42}});
+  test_format(SV("{0: 99}"), std::map<int, int>{{0, 99}});
+}
+
+void test() {
+  test_fmt<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_fmt<wchar_t>();
+#endif
+}
+
+int main(int, char**) {
+  test();
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/parse.pass.cpp b/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/parse.pass.cpp
new file mode 100644
index 0000000000000..92763be54e15a
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/parse.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+// 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, c++20
+// UNSUPPORTED: libcpp-has-no-incomplete-format
+
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
+// This test requires the dylib support introduced in D92214.
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}}
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}}
+
+// <format>
+
+// template<ranges::input_range R, class charT>
+//   struct range-default-formatter<range_format::map, R, charT>
+
+// template<class ParseContext>
+//   constexpr typename ParseContext::iterator
+//     parse(ParseContext& ctx);
+
+// Note this tests the basics of this function. It's tested in more detail in
+// the format.functions test.
+
+#include <cassert>
+#include <concepts>
+#include <format>
+#include <map>
+
+#include "test_format_context.h"
+#include "test_macros.h"
+#include "make_string.h"
+
+#define SV(S) MAKE_STRING_VIEW(CharT, S)
+
+template <class StringViewT>
+constexpr void test_parse(StringViewT fmt) {
+  using CharT    = typename StringViewT::value_type;
+  auto parse_ctx = std::basic_format_parse_context<CharT>(fmt);
+  std::formatter<std::map<int, int>, CharT> formatter;
+  static_assert(std::semiregular<decltype(formatter)>);
+
+  std::same_as<typename StringViewT::iterator> auto it = formatter.parse(parse_ctx);
+  assert(it == fmt.end() - (!fmt.empty() && fmt.back() == '}'));
+}
+
+template <class CharT>
+constexpr void test_fmt() {
+  test_parse(SV(""));
+  test_parse(SV(":5"));
+
+  test_parse(SV("}"));
+  test_parse(SV(":5}"));
+}
+
+constexpr bool test() {
+  test_fmt<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_fmt<wchar_t>();
+#endif
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/format/format.tuple/format.pass.cpp b/libcxx/test/std/utilities/format/format.tuple/format.pass.cpp
index aa56e2d3259e9..442df5d0b2f47 100644
--- a/libcxx/test/std/utilities/format/format.tuple/format.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.tuple/format.pass.cpp
@@ -8,6 +8,9 @@
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
 // UNSUPPORTED: libcpp-has-no-incomplete-format
 
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
 // This test requires the dylib support introduced in D92214.
 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}}
 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}}

diff  --git a/libcxx/test/std/utilities/format/format.tuple/parse.pass.cpp b/libcxx/test/std/utilities/format/format.tuple/parse.pass.cpp
index 78008952049a3..05c90557cd54f 100644
--- a/libcxx/test/std/utilities/format/format.tuple/parse.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.tuple/parse.pass.cpp
@@ -8,6 +8,9 @@
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
 // UNSUPPORTED: libcpp-has-no-incomplete-format
 
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
 // This test requires the dylib support introduced in D92214.
 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}}
 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}}

diff  --git a/libcxx/test/std/utilities/format/format.tuple/set_brackets.pass.cpp b/libcxx/test/std/utilities/format/format.tuple/set_brackets.pass.cpp
index bb32611ca137d..86c98455d0a8b 100644
--- a/libcxx/test/std/utilities/format/format.tuple/set_brackets.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.tuple/set_brackets.pass.cpp
@@ -8,6 +8,9 @@
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
 // UNSUPPORTED: libcpp-has-no-incomplete-format
 
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
 // This test requires the dylib support introduced in D92214.
 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}}
 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}}

diff  --git a/libcxx/test/std/utilities/format/format.tuple/set_separator.pass.cpp b/libcxx/test/std/utilities/format/format.tuple/set_separator.pass.cpp
index dfa65617d77bb..fd2c827fe8f47 100644
--- a/libcxx/test/std/utilities/format/format.tuple/set_separator.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.tuple/set_separator.pass.cpp
@@ -8,6 +8,9 @@
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
 // UNSUPPORTED: libcpp-has-no-incomplete-format
 
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
 // This test requires the dylib support introduced in D92214.
 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}}
 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}}

diff  --git a/libcxx/test/support/format.functions.common.h b/libcxx/test/support/format.functions.common.h
index 9796c87f56b86..769b1aff9c642 100644
--- a/libcxx/test/support/format.functions.common.h
+++ b/libcxx/test/support/format.functions.common.h
@@ -14,6 +14,9 @@
 #include <charconv>
 #include <format>
 #include <ranges>
+#include <string>
+#include <string_view>
+#include <vector>
 
 #include "make_string.h"
 


        


More information about the libcxx-commits mailing list