[libcxx-commits] [libcxx] 0e9979a - [libc++][format][1/6] Reduce binary size.

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Wed Dec 1 08:50:22 PST 2021


Author: Mark de Wever
Date: 2021-12-01T17:50:17+01:00
New Revision: 0e9979affe2941b25df61c1219ba9ed64f4fbf6c

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

LOG: [libc++][format][1/6] Reduce binary size.

This removes the `format_args_t` from `<format>` and adjusts the type of
the `format_args` for the `vformat_to` overloads.

The `format_context` uses a `back_insert_iterator<string>` therefore the
new `output_iterator` function uses a `string` as its temporary storage
buffer. This isn't ideal. The next patches in this series will improve
this. These improvements make it easy to also improve `format_to_n` and
`formatted_size`.

This addresses P2216 `6. Binary size`.
P2216 `5. Compile-time checks` are not part of this change.

Implements parts of:
- P2216 std::format improvements

Depends on D103670

Reviewed By: ldionne, #libc

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

Added: 
    

Modified: 
    libcxx/docs/Status/Cxx20Papers.csv
    libcxx/include/format
    libcxx/include/version
    libcxx/test/std/language.support/support.limits/support.limits.general/format.version.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
    libcxx/test/std/utilities/format/format.arguments/format.arg.store/make_format_args.sh.cpp
    libcxx/test/std/utilities/format/format.arguments/format.args/types.compile.pass.cpp
    libcxx/test/std/utilities/format/format.functions/format_tests.h
    libcxx/test/std/utilities/format/format.functions/locale-specific_form.pass.cpp
    libcxx/test/std/utilities/format/format.functions/vformat.locale.pass.cpp
    libcxx/test/std/utilities/format/format.functions/vformat.pass.cpp
    libcxx/test/std/utilities/format/format.functions/vformat_to.locale.pass.cpp
    libcxx/test/std/utilities/format/format.functions/vformat_to.pass.cpp
    libcxx/utils/generate_feature_test_macro_components.py

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv
index d2ce8ddf5df58..c456212b859dc 100644
--- a/libcxx/docs/Status/Cxx20Papers.csv
+++ b/libcxx/docs/Status/Cxx20Papers.csv
@@ -196,7 +196,7 @@
 "`P2231R1 <https://wg21.link/P2231R1>`__","LWG","Missing constexpr in std::optional and std::variant","June 2021","|In progress|","13.0"
 "`P2325R3 <https://wg21.link/P2325R3>`__","LWG","Views should not be required to be default constructible","June 2021","|In progress|",""
 "`P2210R2 <https://wg21.link/P2210R2>`__","LWG",Superior String Splitting,"June 2021","",""
-"`P2216R3 <https://wg21.link/P2216R3>`__","LWG",std::format improvements,"June 2021","",""
+"`P2216R3 <https://wg21.link/P2216R3>`__","LWG",std::format improvements,"June 2021","|Partial|",""
 "`P2281R1 <https://wg21.link/P2281R1>`__","LWG",Clarifying range adaptor objects,"June 2021","",""
 "`P2328R1 <https://wg21.link/P2328R1>`__","LWG",join_view should join all views of ranges,"June 2021","",""
 "`P2367R0 <https://wg21.link/P2367R0>`__","LWG",Remove misuses of list-initialization from Clause 24,"June 2021","",""

