[libcxx-commits] [libcxx] 857cbb9 - [libc++][format] range-default-formatter for set.

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jan 20 08:40:08 PST 2023


Author: Mark de Wever
Date: 2023-01-20T17:39:59+01:00
New Revision: 857cbb9276e55d817e8b3b052db9dffc29b7ebd6

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

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

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

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

Depends on D140801

Reviewed By: ldionne, #libc

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

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

Modified: 
    libcxx/docs/Status/FormatPaper.csv
    libcxx/include/__format/range_default_formatter.h
    libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/FormatPaper.csv b/libcxx/docs/Status/FormatPaper.csv
index bee4e6743ea2a..cbe73ce7127ad 100644
--- a/libcxx/docs/Status/FormatPaper.csv
+++ b/libcxx/docs/Status/FormatPaper.csv
@@ -32,7 +32,7 @@ Section,Description,Dependencies,Assignee,Status,First released version
 `[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.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.fmtset] <https://wg21.link/format.range.fmtset>`_,"Formatting for ranges: set",,Mark de Wever,|Complete|,Clang 16
 `[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

diff  --git a/libcxx/include/__format/range_default_formatter.h b/libcxx/include/__format/range_default_formatter.h
index 6b0793676433f..774887b05305c 100644
--- a/libcxx/include/__format/range_default_formatter.h
+++ b/libcxx/include/__format/range_default_formatter.h
@@ -161,7 +161,26 @@ 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::set, _Rp, _CharT> {
-  __range_default_formatter() = delete; // TODO FMT Implement
+private:
+  using __maybe_const_set = __fmt_maybe_const<_Rp, _CharT>;
+  using __element_type    = remove_cvref_t<ranges::range_reference_t<__maybe_const_set>>;
+  range_formatter<__element_type, _CharT> __underlying_;
+
+public:
+  _LIBCPP_HIDE_FROM_ABI constexpr __range_default_formatter() {
+    __underlying_.set_brackets(_LIBCPP_STATICALLY_WIDEN(_CharT, "{"), _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_set& __range, _FormatContext& __ctx) const {
+    return __underlying_.format(__range, __ctx);
+  }
 };
 
 template <range_format _Kp, ranges::input_range _Rp, class _CharT>

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 35c355840de6e..b0abc2c5bc172 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
@@ -210,14 +210,14 @@ void test_P2286() {
   assert_is_formattable<std::forward_list<int>, CharT>();
   assert_is_formattable<std::list<int>, CharT>();
 
-  assert_is_not_formattable<std::set<int>, CharT>();
+  assert_is_formattable<std::set<int>, CharT>();
   assert_is_formattable<std::map<int, int>, CharT>();
-  assert_is_not_formattable<std::multiset<int>, CharT>();
+  assert_is_formattable<std::multiset<int>, CharT>();
   assert_is_formattable<std::multimap<int, int>, CharT>();
 
-  assert_is_not_formattable<std::unordered_set<int>, CharT>();
+  assert_is_formattable<std::unordered_set<int>, CharT>();
   assert_is_formattable<std::unordered_map<int, int>, CharT>();
-  assert_is_not_formattable<std::unordered_multiset<int>, CharT>();
+  assert_is_formattable<std::unordered_multiset<int>, CharT>();
   assert_is_formattable<std::unordered_multimap<int, int>, CharT>();
 
   assert_is_formattable<std::stack<int>, CharT>();

diff  --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.functions.format.pass.cpp b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.functions.format.pass.cpp
new file mode 100644
index 0000000000000..1361626f99e14
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/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::set, 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.fmtset/format.functions.tests.h b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.functions.tests.h
new file mode 100644
index 0000000000000..7bb65636e2438
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.functions.tests.h
@@ -0,0 +1,1479 @@
+//===----------------------------------------------------------------------===//
+// 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_FMTSET_FORMAT_FUNCTIONS_TESTS_H
+#define TEST_STD_UTILITIES_FORMAT_FORMAT_RANGE_FORMAT_RANGE_FMTSET_FORMAT_FUNCTIONS_TESTS_H
+
+#include <algorithm>
+#include <format>
+#include <set>
+#include <tuple>
+#include <unordered_set>
+#include <utility>
+
+#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_default(TestFunction check, ExceptionTest check_exception) {
+  std::set input{CharT('a'), CharT('c'), CharT('b')}; // input not sorted.
+
+  // Note when no range-underlying-spec is present the char is escaped,
+  check(SV("{'a', 'b', 'c'}"), SV("{}"), input);
+  // when one is present there is no escaping,
+  check(SV("{a, b, c}"), SV("{::}"), input);
+  // unless forced by the type specifier.
+  check(SV("{'a', 'b', 'c'}"), SV("{::?}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{'a', 'b', 'c'}     "), SV("{:20}"), input);
+  check(SV("{'a', 'b', 'c'}*****"), SV("{:*<20}"), input);
+  check(SV("__{'a', 'b', 'c'}___"), SV("{:_^20}"), input);
+  check(SV("#####{'a', 'b', 'c'}"), SV("{:#>20}"), input);
+
+  check(SV("{'a', 'b', 'c'}     "), SV("{:{}}"), input, 20);
+  check(SV("{'a', 'b', 'c'}*****"), SV("{:*<{}}"), input, 20);
+  check(SV("__{'a', 'b', 'c'}___"), SV("{:_^{}}"), input, 20);
+  check(SV("#####{'a', 'b', 'c'}"), SV("{:#>{}}"), input, 20);
+
+  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', 'b', 'c'___"), SV("{:_^18n}"), input);
+
+  // *** type ***
+  check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
+
+  // ***** Only underlying has a format-spec
+  check(SV("{a   , b   , c   }"), SV("{::4}"), input);
+  check(SV("{a***, b***, c***}"), SV("{::*<4}"), input);
+  check(SV("{_a__, _b__, _c__}"), SV("{::_^4}"), input);
+  check(SV("{:::a, :::b, :::c}"), SV("{:::>4}"), input);
+
+  check(SV("{a   , b   , c   }"), SV("{::{}}"), input, 4);
+  check(SV("{a***, b***, c***}"), SV("{::*<{}}"), input, 4);
+  check(SV("{_a__, _b__, _c__}"), SV("{::_^{}}"), input, 4);
+  check(SV("{:::a, :::b, :::c}"), SV("{:::>{}}"), input, 4);
+
+  check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
+  check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
+
+  // *** sign ***
+  check_exception("A sign field isn't allowed in this format-spec", SV("{::-}"), input);
+  check_exception("A sign field isn't allowed in this format-spec", SV("{::+}"), input);
+  check_exception("A sign field isn't allowed in this format-spec", SV("{:: }"), input);
+
+  check(SV("{97, 98, 99}"), SV("{::-d}"), input);
+  check(SV("{+97, +98, +99}"), SV("{::+d}"), input);
+  check(SV("{ 97,  98,  99}"), SV("{:: d}"), input);
+
+  // *** alternate form ***
+  check_exception("An alternate form field isn't allowed in this format-spec", SV("{::#}"), input);
+
+  check(SV("{0x61, 0x62, 0x63}"), SV("{::#x}"), input);
+
+  // *** zero-padding ***
+  check_exception("A zero-padding field isn't allowed in this format-spec", SV("{::05}"), input);
+
+  check(SV("{00141, 00142, 00143}"), SV("{::05o}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
+
+  // *** locale-specific form ***
+  check(SV("{a, b, c}"), SV("{::L}"), input);
+
+  // *** type ***
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("bBcdoxX?"))
+    check_exception("The format-spec type has a type not supported for a char argument", fmt, input);
+
+  // ***** Both have a format-spec
+  check(SV("^^{:a, :b, :c}^^^"), SV("{:^^17::>2}"), input);
+  check(SV("^^{:a, :b, :c}^^^"), SV("{:^^{}::>2}"), input, 17);
+  check(SV("^^{:a, :b, :c}^^^"), SV("{:^^{}::>{}}"), input, 17, 2);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}::>2}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 17);
+}
+
+// A set can be written as a string, based on
+//   [tab:formatter.range.type]
+//   s  T shall be charT. ...
+// This does not seem very useful, but it is allowed.
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_char_string(TestFunction check, [[maybe_unused]] ExceptionTest check_exception) {
+  std::set input{CharT('a'), CharT('c'), CharT('b')}; // input not sorted.
+
+  check(SV("abc"), SV("{:s}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("abc   "), SV("{:6s}"), input);
+  check(SV("abc***"), SV("{:*<6s}"), input);
+  check(SV("_abc__"), SV("{:_^6s}"), input);
+  check(SV("###abc"), SV("{:#>6s}"), input);
+
+  check(SV("abc   "), SV("{:{}s}"), input, 6);
+  check(SV("abc***"), SV("{:*<{}s}"), input, 6);
+  check(SV("_abc__"), SV("{:_^{}s}"), input, 6);
+  check(SV("###abc"), SV("{:#>{}s}"), input, 6);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<s}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<s}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::<s}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:-s}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:+s}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{: s}"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:#s}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0s}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:.s}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:Ls}"), input);
+
+  // *** n
+  check_exception("The n option and type s can't be used together", SV("{:ns}"), input);
+
+  // *** type ***
+  check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
+
+  // ***** Only underlying has a format-spec
+  check_exception("Type s and an underlying format specification can't be used together", SV("{:s:}"), input);
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("bBcdoxX?"))
+    check_exception("The format-spec type has a type not supported for a char argument", fmt, input);
+
+  // ***** Both have a format-spec
+  check_exception("Type s and an underlying format specification can't be used together", SV("{:5s:5}"), input);
+}
+
+// A set can be written as a debug_string, based on
+//   [tab:formatter.range.type]
+//   ?s T shall be charT. ...
+// This does not seem very useful, but it is allowed.
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_char_escaped_string(TestFunction check, [[maybe_unused]] ExceptionTest check_exception) {
+  std::set input{CharT('a'), CharT('c'), CharT('b')}; // input not sorted.
+
+  check(SV("\"abc\""), SV("{:?s}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV(R"("abc"   )"), SV("{:8?s}"), input);
+  check(SV(R"("abc"***)"), SV("{:*<8?s}"), input);
+  check(SV(R"(_"abc"__)"), SV("{:_^8?s}"), input);
+  check(SV(R"(###"abc")"), SV("{:#>8?s}"), input);
+
+  check(SV(R"("abc"   )"), SV("{:{}?s}"), input, 8);
+  check(SV(R"("abc"***)"), SV("{:*<{}?s}"), input, 8);
+  check(SV(R"(_"abc"__)"), SV("{:_^{}?s}"), input, 8);
+  check(SV(R"(###"abc")"), SV("{:#>{}?s}"), input, 8);
+
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<?s}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<?s}"), input);
+  check_exception("The format-spec range-fill field contains an invalid character", SV("{::<?s}"), input);
+
+  // *** sign ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:-?s}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:+?s}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{: ?s}"), input);
+
+  // *** alternate form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:#?s}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0?s}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:.?s}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{:L?s}"), input);
+
+  // *** n
+  check_exception("The n option and type ?s can't be used together", SV("{:n?s}"), input);
+
+  // *** type ***
+  check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
+
+  // ***** Only underlying has a format-spec
+  check_exception("Type ?s and an underlying format specification can't be used together", SV("{:?s:}"), input);
+
+  // ***** Both have a format-spec
+  check_exception("Type ?s and an underlying format specification can't be used together", SV("{:5?s:5}"), input);
+}
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_char(TestFunction check, ExceptionTest check_exception) {
+  test_char_default<CharT>(check, check_exception);
+  test_char_string<CharT>(check, check_exception);
+  test_char_escaped_string<CharT>(check, check_exception);
+}
+
+//
+// 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::set input{'a', 'c', 'b'}; // input not sorted.
+
+  using CharT = wchar_t;
+
+  // Note when no range-underlying-spec is present the char is escaped,
+  check(SV("{'a', 'b', 'c'}"), SV("{}"), input);
+  // when one is present there is no escaping,
+  check(SV("{a, b, c}"), SV("{::}"), input);
+  // unless forced by the type specifier.
+  check(SV("{'a', 'b', 'c'}"), SV("{::?}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{'a', 'b', 'c'}     "), SV("{:20}"), input);
+  check(SV("{'a', 'b', 'c'}*****"), SV("{:*<20}"), input);
+  check(SV("__{'a', 'b', 'c'}___"), SV("{:_^20}"), input);
+  check(SV("#####{'a', 'b', 'c'}"), SV("{:#>20}"), input);
+
+  check(SV("{'a', 'b', 'c'}     "), SV("{:{}}"), input, 20);
+  check(SV("{'a', 'b', 'c'}*****"), SV("{:*<{}}"), input, 20);
+  check(SV("__{'a', 'b', 'c'}___"), SV("{:_^{}}"), input, 20);
+  check(SV("#####{'a', 'b', 'c'}"), SV("{:#>{}}"), input, 20);
+
+  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', 'b', 'c'___"), SV("{:_^18n}"), input);
+
+  // *** type ***
+  check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
+
+  // ***** Only underlying has a format-spec
+  check(SV("{a   , b   , c   }"), SV("{::4}"), input);
+  check(SV("{a***, b***, c***}"), SV("{::*<4}"), input);
+  check(SV("{_a__, _b__, _c__}"), SV("{::_^4}"), input);
+  check(SV("{:::a, :::b, :::c}"), SV("{:::>4}"), input);
+
+  check(SV("{a   , b   , c   }"), SV("{::{}}"), input, 4);
+  check(SV("{a***, b***, c***}"), SV("{::*<{}}"), input, 4);
+  check(SV("{_a__, _b__, _c__}"), SV("{::_^{}}"), input, 4);
+  check(SV("{:::a, :::b, :::c}"), SV("{:::>{}}"), input, 4);
+
+  check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
+  check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
+
+  // *** sign ***
+  check_exception("A sign field isn't allowed in this format-spec", SV("{::-}"), input);
+  check_exception("A sign field isn't allowed in this format-spec", SV("{::+}"), input);
+  check_exception("A sign field isn't allowed in this format-spec", SV("{:: }"), input);
+
+  check(SV("{97, 98, 99}"), SV("{::-d}"), input);
+  check(SV("{+97, +98, +99}"), SV("{::+d}"), input);
+  check(SV("{ 97,  98,  99}"), SV("{:: d}"), input);
+
+  // *** alternate form ***
+  check_exception("An alternate form field isn't allowed in this format-spec", SV("{::#}"), input);
+
+  check(SV("{0x61, 0x62, 0x63}"), SV("{::#x}"), input);
+
+  // *** zero-padding ***
+  check_exception("A zero-padding field isn't allowed in this format-spec", SV("{::05}"), input);
+
+  check(SV("{00141, 00142, 00143}"), SV("{::05o}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
+
+  // *** locale-specific form ***
+  check(SV("{a, b, c}"), SV("{::L}"), input);
+
+  // *** type ***
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("bBcdoxX?"))
+    check_exception("The format-spec type has a type not supported for a char argument", fmt, input);
+
+  // ***** Both have a format-spec
+  check(SV("^^{:a, :b, :c}^^^"), SV("{:^^17::>2}"), input);
+  check(SV("^^{:a, :b, :c}^^^"), SV("{:^^{}::>2}"), input, 17);
+  check(SV("^^{:a, :b, :c}^^^"), SV("{:^^{}::>{}}"), input, 17, 2);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}::>2}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 17);
+
+  // The types s and ?s may only be used when using range_formatter<T, charT>
+  // where the types T and charT are the same. This means this can't be used for
+  // range_formatter<wchar_t, char> even when formatter<wchar_t, char> has a
+  // debug-enabled specialization.
+
+  using CharT = wchar_t;
+  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);
+}
+#endif //  _LIBCPP_HAS_NO_WIDE_CHARACTERS
+
+//
+// Bool
+//
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_bool(TestFunction check, ExceptionTest check_exception) {
+  std::set input{true, false};
+
+  check(SV("{false, true}"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{false, true}     "), SV("{:18}"), input);
+  check(SV("{false, true}*****"), SV("{:*<18}"), input);
+  check(SV("__{false, true}___"), SV("{:_^18}"), input);
+  check(SV("#####{false, true}"), SV("{:#>18}"), input);
+
+  check(SV("{false, true}     "), SV("{:{}}"), input, 18);
+  check(SV("{false, true}*****"), SV("{:*<{}}"), input, 18);
+  check(SV("__{false, true}___"), SV("{:_^{}}"), input, 18);
+  check(SV("#####{false, true}"), SV("{:#>{}}"), input, 18);
+
+  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, true___"), SV("{:_^16n}"), input);
+
+  // *** type ***
+  check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), 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("{false  , true   }"), SV("{::7}"), input);
+  check(SV("{false**, true***}"), SV("{::*<7}"), input);
+  check(SV("{_false_, _true__}"), SV("{::_^7}"), input);
+  check(SV("{::false, :::true}"), SV("{:::>7}"), input);
+
+  check(SV("{false  , true   }"), SV("{::{}}"), input, 7);
+  check(SV("{false**, true***}"), SV("{::*<{}}"), input, 7);
+  check(SV("{_false_, _true__}"), SV("{::_^{}}"), input, 7);
+  check(SV("{::false, :::true}"), SV("{:::>{}}"), input, 7);
+
+  check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
+  check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
+
+  // *** sign ***
+  check_exception("A sign field isn't allowed in this format-spec", SV("{::-}"), input);
+  check_exception("A sign field isn't allowed in this format-spec", SV("{::+}"), input);
+  check_exception("A sign field isn't allowed in this format-spec", SV("{:: }"), input);
+
+  check(SV("{0, 1}"), SV("{::-d}"), input);
+  check(SV("{+0, +1}"), SV("{::+d}"), input);
+  check(SV("{ 0,  1}"), SV("{:: d}"), input);
+
+  // *** alternate form ***
+  check_exception("An alternate form field isn't allowed in this format-spec", SV("{::#}"), input);
+
+  check(SV("{0x0, 0x1}"), SV("{::#x}"), input);
+
+  // *** zero-padding ***
+  check_exception("A zero-padding field isn't allowed in this format-spec", SV("{::05}"), input);
+
+  check(SV("{00000, 00001}"), SV("{::05o}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
+
+  // *** locale-specific form ***
+  check(SV("{false, true}"), SV("{::L}"), input);
+
+  // *** type ***
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("bBdosxX"))
+    check_exception("The format-spec type has a type not supported for a bool argument", fmt, input);
+
+  // ***** Both have a format-spec
+  check(SV("^^{::false, :::true}^^^"), SV("{:^^23::>7}"), input);
+  check(SV("^^{::false, :::true}^^^"), SV("{:^^{}::>7}"), input, 23);
+  check(SV("^^{::false, :::true}^^^"), SV("{:^^{}::>{}}"), input, 23, 7);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}::>5}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 23);
+}
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_bool_multiset(TestFunction check, ExceptionTest check_exception) {
+  std::multiset<bool, std::greater<bool>> input{true, false, true}; // unordered
+
+  check(SV("{true, true, false}"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{true, true, false}     "), SV("{:24}"), input);
+  check(SV("{true, true, false}*****"), SV("{:*<24}"), input);
+  check(SV("__{true, true, false}___"), SV("{:_^24}"), input);
+  check(SV("#####{true, true, false}"), SV("{:#>24}"), input);
+
+  check(SV("{true, true, false}     "), SV("{:{}}"), input, 24);
+  check(SV("{true, true, false}*****"), SV("{:*<{}}"), input, 24);
+  check(SV("__{true, true, false}___"), SV("{:_^{}}"), input, 24);
+  check(SV("#####{true, true, false}"), SV("{:#>{}}"), input, 24);
+
+  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("__true, true, false___"), SV("{:_^22n}"), input);
+
+  // *** type ***
+  check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), 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("{true   , true   , false  }"), SV("{::7}"), input);
+  check(SV("{true***, true***, false**}"), SV("{::*<7}"), input);
+  check(SV("{_true__, _true__, _false_}"), SV("{::_^7}"), input);
+  check(SV("{:::true, :::true, ::false}"), SV("{:::>7}"), input);
+
+  check(SV("{true   , true   , false  }"), SV("{::{}}"), input, 7);
+  check(SV("{true***, true***, false**}"), SV("{::*<{}}"), input, 7);
+  check(SV("{_true__, _true__, _false_}"), SV("{::_^{}}"), input, 7);
+  check(SV("{:::true, :::true, ::false}"), SV("{:::>{}}"), input, 7);
+
+  check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
+  check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
+
+  // *** sign ***
+  check_exception("A sign field isn't allowed in this format-spec", SV("{::-}"), input);
+  check_exception("A sign field isn't allowed in this format-spec", SV("{::+}"), input);
+  check_exception("A sign field isn't allowed in this format-spec", SV("{:: }"), input);
+
+  check(SV("{1, 1, 0}"), SV("{::-d}"), input);
+  check(SV("{+1, +1, +0}"), SV("{::+d}"), input);
+  check(SV("{ 1,  1,  0}"), SV("{:: d}"), input);
+
+  // *** alternate form ***
+  check_exception("An alternate form field isn't allowed in this format-spec", SV("{::#}"), input);
+
+  check(SV("{0x1, 0x1, 0x0}"), SV("{::#x}"), input);
+
+  // *** zero-padding ***
+  check_exception("A zero-padding field isn't allowed in this format-spec", SV("{::05}"), input);
+
+  check(SV("{00001, 00001, 00000}"), SV("{::05o}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
+
+  // *** locale-specific form ***
+  check(SV("{true, true, false}"), SV("{::L}"), input);
+
+  // *** type ***
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("bBdosxX"))
+    check_exception("The format-spec type has a type not supported for a bool argument", fmt, input);
+
+  // ***** Both have a format-spec
+  check(SV("^^{:::true, :::true, ::false}^^^"), SV("{:^^32::>7}"), input);
+  check(SV("^^{:::true, :::true, ::false}^^^"), SV("{:^^{}::>7}"), input, 32);
+  check(SV("^^{:::true, :::true, ::false}^^^"), SV("{:^^{}::>{}}"), input, 32, 7);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}::>5}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 32);
+}
+
+//
+// Integral
+//
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
+  check(SV("{-42, 1, 2, 42}"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{-42, 1, 2, 42}     "), SV("{:20}"), input);
+  check(SV("{-42, 1, 2, 42}*****"), SV("{:*<20}"), input);
+  check(SV("__{-42, 1, 2, 42}___"), SV("{:_^20}"), input);
+  check(SV("#####{-42, 1, 2, 42}"), SV("{:#>20}"), input);
+
+  check(SV("{-42, 1, 2, 42}     "), SV("{:{}}"), input, 20);
+  check(SV("{-42, 1, 2, 42}*****"), SV("{:*<{}}"), input, 20);
+  check(SV("__{-42, 1, 2, 42}___"), SV("{:_^{}}"), input, 20);
+  check(SV("#####{-42, 1, 2, 42}"), SV("{:#>{}}"), input, 20);
+
+  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, 1, 2, 42___"), SV("{:_^18n}"), input);
+
+  // *** type ***
+  check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), 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("{  -42,     1,     2,    42}"), SV("{::5}"), input);
+  check(SV("{-42**, 1****, 2****, 42***}"), SV("{::*<5}"), input);
+  check(SV("{_-42_, __1__, __2__, _42__}"), SV("{::_^5}"), input);
+  check(SV("{::-42, ::::1, ::::2, :::42}"), SV("{:::>5}"), input);
+
+  check(SV("{  -42,     1,     2,    42}"), SV("{::{}}"), input, 5);
+  check(SV("{-42**, 1****, 2****, 42***}"), SV("{::*<{}}"), input, 5);
+  check(SV("{_-42_, __1__, __2__, _42__}"), SV("{::_^{}}"), input, 5);
+  check(SV("{::-42, ::::1, ::::2, :::42}"), SV("{:::>{}}"), input, 5);
+
+  check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
+  check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
+
+  // *** sign ***
+  check(SV("{-42, 1, 2, 42}"), SV("{::-}"), input);
+  check(SV("{-42, +1, +2, +42}"), SV("{::+}"), input);
+  check(SV("{-42,  1,  2,  42}"), SV("{:: }"), input);
+
+  // *** alternate form ***
+  check(SV("{-0x2a, 0x1, 0x2, 0x2a}"), SV("{::#x}"), input);
+
+  // *** zero-padding ***
+  check(SV("{-0042, 00001, 00002, 00042}"), SV("{::05}"), input);
+  check(SV("{-002a, 00001, 00002, 0002a}"), SV("{::05x}"), input);
+  check(SV("{-0x2a, 0x001, 0x002, 0x02a}"), SV("{::#05x}"), input);
+
+  // *** precision ***
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
+
+  // *** locale-specific form ***
+  check(SV("{-42, 1, 2, 42}"), SV("{::L}"), input); // does nothing in this test, but is accepted.
+
+  // *** type ***
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("bBcdoxX"))
+    check_exception("The format-spec type has a type not supported for an integer argument", fmt, input);
+
+  // ***** Both have a format-spec
+  check(SV("^^{::-42, ::::1, ::::2, :::42}^^^"), SV("{:^^33::>5}"), input);
+  check(SV("^^{::-42, ::::1, ::::2, :::42}^^^"), SV("{:^^{}::>5}"), input, 33);
+  check(SV("^^{::-42, ::::1, ::::2, :::42}^^^"), SV("{:^^{}::>{}}"), input, 33, 5);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}::>5}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 33);
+}
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_int(TestFunction check, ExceptionTest check_exception) {
+  test_int<CharT>(check, check_exception, std::set{1, 42, 2, -42});      // unsorted
+  test_int<CharT>(check, check_exception, std::multiset{1, 42, 2, -42}); // unsorted
+}
+
+//
+// Floating point
+//
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_floating_point(TestFunction check, ExceptionTest check_exception, auto&& input) {
+  check(SV("{-42.5, 0, 1.25, 42.5}"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{-42.5, 0, 1.25, 42.5}     "), SV("{:27}"), input);
+  check(SV("{-42.5, 0, 1.25, 42.5}*****"), SV("{:*<27}"), input);
+  check(SV("__{-42.5, 0, 1.25, 42.5}___"), SV("{:_^27}"), input);
+  check(SV("#####{-42.5, 0, 1.25, 42.5}"), SV("{:#>27}"), input);
+
+  check(SV("{-42.5, 0, 1.25, 42.5}     "), SV("{:{}}"), input, 27);
+  check(SV("{-42.5, 0, 1.25, 42.5}*****"), SV("{:*<{}}"), input, 27);
+  check(SV("__{-42.5, 0, 1.25, 42.5}___"), SV("{:_^{}}"), input, 27);
+  check(SV("#####{-42.5, 0, 1.25, 42.5}"), SV("{:#>{}}"), input, 27);
+
+  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.5, 0, 1.25, 42.5___"), SV("{:_^25n}"), input);
+
+  // *** type ***
+  check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), 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("{-42.5,     0,  1.25,  42.5}"), SV("{::5}"), input);
+  check(SV("{-42.5, 0****, 1.25*, 42.5*}"), SV("{::*<5}"), input);
+  check(SV("{-42.5, __0__, 1.25_, 42.5_}"), SV("{::_^5}"), input);
+  check(SV("{-42.5, ::::0, :1.25, :42.5}"), SV("{:::>5}"), input);
+
+  check(SV("{-42.5,     0,  1.25,  42.5}"), SV("{::{}}"), input, 5);
+  check(SV("{-42.5, 0****, 1.25*, 42.5*}"), SV("{::*<{}}"), input, 5);
+  check(SV("{-42.5, __0__, 1.25_, 42.5_}"), SV("{::_^{}}"), input, 5);
+  check(SV("{-42.5, ::::0, :1.25, :42.5}"), SV("{:::>{}}"), input, 5);
+
+  check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
+  check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
+
+  // *** sign ***
+  check(SV("{-42.5, 0, 1.25, 42.5}"), SV("{::-}"), input);
+  check(SV("{-42.5, +0, +1.25, +42.5}"), SV("{::+}"), input);
+  check(SV("{-42.5,  0,  1.25,  42.5}"), SV("{:: }"), input);
+
+  // *** alternate form ***
+  check(SV("{-42.5, 0., 1.25, 42.5}"), SV("{::#}"), input);
+
+  // *** zero-padding ***
+  check(SV("{-42.5, 00000, 01.25, 042.5}"), SV("{::05}"), input);
+  check(SV("{-42.5, 0000., 01.25, 042.5}"), SV("{::#05}"), input);
+
+  // *** precision ***
+  check(SV("{-42, 0, 1.2, 42}"), SV("{::.2}"), input);
+  check(SV("{-42.500, 0.000, 1.250, 42.500}"), SV("{::.3f}"), input);
+
+  check(SV("{-42, 0, 1.2, 42}"), SV("{::.{}}"), input, 2);
+  check(SV("{-42.500, 0.000, 1.250, 42.500}"), SV("{::.{}f}"), input, 3);
+
+  check_exception("The format-spec precision field doesn't contain a value or arg-id", SV("{::.}"), input);
+
+  // *** locale-specific form ***
+  check(SV("{-42.5, 0, 1.25, 42.5}"), SV("{::L}"), input); // does not require locales present
+#ifndef TEST_HAS_NO_LOCALIZATION
+  std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
+  check(SV("{-42,5, 0, 1,25, 42,5}"), SV("{::L}"), input);
+
+  std::locale::global(std::locale(LOCALE_en_US_UTF_8));
+  check(SV("{-42.5, 0, 1.25, 42.5}"), SV("{::L}"), input);
+
+  std::locale::global(std::locale::classic());
+#endif // TEST_HAS_NO_LOCALIZATION
+
+  // *** type ***
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("aAeEfFgG"))
+    check_exception("The format-spec type has a type not supported for a floating-point argument", fmt, input);
+
+  // ***** Both have a format-spec
+  check(SV("^^{-42.5, ::::0, :1.25, :42.5}^^^"), SV("{:^^33::>5}"), input);
+  check(SV("^^{-42.5, ::::0, :1.25, :42.5}^^^"), SV("{:^^{}::>5}"), input, 33);
+  check(SV("^^{-42.5, ::::0, :1.25, :42.5}^^^"), SV("{:^^{}::>{}}"), input, 33, 5);
+
+  check(SV("^^{::-42, ::::0, ::1.2, :::42}^^^"), SV("{:^^33::>5.2}"), input);
+  check(SV("^^{::-42, ::::0, ::1.2, :::42}^^^"), SV("{:^^{}::>5.2}"), input, 33);
+  check(SV("^^{::-42, ::::0, ::1.2, :::42}^^^"), SV("{:^^{}::>{}.2}"), input, 33, 5);
+  check(SV("^^{::-42, ::::0, ::1.2, :::42}^^^"), SV("{:^^{}::>{}.{}}"), input, 33, 5, 2);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}::>5.2}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}::>{}.2}"), input, 33);
+  check_exception("Argument index out of bounds", SV("{:^^{}::>{}.{}}"), input, 33, 5);
+}
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_floating_point(TestFunction check, ExceptionTest check_exception) {
+  test_floating_point<CharT>(check, check_exception, std::set{-42.5f, 0.0f, 1.25f, 42.5f});
+  test_floating_point<CharT>(check, check_exception, std::multiset{-42.5, 0.0, 1.25, 42.5});
+  test_floating_point<CharT>(check, check_exception, std::set{-42.5l, 0.0l, 1.25l, 42.5l});
+}
+
+//
+// Pointer
+//
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& input) {
+  check(SV("{0x0}"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{0x0}     "), SV("{:10}"), input);
+  check(SV("{0x0}*****"), SV("{:*<10}"), input);
+  check(SV("__{0x0}___"), SV("{:_^10}"), input);
+  check(SV("#####{0x0}"), SV("{:#>10}"), input);
+
+  check(SV("{0x0}     "), SV("{:{}}"), input, 10);
+  check(SV("{0x0}*****"), SV("{:*<{}}"), input, 10);
+  check(SV("__{0x0}___"), SV("{:_^{}}"), input, 10);
+  check(SV("#####{0x0}"), 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);
+
+  // *** 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_"), SV("{:_^5n}"), input);
+
+  // *** type ***
+  check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), 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("{  0x0}"), SV("{::5}"), input);
+  check(SV("{0x0**}"), SV("{::*<5}"), input);
+  check(SV("{_0x0_}"), SV("{::_^5}"), input);
+  check(SV("{::0x0}"), SV("{:::>5}"), input);
+
+  check(SV("{  0x0}"), SV("{::{}}"), input, 5);
+  check(SV("{0x0**}"), SV("{::*<{}}"), input, 5);
+  check(SV("{_0x0_}"), SV("{::_^{}}"), input, 5);
+  check(SV("{::0x0}"), SV("{:::>{}}"), input, 5);
+
+  check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
+  check_exception("The format-spec 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("{::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>("p"))
+    check_exception("The format-spec type has a type not supported for a pointer argument", fmt, input);
+
+  // ***** Both have a format-spec
+  check(SV("^^{::0x0}^^^"), SV("{:^^12::>5}"), input);
+  check(SV("^^{::0x0}^^^"), SV("{:^^{}::>5}"), input, 12);
+  check(SV("^^{::0x0}^^^"), SV("{:^^{}::>{}}"), input, 12, 5);
+
+  check(SV("^^{::0x0}^^^"), SV("{:^^12::>5}"), input);
+  check(SV("^^{::0x0}^^^"), SV("{:^^{}::>5}"), input, 12);
+  check(SV("^^{::0x0}^^^"), SV("{:^^{}::>{}}"), input, 12, 5);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}::>5}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 12);
+}
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_pointer(TestFunction check, ExceptionTest check_exception) {
+  // Note nullptr_t can only be equality compared so not used in a set.
+  test_pointer<CharT>(check, check_exception, std::unordered_set{static_cast<const void*>(0)});
+  test_pointer<CharT>(check, check_exception, std::unordered_multiset{static_cast<void*>(0)});
+}
+
+//
+// String
+//
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
+  check(SV(R"({"Hello", "world"})"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV(R"({"Hello", "world"}     )"), SV("{:23}"), input);
+  check(SV(R"({"Hello", "world"}*****)"), SV("{:*<23}"), input);
+  check(SV(R"(__{"Hello", "world"}___)"), SV("{:_^23}"), input);
+  check(SV(R"(#####{"Hello", "world"})"), SV("{:#>23}"), input);
+
+  check(SV(R"({"Hello", "world"}     )"), SV("{:{}}"), input, 23);
+  check(SV(R"({"Hello", "world"}*****)"), SV("{:*<{}}"), input, 23);
+  check(SV(R"(__{"Hello", "world"}___)"), SV("{:_^{}}"), input, 23);
+  check(SV(R"(#####{"Hello", "world"})"), 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);
+
+  // *** 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", "world"_)"), SV("{:_^18n}"), input);
+
+  // *** type ***
+  check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), 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   , world   })"), SV("{::8}"), input);
+  check(SV(R"({Hello***, world***})"), SV("{::*<8}"), input);
+  check(SV(R"({_Hello__, _world__})"), SV("{::_^8}"), input);
+  check(SV(R"({:::Hello, :::world})"), SV("{:::>8}"), input);
+
+  check(SV(R"({Hello   , world   })"), SV("{::{}}"), input, 8);
+  check(SV(R"({Hello***, world***})"), SV("{::*<{}}"), input, 8);
+  check(SV(R"({_Hello__, _world__})"), SV("{::_^{}}"), input, 8);
+  check(SV(R"({:::Hello, :::world})"), SV("{:::>{}}"), input, 8);
+
+  check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
+  check_exception("The format-spec 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("{::05}"), input);
+
+  // *** precision ***
+  check(SV(R"({Hel, wor})"), SV("{::.3}"), input);
+
+  check(SV(R"({Hel, wor})"), SV("{::.{}}"), input, 3);
+
+  check_exception("The format-spec precision field doesn't contain a value or arg-id", 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>("s?"))
+    check_exception("The format-spec type has a type not supported for a string argument", fmt, input);
+
+  // ***** Both have a format-spec
+  check(SV(R"(^^{:::Hello, :::world}^^^)"), SV("{:^^25::>8}"), input);
+  check(SV(R"(^^{:::Hello, :::world}^^^)"), SV("{:^^{}::>8}"), input, 25);
+  check(SV(R"(^^{:::Hello, :::world}^^^)"), SV("{:^^{}::>{}}"), input, 25, 8);
+
+  check(SV(R"(^^{:::Hello, :::world}^^^)"), SV("{:^^25::>8}"), input);
+  check(SV(R"(^^{:::Hello, :::world}^^^)"), SV("{:^^{}::>8}"), input, 25);
+  check(SV(R"(^^{:::Hello, :::world}^^^)"), SV("{:^^{}::>{}}"), input, 25, 8);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}::>8}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 25);
+}
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_string(TestFunction check, ExceptionTest check_exception) {
+  test_string<CharT>(check, check_exception, std::set{STR("Hello"), STR("world")});
+  test_string<CharT>(check, check_exception, std::set{SV("Hello"), SV("world")});
+}
+
+//
+// Handle
+//
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_status(TestFunction check, ExceptionTest check_exception) {
+  std::set input{status::foo, status::bar, status::foobar}; // unordered input
+
+  check(SV("{0x5555, 0xaa55, 0xaaaa}"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{0x5555, 0xaa55, 0xaaaa}     "), SV("{:29}"), input);
+  check(SV("{0x5555, 0xaa55, 0xaaaa}*****"), SV("{:*<29}"), input);
+  check(SV("__{0x5555, 0xaa55, 0xaaaa}___"), SV("{:_^29}"), input);
+  check(SV("#####{0x5555, 0xaa55, 0xaaaa}"), SV("{:#>29}"), input);
+
+  check(SV("{0x5555, 0xaa55, 0xaaaa}     "), SV("{:{}}"), input, 29);
+  check(SV("{0x5555, 0xaa55, 0xaaaa}*****"), SV("{:*<{}}"), input, 29);
+  check(SV("__{0x5555, 0xaa55, 0xaaaa}___"), SV("{:_^{}}"), input, 29);
+  check(SV("#####{0x5555, 0xaa55, 0xaaaa}"), SV("{:#>{}}"), input, 29);
+
+  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("__0x5555, 0xaa55, 0xaaaa___"), SV("{:_^27n}"), input);
+
+  // *** type ***
+  check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), 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_exception("The format-spec type has a type not supported for a status argument", SV("{::*<7}"), input);
+
+  check(SV("{0x5555, 0xaa55, 0xaaaa}"), SV("{::x}"), input);
+  check(SV("{0X5555, 0XAA55, 0XAAAA}"), SV("{::X}"), input);
+  check(SV("{bar, foobar, foo}"), SV("{::s}"), input);
+
+  // ***** Both have a format-spec
+  check(SV("^^{0X5555, 0XAA55, 0XAAAA}^^^"), SV("{:^^29:X}"), input);
+  check(SV("^^{0X5555, 0XAA55, 0XAAAA}^^^"), SV("{:^^{}:X}"), input, 29);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}:X}"), input);
+}
+
+//
+// Pair
+//
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_pair_tuple(TestFunction check, ExceptionTest check_exception, auto&& input) {
+  check(SV("{(1, a), (42, *)}"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{(1, a), (42, *)}     "), SV("{:22}"), input);
+  check(SV("{(1, a), (42, *)}*****"), SV("{:*<22}"), input);
+  check(SV("__{(1, a), (42, *)}___"), SV("{:_^22}"), input);
+  check(SV("#####{(1, a), (42, *)}"), SV("{:#>22}"), input);
+
+  check(SV("{(1, a), (42, *)}     "), SV("{:{}}"), input, 22);
+  check(SV("{(1, a), (42, *)}*****"), SV("{:*<{}}"), input, 22);
+  check(SV("__{(1, a), (42, *)}___"), SV("{:_^{}}"), input, 22);
+  check(SV("#####{(1, a), (42, *)}"), SV("{:#>{}}"), input, 22);
+
+  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("__(1, a), (42, *)___"), SV("{:_^20n}"), input);
+  check(SV("__(1, a), (42, *)___"), SV("{:_^20nm}"), input); // m should have no effect
+
+  // *** type ***
+  check(SV("__{(1, a), (42, *)}___"), SV("{:_^22m}"), 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("{(1, 'a')   , (42, '*')  }"), SV("{::11}"), input);
+  check(SV("{(1, 'a')***, (42, '*')**}"), SV("{::*<11}"), input);
+  check(SV("{_(1, 'a')__, _(42, '*')_}"), SV("{::_^11}"), input);
+  check(SV("{###(1, 'a'), ##(42, '*')}"), SV("{::#>11}"), input);
+
+  check(SV("{(1, 'a')   , (42, '*')  }"), SV("{::{}}"), input, 11);
+  check(SV("{(1, 'a')***, (42, '*')**}"), SV("{::*<{}}"), input, 11);
+  check(SV("{_(1, 'a')__, _(42, '*')_}"), SV("{::_^{}}"), input, 11);
+  check(SV("{###(1, 'a'), ##(42, '*')}"), SV("{::#>{}}"), input, 11);
+
+  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("{1: 'a', 42: '*'}"), SV("{::m}"), input);
+  check(SV("{1, 'a', 42, '*'}"), SV("{::n}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::s}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::?s}"), input);
+
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_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("^^{###(1, 'a'), ##(42, '*')}^^^"), SV("{:^^31:#>11}"), input);
+  check(SV("^^{###(1, 'a'), ##(42, '*')}^^^"), SV("{:^^31:#>11}"), input);
+  check(SV("^^{###(1, 'a'), ##(42, '*')}^^^"), SV("{:^^{}:#>11}"), input, 31);
+  check(SV("^^{###(1, 'a'), ##(42, '*')}^^^"), SV("{:^^{}:#>{}}"), input, 31, 11);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>5}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>{}}"), input, 31);
+
+  check(SV("1: 'a', 42: '*'"), SV("{:n:m}"), input);
+  check(SV("1, 'a', 42, '*'"), SV("{:n:n}"), input);
+  check(SV("{1: 'a', 42: '*'}"), SV("{:m:m}"), input);
+  check(SV("{1, 'a', 42, '*'}"), SV("{:m:n}"), input);
+}
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_pair_tuple(TestFunction check, ExceptionTest check_exception) {
+  test_pair_tuple<CharT>(
+      check, check_exception, std::set{std::make_pair(1, CharT('a')), std::make_pair(42, CharT('*'))});
+  test_pair_tuple<CharT>(
+      check, check_exception, std::set{std::make_tuple(1, CharT('a')), std::make_tuple(42, CharT('*'))});
+}
+
+//
+// Tuple 1
+//
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_tuple_int(TestFunction check, ExceptionTest check_exception) {
+  std::set input{std::make_tuple(42), std::make_tuple(99)};
+
+  check(SV("{(42), (99)}"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{(42), (99)}     "), SV("{:17}"), input);
+  check(SV("{(42), (99)}*****"), SV("{:*<17}"), input);
+  check(SV("__{(42), (99)}___"), SV("{:_^17}"), input);
+  check(SV("#####{(42), (99)}"), SV("{:#>17}"), input);
+
+  check(SV("{(42), (99)}     "), SV("{:{}}"), input, 17);
+  check(SV("{(42), (99)}*****"), SV("{:*<{}}"), input, 17);
+  check(SV("__{(42), (99)}___"), SV("{:_^{}}"), input, 17);
+  check(SV("#####{(42), (99)}"), SV("{:#>{}}"), input, 17);
+
+  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), (99)___"), SV("{:_^15n}"), input);
+
+  // *** type ***
+  check(SV("__{(42), (99)}___"), SV("{:_^17m}"), 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("{(42)   , (99)   }"), SV("{::7}"), input);
+  check(SV("{(42)***, (99)***}"), SV("{::*<7}"), input);
+  check(SV("{_(42)__, _(99)__}"), SV("{::_^7}"), input);
+  check(SV("{###(42), ###(99)}"), SV("{::#>7}"), input);
+
+  check(SV("{(42)   , (99)   }"), SV("{::{}}"), input, 7);
+  check(SV("{(42)***, (99)***}"), SV("{::*<{}}"), input, 7);
+  check(SV("{_(42)__, _(99)__}"), SV("{::_^{}}"), input, 7);
+  check(SV("{###(42), ###(99)}"), SV("{::#>{}}"), input, 7);
+
+  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("{42, 99}"), SV("{::n}"), input);
+  check_exception("The format specifier m requires a pair or a two-element tuple", SV("{::m}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::s}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::?s}"), input);
+
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_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("^^{###(42), ###(99)}^^^"), SV("{:^^23:#>7}"), input);
+  check(SV("^^{###(42), ###(99)}^^^"), SV("{:^^23:#>7}"), input);
+  check(SV("^^{###(42), ###(99)}^^^"), SV("{:^^{}:#>7}"), input, 23);
+  check(SV("^^{###(42), ###(99)}^^^"), SV("{:^^{}:#>{}}"), input, 23, 7);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>5}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>{}}"), input, 23);
+}
+
+//
+// Tuple 3
+//
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_tuple_int_int_int(TestFunction check, ExceptionTest check_exception) {
+  std::set input{std::make_tuple(42, 99, 0), std::make_tuple(1, 10, 100)}; // unordered
+
+  check(SV("{(1, 10, 100), (42, 99, 0)}"), SV("{}"), input);
+
+  // ***** underlying has no format-spec
+
+  // *** align-fill & width ***
+  check(SV("{(1, 10, 100), (42, 99, 0)}     "), SV("{:32}"), input);
+  check(SV("{(1, 10, 100), (42, 99, 0)}*****"), SV("{:*<32}"), input);
+  check(SV("__{(1, 10, 100), (42, 99, 0)}___"), SV("{:_^32}"), input);
+  check(SV("#####{(1, 10, 100), (42, 99, 0)}"), SV("{:#>32}"), input);
+
+  check(SV("{(1, 10, 100), (42, 99, 0)}     "), SV("{:{}}"), input, 32);
+  check(SV("{(1, 10, 100), (42, 99, 0)}*****"), SV("{:*<{}}"), input, 32);
+  check(SV("__{(1, 10, 100), (42, 99, 0)}___"), SV("{:_^{}}"), input, 32);
+  check(SV("#####{(1, 10, 100), (42, 99, 0)}"), SV("{:#>{}}"), input, 32);
+
+  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("__(1, 10, 100), (42, 99, 0)___"), SV("{:_^30n}"), input);
+
+  // *** type ***
+  check(SV("__{(1, 10, 100), (42, 99, 0)}___"), SV("{:_^32m}"), 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("{(1, 10, 100)  , (42, 99, 0)   }"), SV("{::14}"), input);
+  check(SV("{(1, 10, 100)**, (42, 99, 0)***}"), SV("{::*<14}"), input);
+  check(SV("{_(1, 10, 100)_, _(42, 99, 0)__}"), SV("{::_^14}"), input);
+  check(SV("{##(1, 10, 100), ###(42, 99, 0)}"), SV("{::#>14}"), input);
+
+  check(SV("{(1, 10, 100)  , (42, 99, 0)   }"), SV("{::{}}"), input, 14);
+  check(SV("{(1, 10, 100)**, (42, 99, 0)***}"), SV("{::*<{}}"), input, 14);
+  check(SV("{_(1, 10, 100)_, _(42, 99, 0)__}"), SV("{::_^{}}"), input, 14);
+  check(SV("{##(1, 10, 100), ###(42, 99, 0)}"), SV("{::#>{}}"), input, 14);
+
+  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("{1, 10, 100, 42, 99, 0}"), SV("{::n}"), input);
+  check_exception("The format specifier m requires a pair or a two-element tuple", SV("{::m}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::s}"), input);
+  check_exception("The format-spec should consume the input or end with a '}'", SV("{::?s}"), input);
+
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_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("^^{##(1, 10, 100), ###(42, 99, 0)}^^^"), SV("{:^^37:#>14}"), input);
+  check(SV("^^{##(1, 10, 100), ###(42, 99, 0)}^^^"), SV("{:^^37:#>14}"), input);
+  check(SV("^^{##(1, 10, 100), ###(42, 99, 0)}^^^"), SV("{:^^{}:#>14}"), input, 37);
+  check(SV("^^{##(1, 10, 100), ###(42, 99, 0)}^^^"), SV("{:^^{}:#>{}}"), input, 37, 14);
+
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>5}"), input);
+  check_exception("Argument index out of bounds", SV("{:^^{}:#>{}}"), input, 37);
+}
+
+//
+// Adaptor
+//
+
+class adaptor {
+  using adaptee = std::set<int>;
+
+public:
+  using key_type = typename adaptee::key_type;
+  using iterator = typename adaptee::iterator;
+
+  iterator begin() { return data_.begin(); }
+  iterator end() { return data_.end(); }
+
+  explicit adaptor(std::set<int>&& data) : data_(std::move(data)) {}
+
+private:
+  adaptee data_;
+};
+
+static_assert(std::format_kind<adaptor> == std::range_format::set);
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void test_adaptor(TestFunction check, ExceptionTest check_exception) {
+  test_int<CharT>(check, check_exception, adaptor{std::set{1, 42, 2, -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_bool_multiset<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); // Has its own handler with its own parser
+
+  test_pair_tuple<CharT>(check, check_exception);
+  test_tuple_int<CharT>(check, check_exception);
+  test_tuple_int_int_int<CharT>(check, check_exception);
+
+  test_adaptor<CharT>(check, check_exception);
+}
+
+#endif // TEST_STD_UTILITIES_FORMAT_FORMAT_RANGE_FORMAT_RANGE_FMTSET_FORMAT_FUNCTIONS_TESTS_H

diff  --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.functions.vformat.pass.cpp b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.functions.vformat.pass.cpp
new file mode 100644
index 0000000000000..4a8ee4c013b32
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/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::set, 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.fmtset/format.pass.cpp b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.pass.cpp
new file mode 100644
index 0000000000000..651ae86414be6
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.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
+
+// 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::set, 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 <set>
+
+#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::set<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::set<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("{42}"), std::set<int>{42});
+}
+
+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.fmtset/parse.pass.cpp b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/parse.pass.cpp
new file mode 100644
index 0000000000000..753a975513aba
--- /dev/null
+++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/parse.pass.cpp
@@ -0,0 +1,72 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// 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::set, 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 <set>
+
+#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::set<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;
+}


        


More information about the libcxx-commits mailing list