[libcxx-commits] [libcxx] [libc++][format] Don't treat a closing '}' as part of format-spec (PR #81305)

Po-yao Chang via libcxx-commits libcxx-commits at lists.llvm.org
Wed Feb 14 05:32:23 PST 2024


https://github.com/poyaoc97 updated https://github.com/llvm/llvm-project/pull/81305

>From 12dc222f05737d1950c50c4fa426011d39805acf Mon Sep 17 00:00:00 2001
From: Po-yao Chang <poyaoc97 at gmail.com>
Date: Sat, 10 Feb 2024 04:06:01 +0800
Subject: [PATCH 1/3] [libc++][format] Don't treat a closing '}' as part of
 format-spec

This allows:
```
std::println("{}>42", std::thread::id{});
std::println("{}>42", std::span<int>{});
std::println("{}>42", std::pair{42, "Hello"sv});
```
to compile and run.
---
 libcxx/include/__format/format_functions.h                  | 4 ++--
 libcxx/include/__format/format_parse_context.h              | 6 +++++-
 libcxx/include/__format/parser_std_format_spec.h            | 2 +-
 .../utilities/format/format.tuple/format.functions.tests.h  | 1 +
 4 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/libcxx/include/__format/format_functions.h b/libcxx/include/__format/format_functions.h