diff  --git a/libcxx/include/format b/libcxx/include/format
index e1d47c9f84dd1..788b9c299abc0 100644
--- a/libcxx/include/format
+++ b/libcxx/include/format
@@ -51,9 +51,6 @@ namespace std {
   using wformat_args = basic_format_args<wformat_context>;
 
 
-  template<class Out, class charT>
-    using format_args_t = basic_format_args<basic_format_context<Out, charT>>;
-
   // [format.functions], formatting functions
   template<class... Args>
     string format(string_view fmt, const Args&... args);
@@ -79,17 +76,15 @@ namespace std {
     Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args);
 
   template<class Out>
-    Out vformat_to(Out out, string_view fmt,
-                   format_args_t<type_identity_t<Out>, char> args);
+    Out vformat_to(Out out, string_view fmt, format_args args);
   template<class Out>
-    Out vformat_to(Out out, wstring_view fmt,
-                   format_args_t<type_identity_t<Out>, wchar_t> args);
+    Out vformat_to(Out out, wstring_view fmt, wformat_args args);
   template<class Out>
     Out vformat_to(Out out, const locale& loc, string_view fmt,
-                   format_args_t<type_identity_t<Out>, char> args);
+                   format_args char> args);
   template<class Out>
     Out vformat_to(Out out, const locale& loc, wstring_view fmt,
-                   format_args_t<type_identity_t<Out>, wchar_t> args);
+                   wformat_args args);
 
   template<class Out> struct format_to_n_result {
     Out out;
@@ -325,9 +320,6 @@ using format_args = basic_format_args<format_context>;
 using wformat_args = basic_format_args<wformat_context>;
 #endif
 
-template <class _OutIt, class _CharT>
-using format_args_t = basic_format_args<basic_format_context<_OutIt, _CharT>>;
-
 template <class _Context, class... _Args>
 struct _LIBCPP_TEMPLATE_VIS __format_arg_store {
   // TODO FMT Use a built-in array.
@@ -436,51 +428,55 @@ __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
 
 } // namespace __format
 
-template <class _OutIt, class _CharT>
+template <class _OutIt, class _CharT, class _FormatOutIt>
 requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
-    __vformat_to(_OutIt __out_it, basic_string_view<_CharT> __fmt,
-                 format_args_t<type_identity_t<_OutIt>, _CharT> __args) {
-  return __format::__vformat_to(
-      basic_format_parse_context{__fmt, __args.__size()},
-      _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
+    __vformat_to(
+        _OutIt __out_it, basic_string_view<_CharT> __fmt,
+        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
+  if constexpr (same_as<_OutIt, _FormatOutIt>)
+    return _VSTD::__format::__vformat_to(
+        basic_format_parse_context{__fmt, __args.__size()},
+        _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
+  else {
+    basic_string<_CharT> __str;
+    _VSTD::__format::__vformat_to(
+        basic_format_parse_context{__fmt, __args.__size()},
+        _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args));
+    return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it));
+  }
 }
 
 template <output_iterator<const char&> _OutIt>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
-vformat_to(_OutIt __out_it, string_view __fmt,
-           format_args_t<type_identity_t<_OutIt>, char> __args) {
+_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
+vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) {
   return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
 }
 
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 template <output_iterator<const wchar_t&> _OutIt>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
-vformat_to(_OutIt __out_it, wstring_view __fmt,
-           format_args_t<type_identity_t<_OutIt>, wchar_t> __args) {
+_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
+vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) {
   return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
 }
 #endif
 
 template <output_iterator<const char&> _OutIt, class... _Args>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
+_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
 format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) {
-  return _VSTD::vformat_to(
-      _VSTD::move(__out_it), __fmt,
-      _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...));
+  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
+                           _VSTD::make_format_args(__args...));
 }
 
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
+_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
 format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) {
-  return _VSTD::vformat_to(
-      _VSTD::move(__out_it), __fmt,
-      _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>(
-          __args...));
+  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
+                           _VSTD::make_wformat_args(__args...));
 }
 #endif
 
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
+_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
 vformat(string_view __fmt, format_args __args) {
   string __res;
   _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
@@ -488,7 +484,7 @@ vformat(string_view __fmt, format_args __args) {
 }
 
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
+_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
 vformat(wstring_view __fmt, wformat_args __args) {
   wstring __res;
   _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
@@ -497,14 +493,14 @@ vformat(wstring_view __fmt, wformat_args __args) {
 #endif
 
 template <class... _Args>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
+_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
 format(string_view __fmt, const _Args&... __args) {
   return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
 }
 
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 template <class... _Args>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
+_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
 format(wstring_view __fmt, const _Args&... __args) {
   return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
 }
@@ -556,54 +552,59 @@ formatted_size(wstring_view __fmt, const _Args&... __args) {
 
 #ifndef _LIBCPP_HAS_NO_LOCALIZATION
 
-template <class _OutIt, class _CharT>
+template <class _OutIt, class _CharT, class _FormatOutIt>
 requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
-    __vformat_to(_OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
-                 format_args_t<type_identity_t<_OutIt>, _CharT> __args) {
-  return __format::__vformat_to(
-      basic_format_parse_context{__fmt, __args.__size()},
-      _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
-                                     _VSTD::move(__loc)));
+    __vformat_to(
+        _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
+        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
+  if constexpr (same_as<_OutIt, _FormatOutIt>)
+    return _VSTD::__format::__vformat_to(
+        basic_format_parse_context{__fmt, __args.__size()},
+        _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
+                                       _VSTD::move(__loc)));
+  else {
+    basic_string<_CharT> __str;
+    _VSTD::__format::__vformat_to(
+        basic_format_parse_context{__fmt, __args.__size()},
+        _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args,
+                                       _VSTD::move(__loc)));
+    return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it));
+  }
 }
 
 template <output_iterator<const char&> _OutIt>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