index 3ee53539f4ee6c..ad0ec354686807 100644
--- a/libcxx/include/__format/format_functions.h
+++ b/libcxx/include/__format/format_functions.h
@@ -251,7 +251,7 @@ __handle_replacement_field(_Iterator __begin, _Iterator __end, _ParseCtx& __pars
   if (__r.__last == __end)
     std::__throw_format_error("The argument index should end with a ':' or a '}'");
 
-  bool __parse = *__r.__last == _CharT(':');
+  bool __parse = __parse_ctx.__should_parse() = *__r.__last == _CharT(':');
   switch (*__r.__last) {
   case _CharT(':'):
     // The arg-id has a format-specifier, advance the input to the format-spec.
@@ -269,7 +269,7 @@ __handle_replacement_field(_Iterator __begin, _Iterator __end, _ParseCtx& __pars
     __arg_t __type = __ctx.arg(__r.__value);
     if (__type == __arg_t::__none)
       std::__throw_format_error("The argument index value is too large for the number of arguments supplied");
-    else if (__type == __arg_t::__handle)
+    else if (__parse && __type == __arg_t::__handle)
       __ctx.__handle(__r.__value).__parse(__parse_ctx);
     else if (__parse)
       __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type);
diff --git a/libcxx/include/__format/format_parse_context.h b/libcxx/include/__format/format_parse_context.h
index aefcd5497f3b9b..74a0d0a6305c69 100644
--- a/libcxx/include/__format/format_parse_context.h
+++ b/libcxx/include/__format/format_parse_context.h
@@ -36,7 +36,8 @@ class _LIBCPP_TEMPLATE_VIS basic_format_parse_context {
         __end_(__fmt.end()),
         __indexing_(__unknown),
         __next_arg_id_(0),
-        __num_args_(__num_args) {}
+        __num_args_(__num_args),
+        __parse_(true) {}
 
   basic_format_parse_context(const basic_format_parse_context&)            = delete;
   basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
@@ -83,6 +84,8 @@ class _LIBCPP_TEMPLATE_VIS basic_format_parse_context {
       std::__throw_format_error("Argument index outside the valid range");
   }
 
+  _LIBCPP_HIDE_FROM_ABI constexpr bool& __should_parse() { return __parse_; }
+
 private:
   iterator __begin_;
   iterator __end_;
@@ -90,6 +93,7 @@ class _LIBCPP_TEMPLATE_VIS basic_format_parse_context {
   _Indexing __indexing_;
   size_t __next_arg_id_;
   size_t __num_args_;
+  bool __parse_;
 };
 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_parse_context);
 
diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h
index cf8af87b212849..d42ce2dbb456aa 100644
--- a/libcxx/include/__format/parser_std_format_spec.h
+++ b/libcxx/include/__format/parser_std_format_spec.h
@@ -355,7 +355,7 @@ class _LIBCPP_TEMPLATE_VIS __parser {
   _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator __parse(_ParseContext& __ctx, __fields __fields) {
     auto __begin = __ctx.begin();
     auto __end   = __ctx.end();
-    if (__begin == __end)
+    if (__begin == __end || !__ctx.__should_parse())
       return __begin;
 
     if (__parse_fill_align(__begin, __end, __fields.__use_range_fill_) && __begin == __end)
diff --git a/libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h b/libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h
index dd99d2070dbb8a..bcb2bc7ebe03b8 100644
--- a/libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h
+++ b/libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h
@@ -77,6 +77,7 @@ void test_tuple_or_pair_int_int(TestFunction check, ExceptionTest check_exceptio
 template <class CharT, class TestFunction, class ExceptionTest, class TupleOrPair>
 void test_tuple_or_pair_int_string(TestFunction check, ExceptionTest check_exception, TupleOrPair&& input) {
   check(SV("(42, \"hello\")"), SV("{}"), input);
+  check(SV("(42, \"hello\")^42"), SV("{}^42"), input);
 
   // *** align-fill & width ***
   check(SV("(42, \"hello\")     "), SV("{:18}"), input);

>From 620a300a64c481cadaacd6ee1a02c487296131cf Mon Sep 17 00:00:00 2001
From: Po-yao Chang <poyaoc97 at gmail.com>
Date: Sun, 11 Feb 2024 22:19:27 +0800
Subject: [PATCH 2/3] Revert "[libc++][format] Don't treat a closing '}' as
 part of format-spec"

This reverts commit 12dc222f05737d1950c50c4fa426011d39805acf.
---
 libcxx/include/__format/format_functions.h                  | 4 ++--
 libcxx/include/__format/format_parse_context.h              | 6 +-----
 libcxx/include/__format/parser_std_format_spec.h            | 2 +-
 .../utilities/format/format.tuple/format.functions.tests.h  | 1 -
 4 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/libcxx/include/__format/format_functions.h b/libcxx/include/__format/format_functions.h
index ad0ec354686807..3ee53539f4ee6c 100644
--- a/libcxx/include/__format/format_functions.h
+++ b/libcxx/include/__format/format_functions.h
@@ -251,7 +251,7 @@ __handle_replacement_field(_Iterator __begin, _Iterator __end, _ParseCtx& __pars
   if (__r.__last == __end)
     std::__throw_format_error("The argument index should end with a ':' or a '}'");
 
-  bool __parse = __parse_ctx.__should_parse() = *__r.__last == _CharT(':');
+  bool __parse = *__r.__last == _CharT(':');
   switch (*__r.__last) {
   case _CharT(':'):
     // The arg-id has a format-specifier, advance the input to the format-spec.
@@ -269,7 +269,7 @@ __handle_replacement_field(_Iterator __begin, _Iterator __end, _ParseCtx& __pars
     __arg_t __type = __ctx.arg(__r.__value);
     if (__type == __arg_t::__none)
       std::__throw_format_error("The argument index value is too large for the number of arguments supplied");
-    else if (__parse && __type == __arg_t::__handle)
+    else if (__type == __arg_t::__handle)
       __ctx.__handle(__r.__value).__parse(__parse_ctx);
     else if (__parse)
       __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type);
diff --git a/libcxx/include/__format/format_parse_context.h b/libcxx/include/__format/format_parse_context.h
index 74a0d0a6305c69..aefcd5497f3b9b 100644
--- a/libcxx/include/__format/format_parse_context.h
+++ b/libcxx/include/__format/format_parse_context.h
@@ -36,8 +36,7 @@ class _LIBCPP_TEMPLATE_VIS basic_format_parse_context {
         __end_(__fmt.end()),
         __indexing_(__unknown),
         __next_arg_id_(0),
-        __num_args_(__num_args),
-        __parse_(true) {}
+        __num_args_(__num_args) {}
 
   basic_format_parse_context(const basic_format_parse_context&)            = delete;
   basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
@@ -84,8 +83,6 @@ class _LIBCPP_TEMPLATE_VIS basic_format_parse_context {
       std::__throw_format_error("Argument index outside the valid range");
   }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr bool& __should_parse() { return __parse_; }
-
 private:
   iterator __begin_;
   iterator __end_;
@@ -93,7 +90,6 @@ class _LIBCPP_TEMPLATE_VIS basic_format_parse_context {
   _Indexing __indexing_;
   size_t __next_arg_id_;
   size_t __num_args_;
-  bool __parse_;
 };
 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_parse_context);
 
diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h
index d42ce2dbb456aa..cf8af87b212849 100644
--- a/libcxx/include/__format/parser_std_format_spec.h
+++ b/libcxx/include/__format/parser_std_format_spec.h
@@ -355,7 +355,7 @@ class _LIBCPP_TEMPLATE_VIS __parser {
   _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator __parse(_ParseContext& __ctx, __fields __fields) {
     auto __begin = __ctx.begin();
     auto __end   = __ctx.end();
-    if (__begin == __end || !__ctx.__should_parse())
+    if (__begin == __end)
       return __begin;
 
     if (__parse_fill_align(__begin, __end, __fields.__use_range_fill_) && __begin == __end)
diff --git a/libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h b/libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h
index bcb2bc7ebe03b8..dd99d2070dbb8a 100644
--- a/libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h
+++ b/libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h
@@ -77,7 +77,6 @@ void test_tuple_or_pair_int_int(TestFunction check, ExceptionTest check_exceptio
 template <class CharT, class TestFunction, class ExceptionTest, class TupleOrPair>
 void test_tuple_or_pair_int_string(TestFunction check, ExceptionTest check_exception, TupleOrPair&& input) {
   check(SV("(42, \"hello\")"), SV("{}"), input);
-  check(SV("(42, \"hello\")^42"), SV("{}^42"), input);
 
   // *** align-fill & width ***
   check(SV("(42, \"hello\")     "), SV("{:18}"), input);

>From b4858eb2cb6a6a2364e503fe22edbbf4f2955465 Mon Sep 17 00:00:00 2001
From: Po-yao Chang <poyaoc97 at gmail.com>
Date: Wed, 14 Feb 2024 21:09:41 +0800
Subject: [PATCH 3/3] [libc++][format] Don't treat a closing '}' as part of
 format-spec

This allows:
```
std::println("{}>42", std::thread::id{});
std::println("{}>42", std::span<int>{});
std::println("{}>42", std::pair{42, "Hello"sv});
std::println("{:}>42", std::thread::id{});
std::println("{:}>42", std::span<int>{});
std::println("{:}>42", std::pair{42, "Hello"sv});
```
to compile and run.
---
 .../include/__format/parser_std_format_spec.h |  6 +-
 .../format.functions.tests.h                  | 44 +++++++----
 .../vector.bool.fmt/format.functions.tests.h  |  6 +-
 .../thread.thread.id/format.functions.tests.h |  6 +-
 .../format.functions.tests.h                  | 46 ++++++++----
 .../format.functions.tests.h                  | 74 ++++++++++++-------
 .../format.functions.tests.h                  | 18 +++--
 .../format.functions.tests.h                  | 62 ++++++++++------
 .../format.tuple/format.functions.tests.h     | 20 +++--
 9 files changed, 189 insertions(+), 93 deletions(-)

diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h
index cf8af87b212849..370b28a22bba77 100644
--- a/libcxx/include/__format/parser_std_format_spec.h
+++ b/libcxx/include/__format/parser_std_format_spec.h
@@ -355,7 +355,7 @@ class _LIBCPP_TEMPLATE_VIS __parser {
   _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator __parse(_ParseContext& __ctx, __fields __fields) {
     auto __begin = __ctx.begin();
     auto __end   = __ctx.end();
-    if (__begin == __end)
+    if (__begin == __end || *__begin == _CharT('}'))
       return __begin;
 
     if (__parse_fill_align(__begin, __end, __fields.__use_range_fill_) && __begin == __end)
@@ -577,9 +577,9 @@ class _LIBCPP_TEMPLATE_VIS __parser {
   _LIBCPP_HIDE_FROM_ABI constexpr void __validate_fill_character(_CharT __fill, bool __use_range_fill) {
     // The forbidden fill characters all code points formed from a single code unit, thus the
     // check can be omitted when more code units are used.
-    if (__use_range_fill && (__fill == _CharT('{') || __fill == _CharT('}') || __fill == _CharT(':')))
+    if (__use_range_fill && (__fill == _CharT('{') || __fill == _CharT(':')))
       std::__throw_format_error("The fill option contains an invalid value");
-    else if (__fill == _CharT('{') || __fill == _CharT('}'))
+    else if (__fill == _CharT('{'))
       std::__throw_format_error("The fill option contains an invalid value");
   }
 
diff --git a/libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.functions.tests.h b/libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.functions.tests.h
index 4eae6ce76633b3..05de1bb12dfa5a 100644
--- a/libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.functions.tests.h
+++ b/libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.functions.tests.h
@@ -30,6 +30,8 @@ template <class CharT, class TestFunction, class ExceptionTest>
 void test_char_default(TestFunction check, ExceptionTest check_exception, auto&& input) {
   // Note when no range-underlying-spec is present the char is escaped,
   check(SV("['H', 'e', 'l', 'l', 'o']"), SV("{}"), input);
+  check(SV("['H', 'e', 'l', 'l', 'o']^42"), SV("{}^42"), input);
+  check(SV("['H', 'e', 'l', 'l', 'o']^42"), SV("{:}^42"), input);
 
   // when one is present there is no escaping,
   check(SV("[H, e, l, l, o]"), SV("{::}"), input);
@@ -49,7 +51,7 @@ void test_char_default(TestFunction check, ExceptionTest check_exception, auto&&
   check(SV("__['H', 'e', 'l', 'l', 'o']___"), SV("{:_^{}}"), input, 30);
   check(SV("#####['H', 'e', 'l', 'l', 'o']"), SV("{:#>{}}"), input, 30);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -89,7 +91,7 @@ void test_char_default(TestFunction check, ExceptionTest check_exception, auto&&
   check(SV("[_H__, _e__, _l__, _l__, _o__]"), SV("{::_^{}}"), input, 4);
   check(SV("[:::H, :::e, :::l, :::l, :::o]"), SV("{:::>{}}"), input, 4);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -149,7 +151,7 @@ void test_char_string(TestFunction check, ExceptionTest check_exception, auto&&
   check(SV("_Hello__"), SV("{:_^{}s}"), input, 8);
   check(SV("###Hello"), SV("{:#>{}s}"), input, 8);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<s}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<s}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<s}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<s}"), input);
 
@@ -202,7 +204,7 @@ void test_char_escaped_string(TestFunction check, ExceptionTest check_exception,
   check(SV(R"(_"Hello"__)"), SV("{:_^{}?s}"), input, 10);
   check(SV(R"(###"Hello")"), SV("{:#>{}?s}"), input, 10);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<?s}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<?s}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<?s}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<?s}"), input);
 
@@ -304,6 +306,8 @@ void test_char_to_wchar(TestFunction check, ExceptionTest check_exception) {
 template <class CharT, class TestFunction, class ExceptionTest>
 void test_bool(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("[true, true, false]"), SV("{}"), input);
+  check(SV("[true, true, false]^42"), SV("{}^42"), input);
+  check(SV("[true, true, false]^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -318,7 +322,7 @@ void test_bool(TestFunction check, ExceptionTest check_exception, auto&& input)
   check(SV("__[true, true, false]___"), SV("{:_^{}}"), input, 24);
   check(SV("#####[true, true, false]"), SV("{:#>{}}"), input, 24);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -360,7 +364,7 @@ void test_bool(TestFunction check, ExceptionTest check_exception, auto&& input)
   check(SV("[_true__, _true__, _false_]"), SV("{::_^{}}"), input, 7);
   check(SV("[:::true, :::true, ::false]"), SV("{:::>{}}"), input, 7);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -418,6 +422,8 @@ void test_bool(TestFunction check, ExceptionTest check_exception) {
 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);
+  check(SV("[-42, 1, 2, 42]^42"), SV("{}^42"), input);
+  check(SV("[-42, 1, 2, 42]^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -432,7 +438,7 @@ void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("__[-42, 1, 2, 42]___"), SV("{:_^{}}"), input, 20);
   check(SV("#####[-42, 1, 2, 42]"), SV("{:#>{}}"), input, 20);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -474,7 +480,7 @@ void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("[_-42_, __1__, __2__, _42__]"), SV("{::_^{}}"), input, 5);
   check(SV("[::-42, ::::1, ::::2, :::42]"), SV("{:::>{}}"), input, 5);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -526,6 +532,8 @@ void test_int(TestFunction check, ExceptionTest check_exception) {
 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);
+  check(SV("[-42.5, 0, 1.25, 42.5]^42"), SV("{}^42"), input);
+  check(SV("[-42.5, 0, 1.25, 42.5]^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -540,7 +548,7 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception, auto
   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 fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -582,7 +590,7 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception, auto
   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 fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -662,6 +670,8 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception) {
 template <class CharT, class TestFunction, class ExceptionTest>
 void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("[0x0]"), SV("{}"), input);
+  check(SV("[0x0]^42"), SV("{}^42"), input);
+  check(SV("[0x0]^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -676,7 +686,7 @@ void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& inpu
   check(SV("__[0x0]___"), SV("{:_^{}}"), input, 10);
   check(SV("#####[0x0]"), SV("{:#>{}}"), input, 10);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -716,7 +726,7 @@ void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& inpu
   check(SV("[_0x0_]"), SV("{::_^{}}"), input, 5);
   check(SV("[::0x0]"), SV("{:::>{}}"), input, 5);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -770,6 +780,8 @@ void test_pointer(TestFunction check, ExceptionTest check_exception) {
 template <class CharT, class TestFunction, class ExceptionTest>
 void test_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV(R"(["Hello", "world"])"), SV("{}"), input);
+  check(SV(R"(["Hello", "world"]^42)"), SV("{}^42"), input);
+  check(SV(R"(["Hello", "world"]^42)"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -784,7 +796,7 @@ void test_string(TestFunction check, ExceptionTest check_exception, auto&& input
   check(SV(R"(__["Hello", "world"]___)"), SV("{:_^{}}"), input, 23);
   check(SV(R"(#####["Hello", "world"])"), SV("{:#>{}}"), input, 23);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -824,7 +836,7 @@ void test_string(TestFunction check, ExceptionTest check_exception, auto&& input
   check(SV(R"([_Hello__, _world__])"), SV("{::_^{}}"), input, 8);
   check(SV(R"([:::Hello, :::world])"), SV("{:::>{}}"), input, 8);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -880,6 +892,8 @@ void test_string(TestFunction check, ExceptionTest check_exception) {
 template <class CharT, class TestFunction, class ExceptionTest>
 void test_status(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("[0xaaaa, 0x5555, 0xaa55]"), SV("{}"), input);
+  check(SV("[0xaaaa, 0x5555, 0xaa55]^42"), SV("{}^42"), input);
+  check(SV("[0xaaaa, 0x5555, 0xaa55]^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -894,7 +908,7 @@ void test_status(TestFunction check, ExceptionTest check_exception, auto&& input
   check(SV("__[0xaaaa, 0x5555, 0xaa55]___"), SV("{:_^{}}"), input, 29);
   check(SV("#####[0xaaaa, 0x5555, 0xaa55]"), SV("{:#>{}}"), input, 29);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
diff --git a/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.tests.h b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.tests.h
index 6c6ab0f6bc220e..e6f8164c536421 100644
--- a/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.tests.h
+++ b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.tests.h
@@ -16,6 +16,8 @@
 template <class CharT, class TestFunction, class ExceptionTest>
 void format_test_vector_bool(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("[true, true, false]"), SV("{}"), input);
+  check(SV("[true, true, false]^42"), SV("{}^42"), input);
+  check(SV("[true, true, false]^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -30,7 +32,7 @@ void format_test_vector_bool(TestFunction check, ExceptionTest check_exception,
   check(SV("__[true, true, false]___"), SV("{:_^{}}"), input, 24);
   check(SV("#####[true, true, false]"), SV("{:#>{}}"), input, 24);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -73,7 +75,7 @@ void format_test_vector_bool(TestFunction check, ExceptionTest check_exception,
   check(SV("[_true__, _true__, _false_]"), SV("{::_^{}}"), input, 7);
   check(SV("[:::true, :::true, ::false]"), SV("{:::>{}}"), input, 7);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.tests.h b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.tests.h
index 898f7cedb2f1c4..cc38a5324b5ca6 100644
--- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.tests.h
+++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.tests.h
@@ -23,6 +23,8 @@ void format_tests(TestFunction check, ExceptionTest check_exception) {
   /***** Test the type specific part *****/
 #if !defined(__APPLE__) && !defined(__FreeBSD__)
   check(SV("0"), SV("{}"), input);
+  check(SV("0^42"), SV("{}^42"), input);
+  check(SV("0^42"), SV("{:}^42"), input);
 
   // *** align-fill & width ***
   check(SV("    0"), SV("{:5}"), input);
@@ -36,6 +38,8 @@ void format_tests(TestFunction check, ExceptionTest check_exception) {
   check(SV("####0"), SV("{:#>{}}"), input, 5);
 #else  // !defined(__APPLE__) && !defined(__FreeBSD__)
   check(SV("0x0"), SV("{}"), input);
+  check(SV("0x0^42"), SV("{}^42"), input);
+  check(SV("0x0^42"), SV("{:}^42"), input);
 
   // *** align-fill & width ***
   check(SV("    0x0"), SV("{:7}"), input);
@@ -50,7 +54,7 @@ void format_tests(TestFunction check, ExceptionTest check_exception) {
 #endif // !defined(__APPLE__) && !defined(__FreeBSD__)
 
   /***** Test the type generic part *****/
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
 
   // *** sign ***
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
index 1e84ebd5439655..2716f461895c8d 100644
--- 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
@@ -27,6 +27,8 @@ 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);
+  check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}^42"), SV("{}^42"), input);
+  check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -41,7 +43,7 @@ void test_char(TestFunction check, ExceptionTest check_exception) {
   check(SV("__{'a': 'A', 'b': 'B', 'c': 'C'}___"), SV("{:_^{}}"), input, 35);
   check(SV("#####{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{:#>{}}"), input, 35);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -86,7 +88,7 @@ void test_char(TestFunction check, ExceptionTest check_exception) {
   check(SV("{#####'a': 'A', #####'b': 'B', #####'c': 'C'}"), SV("{::#>{}}"), input, 13);
 
   check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -137,6 +139,8 @@ void test_char_to_wchar(TestFunction check, ExceptionTest check_exception) {
 
   using CharT = wchar_t;
   check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{}"), input);
+  check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}^42"), SV("{}^42"), input);
+  check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -151,7 +155,7 @@ void test_char_to_wchar(TestFunction check, ExceptionTest check_exception) {
   check(SV("__{'a': 'A', 'b': 'B', 'c': 'C'}___"), SV("{:_^{}}"), input, 35);
   check(SV("#####{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{:#>{}}"), input, 35);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -195,7 +199,7 @@ void test_char_to_wchar(TestFunction check, ExceptionTest check_exception) {
   check(SV("{#####'a': 'A', #####'b': 'B', #####'c': 'C'}"), SV("{::#>{}}"), input, 13);
 
   check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -245,6 +249,8 @@ void test_bool(TestFunction check, ExceptionTest check_exception) {
   std::multimap<bool, int> input{{true, 42}, {false, 0}, {true, 1}};
 
   check(SV("{false: 0, true: 42, true: 1}"), SV("{}"), input);
+  check(SV("{false: 0, true: 42, true: 1}^42"), SV("{}^42"), input);
+  check(SV("{false: 0, true: 42, true: 1}^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -259,7 +265,7 @@ void test_bool(TestFunction check, ExceptionTest check_exception) {
   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 fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -303,7 +309,7 @@ void test_bool(TestFunction check, ExceptionTest check_exception) {
   check(SV("{##false: 0, ##true: 42, ###true: 1}"), SV("{::#>{}}"), input, 10);
 
   check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -345,6 +351,8 @@ void test_bool(TestFunction check, ExceptionTest check_exception) {
 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);
+  check(SV("{-42: 42, 1: -1, 42: -42}^42"), SV("{}^42"), input);
+  check(SV("{-42: 42, 1: -1, 42: -42}^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -359,7 +367,7 @@ void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
   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 fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -403,7 +411,7 @@ void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("{###-42: 42, #####1: -1, ###42: -42}"), SV("{::#>{}}"), input, 10);
 
   check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -452,6 +460,8 @@ 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);
+  check(SV("{-42: 42, 1: -1}^42"), SV("{}^42"), input);
+  check(SV("{-42: 42, 1: -1}^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -466,7 +476,7 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception) {
   check(SV("__{-42: 42, 1: -1}___"), SV("{:_^{}}"), input, 21);
   check(SV("#####{-42: 42, 1: -1}"), SV("{:#>{}}"), input, 21);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -510,7 +520,7 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception) {
   check(SV("{###-42: 42, #####1: -1}"), SV("{::#>{}}"), input, 10);
 
   check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -554,6 +564,8 @@ 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);
+  check(SV("{0x0: 0x0}^42"), SV("{}^42"), input);
+  check(SV("{0x0: 0x0}^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -568,7 +580,7 @@ void test_pointer(TestFunction check, ExceptionTest check_exception) {
   check(SV("__{0x0: 0x0}___"), SV("{:_^{}}"), input, 15);
   check(SV("#####{0x0: 0x0}"), SV("{:#>{}}"), input, 15);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -610,7 +622,7 @@ void test_pointer(TestFunction check, ExceptionTest check_exception) {
   check(SV("{#####0x0: 0x0}"), SV("{::#>{}}"), input, 13);
 
   check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -655,6 +667,8 @@ void test_string(TestFunction check, ExceptionTest check_exception) {
       {STR("hello"), STR("HELLO")}, {STR("world"), STR("WORLD")}};
 
   check(SV(R"({"hello": "HELLO", "world": "WORLD"})"), SV("{}"), input);
+  check(SV(R"({"hello": "HELLO", "world": "WORLD"}^42)"), SV("{}^42"), input);
+  check(SV(R"({"hello": "HELLO", "world": "WORLD"}^42)"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -669,7 +683,7 @@ void test_string(TestFunction check, ExceptionTest check_exception) {
   check(SV(R"(__{"hello": "HELLO", "world": "WORLD"}___)"), SV("{:_^{}}"), input, 41);
   check(SV(R"(#####{"hello": "HELLO", "world": "WORLD"})"), SV("{:#>{}}"), input, 41);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -711,7 +725,7 @@ void test_string(TestFunction check, ExceptionTest check_exception) {
   check(SV(R"({#####"hello": "HELLO", #####"world": "WORLD"})"), SV("{::#>{}}"), input, 21);
 
   check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -756,6 +770,8 @@ 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);
+  check(SV("{0xaa55: 0xaaaa, 0xaa55: 0x5555}^42"), SV("{}^42"), input);
+  check(SV("{0xaa55: 0xaaaa, 0xaa55: 0x5555}^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -770,7 +786,7 @@ void test_status(TestFunction check, ExceptionTest check_exception) {
   check(SV("__{0xaa55: 0xaaaa, 0xaa55: 0x5555}___"), SV("{:_^{}}"), input, 37);
   check(SV("#####{0xaa55: 0xaaaa, 0xaa55: 0x5555}"), SV("{:#>{}}"), input, 37);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
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
index 44a5dbd8ee2e04..a4d8c2d34c333f 100644
--- 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
@@ -30,6 +30,8 @@ void test_char_default(TestFunction check, ExceptionTest check_exception) {
 
   // Note when no range-underlying-spec is present the char is escaped,
   check(SV("{'a', 'b', 'c'}"), SV("{}"), input);
+  check(SV("{'a', 'b', 'c'}^42"), SV("{}^42"), input);
+  check(SV("{'a', 'b', 'c'}^42"), SV("{:}^42"), input);
   // when one is present there is no escaping,
   check(SV("{a, b, c}"), SV("{::}"), input);
   // unless forced by the type specifier.
@@ -48,7 +50,7 @@ void test_char_default(TestFunction check, ExceptionTest check_exception) {
   check(SV("__{'a', 'b', 'c'}___"), SV("{:_^{}}"), input, 20);
   check(SV("#####{'a', 'b', 'c'}"), SV("{:#>{}}"), input, 20);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -86,7 +88,7 @@ void test_char_default(TestFunction check, ExceptionTest check_exception) {
   check(SV("{_a__, _b__, _c__}"), SV("{::_^{}}"), input, 4);
   check(SV("{:::a, :::b, :::c}"), SV("{:::>{}}"), input, 4);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -152,7 +154,7 @@ void test_char_string(TestFunction check, [[maybe_unused]] ExceptionTest check_e
   check(SV("_abc__"), SV("{:_^{}s}"), input, 6);
   check(SV("###abc"), SV("{:#>{}s}"), input, 6);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<s}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<s}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<s}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<s}"), input);
 
@@ -211,7 +213,7 @@ void test_char_escaped_string(TestFunction check, [[maybe_unused]] ExceptionTest
   check(SV(R"(_"abc"__)"), SV("{:_^{}?s}"), input, 8);
   check(SV(R"(###"abc")"), SV("{:#>{}?s}"), input, 8);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<?s}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<?s}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<?s}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<?s}"), input);
 
@@ -265,6 +267,8 @@ void test_char_to_wchar(TestFunction check, ExceptionTest check_exception) {
 
   // Note when no range-underlying-spec is present the char is escaped,
   check(SV("{'a', 'b', 'c'}"), SV("{}"), input);
+  check(SV("{'a', 'b', 'c'}^42"), SV("{}^42"), input);
+  check(SV("{'a', 'b', 'c'}^42"), SV("{:}^42"), input);
   // when one is present there is no escaping,
   check(SV("{a, b, c}"), SV("{::}"), input);
   // unless forced by the type specifier.
@@ -283,7 +287,7 @@ void test_char_to_wchar(TestFunction check, ExceptionTest check_exception) {
   check(SV("__{'a', 'b', 'c'}___"), SV("{:_^{}}"), input, 20);
   check(SV("#####{'a', 'b', 'c'}"), SV("{:#>{}}"), input, 20);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -321,7 +325,7 @@ void test_char_to_wchar(TestFunction check, ExceptionTest check_exception) {
   check(SV("{_a__, _b__, _c__}"), SV("{::_^{}}"), input, 4);
   check(SV("{:::a, :::b, :::c}"), SV("{:::>{}}"), input, 4);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -383,6 +387,8 @@ void test_bool(TestFunction check, ExceptionTest check_exception) {
   std::set input{true, false};
 
   check(SV("{false, true}"), SV("{}"), input);
+  check(SV("{false, true}^42"), SV("{}^42"), input);
+  check(SV("{false, true}^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -397,7 +403,7 @@ void test_bool(TestFunction check, ExceptionTest check_exception) {
   check(SV("__{false, true}___"), SV("{:_^{}}"), input, 18);
   check(SV("#####{false, true}"), SV("{:#>{}}"), input, 18);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -440,7 +446,7 @@ void test_bool(TestFunction check, ExceptionTest check_exception) {
   check(SV("{_false_, _true__}"), SV("{::_^{}}"), input, 7);
   check(SV("{::false, :::true}"), SV("{:::>{}}"), input, 7);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -488,6 +494,8 @@ 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);
+  check(SV("{true, true, false}^42"), SV("{}^42"), input);
+  check(SV("{true, true, false}^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -502,7 +510,7 @@ void test_bool_multiset(TestFunction check, ExceptionTest check_exception) {
   check(SV("__{true, true, false}___"), SV("{:_^{}}"), input, 24);
   check(SV("#####{true, true, false}"), SV("{:#>{}}"), input, 24);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -545,7 +553,7 @@ void test_bool_multiset(TestFunction check, ExceptionTest check_exception) {
   check(SV("{_true__, _true__, _false_}"), SV("{::_^{}}"), input, 7);
   check(SV("{:::true, :::true, ::false}"), SV("{:::>{}}"), input, 7);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -595,6 +603,8 @@ void test_bool_multiset(TestFunction check, ExceptionTest check_exception) {
 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);
+  check(SV("{-42, 1, 2, 42}^42"), SV("{}^42"), input);
+  check(SV("{-42, 1, 2, 42}^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -609,7 +619,7 @@ void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("__{-42, 1, 2, 42}___"), SV("{:_^{}}"), input, 20);
   check(SV("#####{-42, 1, 2, 42}"), SV("{:#>{}}"), input, 20);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -652,7 +662,7 @@ void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("{_-42_, __1__, __2__, _42__}"), SV("{::_^{}}"), input, 5);
   check(SV("{::-42, ::::1, ::::2, :::42}"), SV("{:::>{}}"), input, 5);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -702,6 +712,8 @@ void test_int(TestFunction check, ExceptionTest check_exception) {
 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);
+  check(SV("{-42.5, 0, 1.25, 42.5}^42"), SV("{}^42"), input);
+  check(SV("{-42.5, 0, 1.25, 42.5}^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -716,7 +728,7 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception, auto
   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 fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -759,7 +771,7 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception, auto
   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 fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -838,6 +850,8 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception) {
 template <class CharT, class TestFunction, class ExceptionTest>
 void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("{0x0}"), SV("{}"), input);
+  check(SV("{0x0}^42"), SV("{}^42"), input);
+  check(SV("{0x0}^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -852,7 +866,7 @@ void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& inpu
   check(SV("__{0x0}___"), SV("{:_^{}}"), input, 10);
   check(SV("#####{0x0}"), SV("{:#>{}}"), input, 10);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -893,7 +907,7 @@ void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& inpu
   check(SV("{_0x0_}"), SV("{::_^{}}"), input, 5);
   check(SV("{::0x0}"), SV("{:::>{}}"), input, 5);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -946,6 +960,8 @@ void test_pointer(TestFunction check, ExceptionTest check_exception) {
 template <class CharT, class TestFunction, class ExceptionTest>
 void test_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV(R"({"Hello", "world"})"), SV("{}"), input);
+  check(SV(R"({"Hello", "world"}^42)"), SV("{}^42"), input);
+  check(SV(R"({"Hello", "world"}^42)"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -960,7 +976,7 @@ void test_string(TestFunction check, ExceptionTest check_exception, auto&& input
   check(SV(R"(__{"Hello", "world"}___)"), SV("{:_^{}}"), input, 23);
   check(SV(R"(#####{"Hello", "world"})"), SV("{:#>{}}"), input, 23);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -1001,7 +1017,7 @@ void test_string(TestFunction check, ExceptionTest check_exception, auto&& input
   check(SV(R"({_Hello__, _world__})"), SV("{::_^{}}"), input, 8);
   check(SV(R"({:::Hello, :::world})"), SV("{:::>{}}"), input, 8);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -1057,6 +1073,8 @@ 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);
+  check(SV("{0x5555, 0xaa55, 0xaaaa}^42"), SV("{}^42"), input);
+  check(SV("{0x5555, 0xaa55, 0xaaaa}^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -1071,7 +1089,7 @@ void test_status(TestFunction check, ExceptionTest check_exception) {
   check(SV("__{0x5555, 0xaa55, 0xaaaa}___"), SV("{:_^{}}"), input, 29);
   check(SV("#####{0x5555, 0xaa55, 0xaaaa}"), SV("{:#>{}}"), input, 29);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -1124,6 +1142,8 @@ void test_status(TestFunction check, ExceptionTest check_exception) {
 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);
+  check(SV("{(1, 'a'), (42, '*')}^42"), SV("{}^42"), input);
+  check(SV("{(1, 'a'), (42, '*')}^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -1138,7 +1158,7 @@ void test_pair_tuple(TestFunction check, ExceptionTest check_exception, auto&& i
   check(SV("__{(1, 'a'), (42, '*')}___"), SV("{:_^{}}"), input, 26);
   check(SV("#####{(1, 'a'), (42, '*')}"), SV("{:#>{}}"), input, 26);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -1183,7 +1203,7 @@ void test_pair_tuple(TestFunction check, ExceptionTest check_exception, auto&& i
   check(SV("{###(1, 'a'), ##(42, '*')}"), SV("{::#>{}}"), input, 11);
 
   check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -1246,6 +1266,8 @@ 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);
+  check(SV("{(42), (99)}^42"), SV("{}^42"), input);
+  check(SV("{(42), (99)}^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -1260,7 +1282,7 @@ void test_tuple_int(TestFunction check, ExceptionTest check_exception) {
   check(SV("__{(42), (99)}___"), SV("{:_^{}}"), input, 17);
   check(SV("#####{(42), (99)}"), SV("{:#>{}}"), input, 17);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -1304,7 +1326,7 @@ void test_tuple_int(TestFunction check, ExceptionTest check_exception) {
   check(SV("{###(42), ###(99)}"), SV("{::#>{}}"), input, 7);
 
   check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -1354,6 +1376,8 @@ 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);
+  check(SV("{(1, 10, 100), (42, 99, 0)}^42"), SV("{}^42"), input);
+  check(SV("{(1, 10, 100), (42, 99, 0)}^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -1368,7 +1392,7 @@ void test_tuple_int_int_int(TestFunction check, ExceptionTest check_exception) {
   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 fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -1412,7 +1436,7 @@ void test_tuple_int_int_int(TestFunction check, ExceptionTest check_exception) {
   check(SV("{##(1, 10, 100), ###(42, 99, 0)}"), SV("{::#>{}}"), input, 14);
 
   check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
diff --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtstr/format.functions.tests.h b/libcxx/test/std/utilities/format/format.range/format.range.fmtstr/format.functions.tests.h
index 623af1db8589ad..5d899d75d30fc4 100644
--- a/libcxx/test/std/utilities/format/format.range/format.range.fmtstr/format.functions.tests.h
+++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtstr/format.functions.tests.h
@@ -59,6 +59,8 @@ constexpr std::range_format std::format_kind<test_range_format_debug_string<Cont
 template <class CharT, class TestFunction, class ExceptionTest>
 void test_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("hello"), SV("{}"), input);
+  check(SV("hello^42"), SV("{}^42"), input);
+  check(SV("hello^42"), SV("{:}^42"), input);
 
   // *** align-fill & width ***
   check(SV("hello     "), SV("{:10}"), input);
@@ -71,7 +73,7 @@ void test_string(TestFunction check, ExceptionTest check_exception, auto&& input
   check(SV("__hello___"), SV("{:_^{}}"), input, 10);
   check(SV(":::::hello"), SV("{::>{}}"), input, 10);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
 
   // *** sign ***
@@ -117,6 +119,8 @@ void test_string(TestFunction check, ExceptionTest check_exception) {
 template <class CharT, class TestFunction, class ExceptionTest>
 void test_range_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV(R"([Hello, world])"), SV("{}"), input);
+  check(SV(R"([Hello, world]^42)"), SV("{}^42"), input);
+  check(SV(R"([Hello, world]^42)"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -131,7 +135,7 @@ void test_range_string(TestFunction check, ExceptionTest check_exception, auto&&
   check(SV(R"(__[Hello, world]___)"), SV("{:_^{}}"), input, 19);
   check(SV(R"(#####[Hello, world])"), SV("{:#>{}}"), input, 19);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -172,7 +176,7 @@ void test_range_string(TestFunction check, ExceptionTest check_exception, auto&&
   check(SV(R"([_Hello__, _world__])"), SV("{::_^{}}"), input, 8);
   check(SV(R"([:::Hello, :::world])"), SV("{:::>{}}"), input, 8);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -246,6 +250,8 @@ void test_range_string(TestFunction check, ExceptionTest check_exception) {
 template <class CharT, class TestFunction, class ExceptionTest>
 void test_debug_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("\"hello\""), SV("{}"), input);
+  check(SV("\"hello\"^42"), SV("{}^42"), input);
+  check(SV("\"hello\"^42"), SV("{:}^42"), input);
 
   // *** align-fill & width ***
   check(SV("\"hello\"     "), SV("{:12}"), input);
@@ -258,7 +264,7 @@ void test_debug_string(TestFunction check, ExceptionTest check_exception, auto&&
   check(SV("__\"hello\"___"), SV("{:_^{}}"), input, 12);
   check(SV(":::::\"hello\""), SV("{::>{}}"), input, 12);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
 
   // *** sign ***
@@ -319,7 +325,7 @@ void test_range_debug_string(TestFunction check, ExceptionTest check_exception,
   check(SV(R"(__["Hello", "world"]___)"), SV("{:_^{}}"), input, 23);
   check(SV(R"(#####["Hello", "world"])"), SV("{:#>{}}"), input, 23);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -360,7 +366,7 @@ void test_range_debug_string(TestFunction check, ExceptionTest check_exception,
   check(SV(R"([_"Hello"__, _"world"__])"), SV("{::_^{}}"), input, 10);
   check(SV(R"([:::"Hello", :::"world"])"), SV("{:::>{}}"), input, 10);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
diff --git a/libcxx/test/std/utilities/format/format.range/format.range.formatter/format.functions.tests.h b/libcxx/test/std/utilities/format/format.range/format.range.formatter/format.functions.tests.h
index 1e6c75cc69fe44..917791f7358a07 100644
--- a/libcxx/test/std/utilities/format/format.range/format.range.formatter/format.functions.tests.h
+++ b/libcxx/test/std/utilities/format/format.range/format.range.formatter/format.functions.tests.h
@@ -34,6 +34,8 @@ template <class CharT, class TestFunction, class ExceptionTest>
 void test_char_default(TestFunction check, ExceptionTest check_exception, auto&& input) {
   // Note when no range-underlying-spec is present the char is escaped,
   check(SV("['H', 'e', 'l', 'l', 'o']"), SV("{}"), input);
+  check(SV("['H', 'e', 'l', 'l', 'o']^42"), SV("{}^42"), input);
+  check(SV("['H', 'e', 'l', 'l', 'o']^42"), SV("{:}^42"), input);
 
   // when one is present there is no escaping,
   check(SV("[H, e, l, l, o]"), SV("{::}"), input);
@@ -53,7 +55,7 @@ void test_char_default(TestFunction check, ExceptionTest check_exception, auto&&
   check(SV("__['H', 'e', 'l', 'l', 'o']___"), SV("{:_^{}}"), input, 30);
   check(SV("#####['H', 'e', 'l', 'l', 'o']"), SV("{:#>{}}"), input, 30);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -93,7 +95,7 @@ void test_char_default(TestFunction check, ExceptionTest check_exception, auto&&
   check(SV("[_H__, _e__, _l__, _l__, _o__]"), SV("{::_^{}}"), input, 4);
   check(SV("[:::H, :::e, :::l, :::l, :::o]"), SV("{:::>{}}"), input, 4);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -153,7 +155,7 @@ void test_char_string(TestFunction check, ExceptionTest check_exception, auto&&
   check(SV("_Hello__"), SV("{:_^{}s}"), input, 8);
   check(SV("###Hello"), SV("{:#>{}s}"), input, 8);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<s}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<s}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<s}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<s}"), input);
 
@@ -206,7 +208,7 @@ void test_char_escaped_string(TestFunction check, ExceptionTest check_exception,
   check(SV(R"(_"\"Hello'"__)"), SV("{:_^{}?s}"), input, 13);
   check(SV(R"(###"\"Hello'")"), SV("{:#>{}?s}"), input, 13);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<?s}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<?s}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<?s}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<?s}"), input);
 
@@ -295,6 +297,8 @@ void test_bool(TestFunction check, ExceptionTest check_exception) {
   std::array input{true, true, false};
 
   check(SV("[true, true, false]"), SV("{}"), input);
+  check(SV("[true, true, false]^42"), SV("{}^42"), input);
+  check(SV("[true, true, false]^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -309,7 +313,7 @@ void test_bool(TestFunction check, ExceptionTest check_exception) {
   check(SV("__[true, true, false]___"), SV("{:_^{}}"), input, 24);
   check(SV("#####[true, true, false]"), SV("{:#>{}}"), input, 24);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -351,7 +355,7 @@ void test_bool(TestFunction check, ExceptionTest check_exception) {
   check(SV("[_true__, _true__, _false_]"), SV("{::_^{}}"), input, 7);
   check(SV("[:::true, :::true, ::false]"), SV("{:::>{}}"), input, 7);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -401,6 +405,8 @@ void test_bool(TestFunction check, ExceptionTest check_exception) {
 template <class CharT, class TestFunction, class ExceptionTest>
 void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("[1, 2, 42, -42]"), SV("{}"), input);
+  check(SV("[1, 2, 42, -42]^42"), SV("{}^42"), input);
+  check(SV("[1, 2, 42, -42]^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -415,7 +421,7 @@ void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("__[1, 2, 42, -42]___"), SV("{:_^{}}"), input, 20);
   check(SV("#####[1, 2, 42, -42]"), SV("{:#>{}}"), input, 20);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -457,7 +463,7 @@ void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("[__1__, __2__, _42__, _-42_]"), SV("{::_^{}}"), input, 5);
   check(SV("[::::1, ::::2, :::42, ::-42]"), SV("{:::>{}}"), input, 5);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -510,6 +516,8 @@ void test_int(TestFunction check, ExceptionTest check_exception) {
 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);
+  check(SV("[-42.5, 0, 1.25, 42.5]^42"), SV("{}^42"), input);
+  check(SV("[-42.5, 0, 1.25, 42.5]^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -524,7 +532,7 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception, auto
   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 fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -566,7 +574,7 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception, auto
   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 fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -647,6 +655,8 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception) {
 template <class CharT, class TestFunction, class ExceptionTest>
 void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("[0x0]"), SV("{}"), input);
+  check(SV("[0x0]^42"), SV("{}^42"), input);
+  check(SV("[0x0]^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -661,7 +671,7 @@ void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& inpu
   check(SV("__[0x0]___"), SV("{:_^{}}"), input, 10);
   check(SV("#####[0x0]"), SV("{:#>{}}"), input, 10);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -701,7 +711,7 @@ void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& inpu
   check(SV("[_0x0_]"), SV("{::_^{}}"), input, 5);
   check(SV("[::0x0]"), SV("{:::>{}}"), input, 5);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -754,6 +764,8 @@ void test_pointer(TestFunction check, ExceptionTest check_exception) {
 template <class CharT, class TestFunction, class ExceptionTest>
 void test_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV(R"(["Hello", "world"])"), SV("{}"), input);
+  check(SV(R"(["Hello", "world"]^42)"), SV("{}^42"), input);
+  check(SV(R"(["Hello", "world"]^42)"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -768,7 +780,7 @@ void test_string(TestFunction check, ExceptionTest check_exception, auto&& input
   check(SV(R"(__["Hello", "world"]___)"), SV("{:_^{}}"), input, 23);
   check(SV(R"(#####["Hello", "world"])"), SV("{:#>{}}"), input, 23);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -808,7 +820,7 @@ void test_string(TestFunction check, ExceptionTest check_exception, auto&& input
   check(SV(R"([_Hello__, _world__])"), SV("{::_^{}}"), input, 8);
   check(SV(R"([:::Hello, :::world])"), SV("{:::>{}}"), input, 8);
 
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -865,6 +877,8 @@ void test_status(TestFunction check, ExceptionTest check_exception) {
   std::array input{status::foo, status::bar, status::foobar};
 
   check(SV("[0xaaaa, 0x5555, 0xaa55]"), SV("{}"), input);
+  check(SV("[0xaaaa, 0x5555, 0xaa55]^42"), SV("{}^42"), input);
+  check(SV("[0xaaaa, 0x5555, 0xaa55]^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -879,7 +893,7 @@ void test_status(TestFunction check, ExceptionTest check_exception) {
   check(SV("__[0xaaaa, 0x5555, 0xaa55]___"), SV("{:_^{}}"), input, 29);
   check(SV("#####[0xaaaa, 0x5555, 0xaa55]"), SV("{:#>{}}"), input, 29);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -946,6 +960,8 @@ void test_pair_tuple(TestFunction check, ExceptionTest check_exception, auto&& i
   // thus the char element is not escaped.
   // TODO FMT P2733 addresses this issue.
   check(SV("[(1, 'a'), (42, '*')]"), SV("{}"), input);
+  check(SV("[(1, 'a'), (42, '*')]^42"), SV("{}^42"), input);
+  check(SV("[(1, 'a'), (42, '*')]^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -960,7 +976,7 @@ void test_pair_tuple(TestFunction check, ExceptionTest check_exception, auto&& i
   check(SV("__[(1, 'a'), (42, '*')]___"), SV("{:_^{}}"), input, 26);
   check(SV("#####[(1, 'a'), (42, '*')]"), SV("{:#>{}}"), input, 26);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -1004,7 +1020,7 @@ void test_pair_tuple(TestFunction check, ExceptionTest check_exception, auto&& i
   check(SV("[###(1, 'a'), ##(42, '*')]"), SV("{::#>{}}"), input, 11);
 
   check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -1064,6 +1080,8 @@ void test_tuple_int(TestFunction check, ExceptionTest check_exception) {
   std::array input{std::make_tuple(42), std::make_tuple(99)};
 
   check(SV("[(42), (99)]"), SV("{}"), input);
+  check(SV("[(42), (99)]^42"), SV("{}^42"), input);
+  check(SV("[(42), (99)]^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -1078,7 +1096,7 @@ void test_tuple_int(TestFunction check, ExceptionTest check_exception) {
   check(SV("__[(42), (99)]___"), SV("{:_^{}}"), input, 17);
   check(SV("#####[(42), (99)]"), SV("{:#>{}}"), input, 17);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -1121,7 +1139,7 @@ void test_tuple_int(TestFunction check, ExceptionTest check_exception) {
   check(SV("[###(42), ###(99)]"), SV("{::#>{}}"), input, 7);
 
   check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
@@ -1167,6 +1185,8 @@ void test_tuple_int_int_int(TestFunction check, ExceptionTest check_exception) {
   std::array input{std::make_tuple(42, 99, 0), std::make_tuple(1, 10, 100)};
 
   check(SV("[(42, 99, 0), (1, 10, 100)]"), SV("{}"), input);
+  check(SV("[(42, 99, 0), (1, 10, 100)]^42"), SV("{}^42"), input);
+  check(SV("[(42, 99, 0), (1, 10, 100)]^42"), SV("{:}^42"), input);
 
   // ***** underlying has no format-spec
 
@@ -1181,7 +1201,7 @@ void test_tuple_int_int_int(TestFunction check, ExceptionTest check_exception) {
   check(SV("__[(42, 99, 0), (1, 10, 100)]___"), SV("{:_^{}}"), input, 32);
   check(SV("#####[(42, 99, 0), (1, 10, 100)]"), SV("{:#>{}}"), input, 32);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -1224,7 +1244,7 @@ void test_tuple_int_int_int(TestFunction check, ExceptionTest check_exception) {
   check(SV("[###(42, 99, 0), ##(1, 10, 100)]"), SV("{::#>{}}"), input, 14);
 
   check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
   // *** sign ***
diff --git a/libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h b/libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h
index dd99d2070dbb8a..dc57693469fec4 100644
--- a/libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h
+++ b/libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h
@@ -30,6 +30,8 @@ struct std::formatter<color, CharT> : std::formatter<basic_string_view<CharT>, C
 template <class CharT, class TestFunction, class ExceptionTest, class TupleOrPair>
 void test_tuple_or_pair_int_int(TestFunction check, ExceptionTest check_exception, TupleOrPair&& input) {
   check(SV("(42, 99)"), SV("{}"), input);
+  check(SV("(42, 99)^42"), SV("{}^42"), input);
+  check(SV("(42, 99)^42"), SV("{:}^42"), input);
 
   // *** align-fill & width ***
   check(SV("(42, 99)     "), SV("{:13}"), input);
@@ -42,7 +44,7 @@ void test_tuple_or_pair_int_int(TestFunction check, ExceptionTest check_exceptio
   check(SV("__(42, 99)___"), SV("{:_^{}}"), input, 13);
   check(SV("#####(42, 99)"), SV("{:#>{}}"), input, 13);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -77,6 +79,8 @@ void test_tuple_or_pair_int_int(TestFunction check, ExceptionTest check_exceptio
 template <class CharT, class TestFunction, class ExceptionTest, class TupleOrPair>
 void test_tuple_or_pair_int_string(TestFunction check, ExceptionTest check_exception, TupleOrPair&& input) {
   check(SV("(42, \"hello\")"), SV("{}"), input);
+  check(SV("(42, \"hello\")^42"), SV("{}^42"), input);
+  check(SV("(42, \"hello\")^42"), SV("{:}^42"), input);
 
   // *** align-fill & width ***
   check(SV("(42, \"hello\")     "), SV("{:18}"), input);
@@ -89,7 +93,7 @@ void test_tuple_or_pair_int_string(TestFunction check, ExceptionTest check_excep
   check(SV("__(42, \"hello\")___"), SV("{:_^{}}"), input, 18);
   check(SV("#####(42, \"hello\")"), SV("{:#>{}}"), input, 18);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -167,6 +171,8 @@ void test_tuple_int(TestFunction check, ExceptionTest check_exception) {
   auto input = std::make_tuple(42);
 
   check(SV("(42)"), SV("{}"), input);
+  check(SV("(42)^42"), SV("{}^42"), input);
+  check(SV("(42)^42"), SV("{:}^42"), input);
 
   // *** align-fill & width ***
   check(SV("(42)     "), SV("{:9}"), input);
@@ -179,7 +185,7 @@ void test_tuple_int(TestFunction check, ExceptionTest check_exception) {
   check(SV("__(42)___"), SV("{:_^{}}"), input, 9);
   check(SV("#####(42)"), SV("{:#>{}}"), input, 9);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -216,6 +222,8 @@ void test_tuple_int_string_color(TestFunction check, ExceptionTest check_excepti
   const auto input = std::make_tuple(42, SV("hello"), color::red);
 
   check(SV("(42, \"hello\", \"red\")"), SV("{}"), input);
+  check(SV("(42, \"hello\", \"red\")^42"), SV("{}^42"), input);
+  check(SV("(42, \"hello\", \"red\")^42"), SV("{:}^42"), input);
 
   // *** align-fill & width ***
   check(SV("(42, \"hello\", \"red\")     "), SV("{:25}"), input);
@@ -228,7 +236,7 @@ void test_tuple_int_string_color(TestFunction check, ExceptionTest check_excepti
   check(SV("__(42, \"hello\", \"red\")___"), SV("{:_^{}}"), input, 25);
   check(SV("#####(42, \"hello\", \"red\")"), SV("{:#>{}}"), input, 25);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
@@ -289,6 +297,8 @@ void test_nested(TestFunction check, ExceptionTest check_exception, Nested&& inp
   // addressed this.
 
   check(SV("(42, (\"hello\", \"red\"))"), SV("{}"), input);
+  check(SV("(42, (\"hello\", \"red\"))^42"), SV("{}^42"), input);
+  check(SV("(42, (\"hello\", \"red\"))^42"), SV("{:}^42"), input);
 
   // *** align-fill & width ***
   check(SV("(42, (\"hello\", \"red\"))     "), SV("{:27}"), input);
@@ -301,7 +311,7 @@ void test_nested(TestFunction check, ExceptionTest check_exception, Nested&& inp
   check(SV("__(42, (\"hello\", \"red\"))___"), SV("{:_^{}}"), input, 27);
   check(SV("#####(42, (\"hello\", \"red\"))"), SV("{:#>{}}"), input, 27);
 
-  check_exception("The fill option contains an invalid value", SV("{:}<}"), input);
+  check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 



More information about the libcxx-commits mailing list