-vformat_to(_OutIt __out_it, locale __loc, string_view __fmt,
-           format_args_t<type_identity_t<_OutIt>, char> __args) {
+_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
+    _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) {
   return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
                              __args);
 }
 
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 template <output_iterator<const wchar_t&> _OutIt>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
-vformat_to(_OutIt __out_it, locale __loc, wstring_view __fmt,
-           format_args_t<type_identity_t<_OutIt>, wchar_t> __args) {
+_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
+    _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) {
   return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
                              __args);
 }
 #endif
 
 template <output_iterator<const char&> _OutIt, class... _Args>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
+_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
     _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) {
-  return _VSTD::vformat_to(
-      _VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
-      _VSTD::make_format_args<basic_format_context<_OutIt, char>>(__args...));
+  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
+                           _VSTD::make_format_args(__args...));
 }
 
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
+_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
     _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) {
-  return _VSTD::vformat_to(
-      _VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
-      _VSTD::make_format_args<basic_format_context<_OutIt, wchar_t>>(
-          __args...));
+  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
+                           _VSTD::make_wformat_args(__args...));
 }
 #endif
 
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
+_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
 vformat(locale __loc, string_view __fmt, format_args __args) {
   string __res;
   _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
@@ -612,7 +613,7 @@ vformat(locale __loc, string_view __fmt, format_args __args) {
 }
 
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
+_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
 vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
   wstring __res;
   _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
@@ -622,7 +623,7 @@ vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
 #endif
 
 template <class... _Args>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
+_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
 format(locale __loc, string_view __fmt, const _Args&... __args) {
   return _VSTD::vformat(_VSTD::move(__loc), __fmt,
                         _VSTD::make_format_args(__args...));
@@ -630,7 +631,7 @@ format(locale __loc, string_view __fmt, const _Args&... __args) {
 
 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 template <class... _Args>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
+_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
 format(locale __loc, wstring_view __fmt, const _Args&... __args) {
   return _VSTD::vformat(_VSTD::move(__loc), __fmt,
                         _VSTD::make_wformat_args(__args...));

diff  --git a/libcxx/include/version b/libcxx/include/version
index 4b6f9b3ed7107..9322c3b8c05d1 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -73,7 +73,7 @@ __cpp_lib_exchange_function                             201304L <utility>
 __cpp_lib_execution                                     201902L <execution>
                                                         201603L // C++17
 __cpp_lib_filesystem                                    201703L <filesystem>
-__cpp_lib_format                                        201907L <format>
+__cpp_lib_format                                        202106L <format>
 __cpp_lib_gcd_lcm                                       201606L <numeric>
 __cpp_lib_generic_associative_lookup                    201304L <map> <set>
 __cpp_lib_generic_unordered_lookup                      201811L <unordered_map> <unordered_set>
@@ -301,7 +301,7 @@ __cpp_lib_void_t                                        201411L <type_traits>
 # undef  __cpp_lib_execution
 // # define __cpp_lib_execution                            201902L
 # if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format)
-// #   define __cpp_lib_format                             201907L
+// #   define __cpp_lib_format                             202106L
 # endif
 # define __cpp_lib_generic_unordered_lookup             201811L
 # define __cpp_lib_int_pow2                             202002L

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/format.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/format.version.pass.cpp
index 67fc1af3a9b23..82e3a66355d3f 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/format.version.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/format.version.pass.cpp
@@ -18,7 +18,7 @@
 // Test the feature test macros defined by <format>
 
 /*  Constant            Value
-    __cpp_lib_format    201907L [C++20]
+    __cpp_lib_format    202106L [C++20]
 */
 
 #include <format>
@@ -48,8 +48,8 @@
 #   ifndef __cpp_lib_format
 #     error "__cpp_lib_format should be defined in c++20"
 #   endif
-#   if __cpp_lib_format != 201907L
-#     error "__cpp_lib_format should have the value 201907L in c++20"
+#   if __cpp_lib_format != 202106L
+#     error "__cpp_lib_format should have the value 202106L in c++20"
 #   endif
 # else // _LIBCPP_VERSION
 #   ifdef __cpp_lib_format
@@ -63,8 +63,8 @@
 #   ifndef __cpp_lib_format
 #     error "__cpp_lib_format should be defined in c++2b"
 #   endif
-#   if __cpp_lib_format != 201907L
-#     error "__cpp_lib_format should have the value 201907L in c++2b"
+#   if __cpp_lib_format != 202106L
+#     error "__cpp_lib_format should have the value 202106L in c++2b"
 #   endif
 # else // _LIBCPP_VERSION
 #   ifdef __cpp_lib_format

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
index 7c1ac22a74768..fe940690f0a88 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
@@ -68,7 +68,7 @@
     __cpp_lib_execution                            201603L [C++17]
                                                    201902L [C++20]
     __cpp_lib_filesystem                           201703L [C++17]
-    __cpp_lib_format                               201907L [C++20]
+    __cpp_lib_format                               202106L [C++20]
     __cpp_lib_gcd_lcm                              201606L [C++17]
     __cpp_lib_generic_associative_lookup           201304L [C++14]
     __cpp_lib_generic_unordered_lookup             201811L [C++20]
@@ -2527,8 +2527,8 @@
 #   ifndef __cpp_lib_format
 #     error "__cpp_lib_format should be defined in c++20"
 #   endif
-#   if __cpp_lib_format != 201907L
-#     error "__cpp_lib_format should have the value 201907L in c++20"
+#   if __cpp_lib_format != 202106L
+#     error "__cpp_lib_format should have the value 202106L in c++20"
 #   endif
 # else // _LIBCPP_VERSION
 #   ifdef __cpp_lib_format
@@ -3655,8 +3655,8 @@
 #   ifndef __cpp_lib_format
 #     error "__cpp_lib_format should be defined in c++2b"
 #   endif
-#   if __cpp_lib_format != 201907L
-#     error "__cpp_lib_format should have the value 201907L in c++2b"
+#   if __cpp_lib_format != 202106L
+#     error "__cpp_lib_format should have the value 202106L in c++2b"
 #   endif
 # else // _LIBCPP_VERSION
 #   ifdef __cpp_lib_format

diff  --git a/libcxx/test/std/utilities/format/format.arguments/format.arg.store/make_format_args.sh.cpp b/libcxx/test/std/utilities/format/format.arguments/format.arg.store/make_format_args.sh.cpp
index af174ea1c1363..f3539b3c4ad71 100644
--- a/libcxx/test/std/utilities/format/format.arguments/format.arg.store/make_format_args.sh.cpp
+++ b/libcxx/test/std/utilities/format/format.arguments/format.arg.store/make_format_args.sh.cpp
@@ -20,6 +20,7 @@
 // - otherwise, if T is char and char_type is wchar_t, initializes value with static_cast<wchar_t>(v);
 
 #include <format>
+#include <string>
 
 void test() {
   std::make_format_args<std::basic_format_context<

diff  --git a/libcxx/test/std/utilities/format/format.arguments/format.args/types.compile.pass.cpp b/libcxx/test/std/utilities/format/format.arguments/format.args/types.compile.pass.cpp
index cac83f7898065..82b506b8f5bde 100644
--- a/libcxx/test/std/utilities/format/format.arguments/format.args/types.compile.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.arguments/format.args/types.compile.pass.cpp
@@ -14,8 +14,6 @@
 // Namespace std typedefs:
 // using format_args = basic_format_args<format_context>;
 // using wformat_args = basic_format_args<wformat_context>;
-// template<class Out, class charT>
-//   using format_args_t = basic_format_args<basic_format_context<Out, charT>>;
 
 #include <format>
 #include <vector>
@@ -30,24 +28,5 @@ static_assert(std::is_same_v<std::wformat_args,
                              std::basic_format_args<std::wformat_context>>);
 #endif
 
-static_assert(std::is_same_v<
-              std::format_args_t<std::back_insert_iterator<std::string>, char>,
-              std::basic_format_args<std::basic_format_context<
-                  std::back_insert_iterator<std::string>, char>>>);
-
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-static_assert(
-    std::is_same_v<
-        std::format_args_t<std::back_insert_iterator<std::wstring>, wchar_t>,
-        std::basic_format_args<std::basic_format_context<
-            std::back_insert_iterator<std::wstring>, wchar_t>>>);
-#endif
-
-static_assert(
-    std::is_same_v<
-        std::format_args_t<std::back_insert_iterator<std::vector<char>>, char>,
-        std::basic_format_args<std::basic_format_context<
-            std::back_insert_iterator<std::vector<char>>, char>>>);
-
 // Required for MSVC internal test runner compatibility.
 int main(int, char**) { return 0; }

diff  --git a/libcxx/test/std/utilities/format/format.functions/format_tests.h b/libcxx/test/std/utilities/format/format.functions/format_tests.h
index a2d71a9881dbc..ca73dbb71dc8a 100644
--- a/libcxx/test/std/utilities/format/format.functions/format_tests.h
+++ b/libcxx/test/std/utilities/format/format.functions/format_tests.h
@@ -8,6 +8,8 @@
 #ifndef TEST_STD_UTILITIES_FORMAT_FORMAT_FUNCTIONS_FORMAT_TESTS_H
 #define TEST_STD_UTILITIES_FORMAT_FORMAT_FUNCTIONS_FORMAT_TESTS_H
 
+#include <format>
+
 #include "make_string.h"
 
 // In this file the following template types are used:
@@ -17,6 +19,24 @@
 #define STR(S) MAKE_STRING(CharT, S)
 #define CSTR(S) MAKE_CSTRING(CharT, S)
 
+template <class T>
+struct context {};
+
+template <>
+struct context<char> {
+  using type = std::format_context;
+};
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+template <>
+struct context<wchar_t> {
+  using type = std::wformat_context;
+};
+#endif
+
+template <class T>
+using context_t = typename context<T>::type;
+
 template <class CharT>
 std::vector<std::basic_string<CharT>> invalid_types(std::string valid) {
   std::vector<std::basic_string<CharT>> result;

diff  --git a/libcxx/test/std/utilities/format/format.functions/locale-specific_form.pass.cpp b/libcxx/test/std/utilities/format/format.functions/locale-specific_form.pass.cpp
index d49ac66e3d1ff..ada7f09f0fd3e 100644
--- a/libcxx/test/std/utilities/format/format.functions/locale-specific_form.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.functions/locale-specific_form.pass.cpp
@@ -49,17 +49,15 @@
 //    Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args);
 //
 //  template<class Out>
-//    Out vformat_to(Out out, string_view fmt,
-//                   format_args_t<type_identity_t<Out>, char> args);
+//    Out vformat_to(Out out, string_view fmt, format_args args);
 //  template<class Out>
-//    Out vformat_to(Out out, wstring_view fmt,
-//                   format_args_t<type_identity_t<Out>, wchar_t> args);
+//    Out vformat_to(Out out, wstring_view fmt, wformat_args args);
 //  template<class Out>
 //    Out vformat_to(Out out, const locale& loc, string_view fmt,
-//                   format_args_t<type_identity_t<Out>, char> args);
+//                   format_args args);
 //  template<class Out>
 //    Out vformat_to(Out out, const locale& loc, wstring_view fmt,
-//                   format_args_t<type_identity_t<Out>, wchar_t> args);
+//                   wformat_arg args);
 //
 //  template<class Out> struct format_to_n_result {
 //    Out out;
@@ -98,6 +96,7 @@
 #include "test_macros.h"
 #include "make_string.h"
 #include "platform_support.h" // locale name macros
+#include "format_tests.h"
 
 #define STR(S) MAKE_STRING(CharT, S)
 
@@ -138,10 +137,8 @@ void test(std::basic_string<CharT> expected, std::basic_string<CharT> fmt,
   }
   // *** vformat ***
   {
-    std::basic_string<CharT> out = std::vformat(
-        fmt, std::make_format_args<std::basic_format_context<
-                 std::back_insert_iterator<std::basic_string<CharT>>, CharT>>(
-                 args...));
+    std::basic_string<CharT> out =
+        std::vformat(fmt, std::make_format_args<context_t<CharT>>(args...));
     assert(out == expected);
   }
   // *** format_to ***
@@ -154,10 +151,8 @@ void test(std::basic_string<CharT> expected, std::basic_string<CharT> fmt,
   // *** vformat_to ***
   {
     std::basic_string<CharT> out(expected.size(), CharT(' '));
-    auto it = std::vformat_to(
-        out.begin(), fmt,
-        std::make_format_args<std::basic_format_context<
-            typename std::basic_string<CharT>::iterator, CharT>>(args...));
+    auto it = std::vformat_to(out.begin(), fmt,
+                              std::make_format_args<context_t<CharT>>(args...));
     assert(it == out.end());
     assert(out == expected);
   }
@@ -195,10 +190,7 @@ void test(std::basic_string<CharT> expected, std::locale loc,
   // *** vformat ***
   {
     std::basic_string<CharT> out = std::vformat(
-        loc, fmt,
-        std::make_format_args<std::basic_format_context<
-            std::back_insert_iterator<std::basic_string<CharT>>, CharT>>(
-            args...));
+        loc, fmt, std::make_format_args<context_t<CharT>>(args...));
     assert(out == expected);
   }
   // *** format_to ***
@@ -211,10 +203,8 @@ void test(std::basic_string<CharT> expected, std::locale loc,
   // *** vformat_to ***
   {
     std::basic_string<CharT> out(expected.size(), CharT(' '));
-    auto it = std::vformat_to(
-        out.begin(), loc, fmt,
-        std::make_format_args<std::basic_format_context<
-            typename std::basic_string<CharT>::iterator, CharT>>(args...));
+    auto it = std::vformat_to(out.begin(), loc, fmt,
+                              std::make_format_args<context_t<CharT>>(args...));
     assert(it == out.end());
     assert(out == expected);
   }

diff  --git a/libcxx/test/std/utilities/format/format.functions/vformat.locale.pass.cpp b/libcxx/test/std/utilities/format/format.functions/vformat.locale.pass.cpp
index 08e067e9f2d61..eb98907098c90 100644
--- a/libcxx/test/std/utilities/format/format.functions/vformat.locale.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.functions/vformat.locale.pass.cpp
@@ -28,10 +28,7 @@ auto test = []<class CharT, class... Args>(std::basic_string<CharT> expected,
                                            std::basic_string<CharT> fmt,
                                            const Args&... args) {
   std::basic_string<CharT> out = std::vformat(
-      std::locale(), fmt,
-      std::make_format_args<std::basic_format_context<
-          std::back_insert_iterator<std::basic_string<CharT>>, CharT>>(
-          args...));
+      std::locale(), fmt, std::make_format_args<context_t<CharT>>(args...));
   assert(out == expected);
 };
 
@@ -39,11 +36,8 @@ auto test_exception = []<class CharT, class... Args>(
     std::string_view what, std::basic_string<CharT> fmt, const Args&... args) {
 #ifndef TEST_HAS_NO_EXCEPTIONS
   try {
-    std::vformat(
-        std::locale(), fmt,
-        std::make_format_args<std::basic_format_context<
-            std::back_insert_iterator<std::basic_string<CharT>>, CharT>>(
-            args...));
+    std::vformat(std::locale(), fmt,
+                 std::make_format_args<context_t<CharT>>(args...));
     assert(false);
   } catch (std::format_error& e) {
     LIBCPP_ASSERT(e.what() == what);

diff  --git a/libcxx/test/std/utilities/format/format.functions/vformat.pass.cpp b/libcxx/test/std/utilities/format/format.functions/vformat.pass.cpp
index c4df0a84f445d..26f7ae0f35c11 100644
--- a/libcxx/test/std/utilities/format/format.functions/vformat.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.functions/vformat.pass.cpp
@@ -26,10 +26,8 @@
 auto test = []<class CharT, class... Args>(std::basic_string<CharT> expected,
                                            std::basic_string<CharT> fmt,
                                            const Args&... args) {
-  std::basic_string<CharT> out = std::vformat(
-      fmt, std::make_format_args<std::basic_format_context<
-               std::back_insert_iterator<std::basic_string<CharT>>, CharT>>(
-               args...));
+  std::basic_string<CharT> out =
+      std::vformat(fmt, std::make_format_args<context_t<CharT>>(args...));
   assert(out == expected);
 };
 
@@ -37,10 +35,7 @@ auto test_exception = []<class CharT, class... Args>(
     std::string_view what, std::basic_string<CharT> fmt, const Args&... args) {
 #ifndef TEST_HAS_NO_EXCEPTIONS
   try {
-    std::vformat(
-        fmt, std::make_format_args<std::basic_format_context<
-                 std::back_insert_iterator<std::basic_string<CharT>>, CharT>>(
-                 args...));
+    std::vformat(fmt, std::make_format_args<context_t<CharT>>(args...));
     assert(false);
   } catch (std::format_error& e) {
     LIBCPP_ASSERT(e.what() == what);

diff  --git a/libcxx/test/std/utilities/format/format.functions/vformat_to.locale.pass.cpp b/libcxx/test/std/utilities/format/format.functions/vformat_to.locale.pass.cpp
index 5a57adf8a4a3b..40fc629cfb928 100644
--- a/libcxx/test/std/utilities/format/format.functions/vformat_to.locale.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.functions/vformat_to.locale.pass.cpp
@@ -16,10 +16,10 @@
 
 // template<class Out>
 //   Out vformat_to(Out out, const locale& loc, string_view fmt,
-//                  format_args_t<type_identity_t<Out>, char> args);
+//                  format_args args);
 // template<class Out>
 //    Out vformat_to(Out out, const locale& loc, wstring_view fmt,
-//                   format_args_t<type_identity_t<Out>, wchar_t> args);
+//                   wformat_args args);
 
 #include <format>
 #include <algorithm>
@@ -35,38 +35,31 @@ auto test = []<class CharT, class... Args>(std::basic_string<CharT> expected,
                                            const Args&... args) {
   {
     std::basic_string<CharT> out(expected.size(), CharT(' '));
-    auto it = std::vformat_to(
-        out.begin(), std::locale(), fmt,
-        std::make_format_args<std::basic_format_context<
-            typename std::basic_string<CharT>::iterator, CharT>>(args...));
+    auto it = std::vformat_to(out.begin(), std::locale(), fmt,
+                              std::make_format_args<context_t<CharT>>(args...));
     assert(it == out.end());
     assert(out == expected);
   }
   {
     std::list<CharT> out;
-    std::vformat_to(
-        std::back_inserter(out), std::locale(), fmt,
-        std::make_format_args<std::basic_format_context<
-            std::back_insert_iterator<std::list<CharT>>, CharT>>(args...));
+    std::vformat_to(std::back_inserter(out), std::locale(), fmt,
+                    std::make_format_args<context_t<CharT>>(args...));
     assert(
         std::equal(out.begin(), out.end(), expected.begin(), expected.end()));
   }
   {
     std::vector<CharT> out;
-    std::vformat_to(
-        std::back_inserter(out), std::locale(), fmt,
-        std::make_format_args<std::basic_format_context<
-            std::back_insert_iterator<std::vector<CharT>>, CharT>>(args...));
+    std::vformat_to(std::back_inserter(out), std::locale(), fmt,
+                    std::make_format_args<context_t<CharT>>(args...));
     assert(
         std::equal(out.begin(), out.end(), expected.begin(), expected.end()));
   }
   {
     assert(expected.size() < 4096 && "Update the size of the buffer.");
     CharT out[4096];
-    CharT* it = std::vformat_to(
-        out, std::locale(), fmt,
-        std::make_format_args<std::basic_format_context<CharT*, CharT>>(
-            args...));
+    CharT* it =
+        std::vformat_to(out, std::locale(), fmt,
+                        std::make_format_args<context_t<CharT>>(args...));
     assert(std::distance(out, it) == int(expected.size()));
     // Convert to std::string since output contains '\0' for boolean tests.
     assert(std::basic_string<CharT>(out, it) == expected);
@@ -78,11 +71,8 @@ auto test_exception = []<class CharT, class... Args>(
 #ifndef TEST_HAS_NO_EXCEPTIONS
   try {
     std::basic_string<CharT> out;
-    std::vformat_to(
-        std::back_inserter(out), std::locale(), fmt,
-        std::make_format_args<std::basic_format_context<
-            std::back_insert_iterator<std::basic_string<CharT>>, CharT>>(
-            args...));
+    std::vformat_to(std::back_inserter(out), std::locale(), fmt,
+                    std::make_format_args<context_t<CharT>>(args...));
     assert(false);
   } catch (std::format_error& e) {
     LIBCPP_ASSERT(e.what() == what);

diff  --git a/libcxx/test/std/utilities/format/format.functions/vformat_to.pass.cpp b/libcxx/test/std/utilities/format/format.functions/vformat_to.pass.cpp
index 1deca0d722cd5..6ebca904e0890 100644
--- a/libcxx/test/std/utilities/format/format.functions/vformat_to.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.functions/vformat_to.pass.cpp
@@ -18,11 +18,9 @@
 // <format>
 
 // template<class Out>
-//   Out vformat_to(Out out, string_view fmt,
-//                  format_args_t<type_identity_t<Out>, char> args);
+//   Out vformat_to(Out out, string_view fmt, format_args args);
 // template<class Out>
-//    Out vformat_to(Out out, wstring_view fmt,
-//                   format_args_t<type_identity_t<Out>, wchar_t> args);
+//    Out vformat_to(Out out, wstring_view fmt, wformat_args_t args);
 
 #include <format>
 #include <algorithm>
@@ -38,28 +36,22 @@ auto test = []<class CharT, class... Args>(std::basic_string<CharT> expected,
                                            const Args&... args) {
   {
     std::basic_string<CharT> out(expected.size(), CharT(' '));
-    auto it = std::vformat_to(
-        out.begin(), fmt,
-        std::make_format_args<std::basic_format_context<
-            typename std::basic_string<CharT>::iterator, CharT>>(args...));
+    auto it = std::vformat_to(out.begin(), fmt,
+                              std::make_format_args<context_t<CharT>>(args...));
     assert(it == out.end());
     assert(out == expected);
   }
   {
     std::list<CharT> out;
-    std::vformat_to(
-        std::back_inserter(out), fmt,
-        std::make_format_args<std::basic_format_context<
-            std::back_insert_iterator<std::list<CharT>>, CharT>>(args...));
+    std::vformat_to(std::back_inserter(out), fmt,
+                    std::make_format_args<context_t<CharT>>(args...));
     assert(
         std::equal(out.begin(), out.end(), expected.begin(), expected.end()));
   }
   {
     std::vector<CharT> out;
-    std::vformat_to(
-        std::back_inserter(out), fmt,
-        std::make_format_args<std::basic_format_context<
-            std::back_insert_iterator<std::vector<CharT>>, CharT>>(args...));
+    std::vformat_to(std::back_inserter(out), fmt,
+                    std::make_format_args<context_t<CharT>>(args...));
     assert(
         std::equal(out.begin(), out.end(), expected.begin(), expected.end()));
   }
@@ -67,9 +59,7 @@ auto test = []<class CharT, class... Args>(std::basic_string<CharT> expected,
     assert(expected.size() < 4096 && "Update the size of the buffer.");
     CharT out[4096];
     CharT* it = std::vformat_to(
-        out, fmt,
-        std::make_format_args<std::basic_format_context<CharT*, CharT>>(
-            args...));
+        out, fmt, std::make_format_args<context_t<CharT>>(args...));
     assert(std::distance(out, it) == int(expected.size()));
     // Convert to std::string since output contains '\0' for boolean tests.
     assert(std::basic_string<CharT>(out, it) == expected);
@@ -81,11 +71,8 @@ auto test_exception = []<class CharT, class... Args>(
 #ifndef TEST_HAS_NO_EXCEPTIONS
   try {
     std::basic_string<CharT> out;
-    std::vformat_to(
-        std::back_inserter(out), fmt,
-        std::make_format_args<std::basic_format_context<
-            std::back_insert_iterator<std::basic_string<CharT>>, CharT>>(
-            args...));
+    std::vformat_to(std::back_inserter(out), fmt,
+                    std::make_format_args<context_t<CharT>>(args...));
     assert(false);
   } catch (std::format_error& e) {
     LIBCPP_ASSERT(e.what() == what);

diff  --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index fa0a3eadbea47..231817156d14e 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -283,7 +283,7 @@ def add_version_header(tc):
     "libcxx_guard": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem)"
   }, {
     "name": "__cpp_lib_format",
-    "values": { "c++20": 201907 },
+    "values": { "c++20": 202106 },
     "headers": ["format"],
     "test_suite_guard": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format)",
     "libcxx_guard": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format)",


        


More information about the libcxx-commits mailing list