[libcxx-commits] [libcxx] a1beb0a - [libc++][format] Implements formattable concept.

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Wed Oct 5 13:21:09 PDT 2022


Author: Mark de Wever
Date: 2022-10-05T22:21:00+02:00
New Revision: a1beb0a38262f2456e435d16cb00867e2cdbb432

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

LOG: [libc++][format] Implements formattable concept.

This concept is introduced in P2286, but was implemented in libc++
before. This implementation was used in the library internally. This
implementation lacked the resolution of LWG3636. The original formatter
had a non-const member function that wasn't trivial to make a const
member. The recent parser improvements made this member a const member
in preparation of LWG3636.

Note LWG3636 isn't voted in. Its status is Ready. P2286's concept has
been written as-if LWG3636 is accepted and refers to that LWG issue.

Updates some tests make format a const member function and removes a
tests that's mainly a duplicate of the formattable concept test.

Implements
- LWG3636 formatter<T>::format should be const-qualified

Implements parts of
- P2286R8 Formatting Ranges

Reviewed By: ldionne, #libc

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

Added: 
    libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp

Modified: 
    libcxx/docs/Status/Cxx2bIssues.csv
    libcxx/docs/Status/FormatPaper.csv
    libcxx/include/__format/concepts.h
    libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.handle.pass.cpp
    libcxx/test/std/utilities/format/format.functions/P2418.pass.cpp
    libcxx/test/std/utilities/format/format.functions/format_tests.h

Removed: 
    libcxx/test/libcxx/utilities/format/format.formatter/format.formatter.spec/formattable.compile.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/types.compile.pass.cpp


################################################################################
diff  --git a/libcxx/docs/Status/Cxx2bIssues.csv b/libcxx/docs/Status/Cxx2bIssues.csv
index 20b20b46a16db..534bd7e336444 100644
--- a/libcxx/docs/Status/Cxx2bIssues.csv
+++ b/libcxx/docs/Status/Cxx2bIssues.csv
@@ -189,4 +189,5 @@
 "`3629 <https://wg21.link/LWG3629>`__","``make_error_code`` and ``make_error_condition`` are customization points","Not voted in","|Complete|","16.0",""
 "`3631 <https://wg21.link/LWG3631>`__","``basic_format_arg(T&&)`` should use ``remove_cvref_t<T>`` throughout","Not voted in","|Complete|","15.0",""
 "`3645 <https://wg21.link/LWG3645>`__","``resize_and_overwrite`` is overspecified to call its callback with lvalues","Not voted in","|Complete|","14.0",""
+"`3636 <https://wg21.link/LWG3636>`__","``formatter<T>::format`` should be ``const``-qualified","Not voted in","|Complete|","16.0",""
 "","","","",""

diff  --git a/libcxx/docs/Status/FormatPaper.csv b/libcxx/docs/Status/FormatPaper.csv
index c0b352c0a52d9..3339728b3a375 100644
--- a/libcxx/docs/Status/FormatPaper.csv
+++ b/libcxx/docs/Status/FormatPaper.csv
@@ -28,7 +28,7 @@ Section,Description,Dependencies,Assignee,Status,First released version
 `[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::local_info``",A ``<chrono>`` implementation,Not assigned,,
 `[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::zoned_time<Duration, TimeZonePtr>``",A ``<chrono>`` implementation,Not assigned,,
 `P2286R8 <https://wg21.link/P2286R8>`__,"Formatting ranges"
-`[format.syn] <https://wg21.link/format.syn>`_,"Concept ``formattable``",,Mark de Wever,|In Progress|,
+`[format.syn] <https://wg21.link/format.syn>`_,"Concept ``formattable``",,Mark de Wever,|Complete|, Clang 16
 `[format.string.std] <https://wg21.link/format.string.std>`_,"std-format-spec ``type`` debug",,Mark de Wever,|In Progress|,
 `[format.range] <https://wg21.link/format.range>`_,"Formatting for ranges: sequences",,Mark de Wever,|In Progress|,
 `[format.range] <https://wg21.link/format.range>`_,"Formatting for ranges: associative",,Mark de Wever,,

diff  --git a/libcxx/include/__format/concepts.h b/libcxx/include/__format/concepts.h
index 09ce22feb4a48..5407feebf77bd 100644
--- a/libcxx/include/__format/concepts.h
+++ b/libcxx/include/__format/concepts.h
@@ -41,20 +41,22 @@ concept __fmt_char_type =
 template <class _CharT>
 using __fmt_iter_for = _CharT*;
 
-// The concept is based on P2286R6
-// It lacks the const of __cf as required by, the not yet accepted, LWG-3636.
-// The current formatters can't be easily adapted, but that is WIP.
-// TODO FMT properly implement this concepts once accepted.
 template <class _Tp, class _CharT>
-concept __formattable = (semiregular<formatter<remove_cvref_t<_Tp>, _CharT>>) &&
-                        requires(formatter<remove_cvref_t<_Tp>, _CharT> __f,
-                                 formatter<remove_cvref_t<_Tp>, _CharT> __cf, _Tp __t,
-                                 basic_format_context<__fmt_iter_for<_CharT>, _CharT> __fc,
-                                 basic_format_parse_context<_CharT> __pc) {
-                          { __f.parse(__pc) } -> same_as<typename basic_format_parse_context<_CharT>::iterator>;
-                          { __cf.format(__t, __fc) } -> same_as<__fmt_iter_for<_CharT>>;
-                        };
+concept __formattable =
+    (semiregular<formatter<remove_cvref_t<_Tp>, _CharT>>) &&
+    requires(formatter<remove_cvref_t<_Tp>, _CharT> __f,
+             const formatter<remove_cvref_t<_Tp>, _CharT> __cf,
+             _Tp __t,
+             basic_format_context<__fmt_iter_for<_CharT>, _CharT> __fc,
+             basic_format_parse_context<_CharT> __pc) {
+      { __f.parse(__pc) } -> same_as<typename basic_format_parse_context<_CharT>::iterator>;
+      { __cf.format(__t, __fc) } -> same_as<__fmt_iter_for<_CharT>>;
+    };
 
+#  if _LIBCPP_STD_VER > 20
+template <class _Tp, class _CharT>
+concept formattable = __formattable<_Tp, _CharT>;
+#  endif //_LIBCPP_STD_VER > 20
 #endif //_LIBCPP_STD_VER > 17
 
 _LIBCPP_END_NAMESPACE_STD

diff  --git a/libcxx/test/libcxx/utilities/format/format.formatter/format.formatter.spec/formattable.compile.pass.cpp b/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
similarity index 98%
rename from libcxx/test/libcxx/utilities/format/format.formatter/format.formatter.spec/formattable.compile.pass.cpp
rename to libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
index 295486867ec6e..f5002577fc6e1 100644
--- a/libcxx/test/libcxx/utilities/format/format.formatter/format.formatter.spec/formattable.compile.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
@@ -5,11 +5,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
 // UNSUPPORTED: libcpp-has-no-incomplete-format
 
-// TODO FMT Move to std after P2286 has been accepted.
-
 // <format>
 
 // template<class T, class charT>
@@ -53,7 +51,7 @@
 
 template <class T, class CharT>
 void assert_is_not_formattable() {
-  static_assert(!std::__formattable<T, CharT>);
+  static_assert(!std::formattable<T, CharT>);
 }
 
 template <class T, class CharT>
@@ -66,7 +64,7 @@ void assert_is_formattable() {
                 || std::same_as<CharT, wchar_t>
 #endif
   )
-    static_assert(std::__formattable<T, CharT>);
+    static_assert(std::formattable<T, CharT>);
   else
     assert_is_not_formattable<T, CharT>();
 }

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.handle.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.handle.pass.cpp
index f8ffbd2a6ff2d..1523fd3ca938b 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.handle.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.handle.pass.cpp
@@ -32,7 +32,9 @@ const char* color_names[] = {"black", "red", "gold"};
 
 template <>
 struct std::formatter<color> : std::formatter<const char*> {
-  auto format(color c, auto& ctx) { return formatter<const char*>::format(color_names[static_cast<int>(c)], ctx); }
+  auto format(color c, auto& ctx) const {
+    return formatter<const char*>::format(color_names[static_cast<int>(c)], ctx);
+  }
 };
 
 void test(std::string expected, std::string_view fmt, color arg) {

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/types.compile.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/types.compile.pass.cpp
deleted file mode 100644
index eb734424360a2..0000000000000
--- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/types.compile.pass.cpp
+++ /dev/null
@@ -1,383 +0,0 @@
-//===----------------------------------------------------------------------===//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-// UNSUPPORTED: libcpp-has-no-incomplete-format
-
-// <format>
-
-// template <class _Tp, class _CharT = char>
-// struct formatter;
-
-// Tests the enabled and disabled requirements for std::formatter.
-
-#include <array>
-#include <bitset>
-#include <bitset>
-#include <chrono>
-#include <complex>
-#include <concepts>
-#include <deque>
-#include <format>
-#include <forward_list>
-#include <list>
-#include <memory>
-#include <map>
-#include <optional>
-#include <queue>
-#include <set>
-#include <stack>
-#include <span>
-#include <tuple>
-#include <type_traits>
-#include <unordered_map>
-#include <unordered_set>
-#include <valarray>
-#include <variant>
-
-#include "test_macros.h"
-
-#ifndef TEST_HAS_NO_FILESYSTEM_LIBRARY
-#  include <filesystem>
-#endif
-#ifndef TEST_HAS_NO_LOCALIZATION
-#  include <regex>
-#endif
-#ifndef TEST_HAS_NO_THREADS
-#  include <thread>
-#endif
-
-// Validate default template argument.
-static_assert(std::same_as<std::formatter<int>, std::formatter<int, char>>);
-
-// Concept for an enabled formatter.
-//
-// Since it's not possible to extract the T and CharT types from the formatter
-// they are specified and the proper formatter is always intended to be
-// defaulted.
-//
-// [formatter.requirements]/2
-// A type F meets the Formatter requirements if it meets the BasicFormatter
-// requirements and the expressions shown in Table 71 are valid and have the
-// indicated semantics.
-template <class T, class CharT, class F = std::formatter<T, CharT>>
-concept enabled =
-    // The basic BasicFormatter requirements:
-    std::default_initializable<F> && std::copyable<F> && std::destructible<F> && std::swappable<F> &&
-    // The expressions shown in Table 71
-    requires(F f, std::basic_format_parse_context<CharT> pc, T u, std::basic_format_context<CharT*, CharT> fc) {
-  { f.parse(pc) } -> std::same_as<typename decltype(pc)::iterator>;
-  { f.format(u, fc) } -> std::same_as<typename decltype(fc)::iterator>;
-};
-
-// Concept for a disabled formatter.
-//
-// This uses the same template arguments as enable. This isn't required since
-// the concept doesn't need to inspect T and CharT. This makes it easier for
-// future changes. For example P2286 formatting ranges intents to change
-// std::formatter<std::vector<int>> from disabled to enabled. The current way
-// makes it easy to define a macro like
-// #if TEST_STD_VER > 23
-//   TEST_ENABLED_AFTER_CXX23(T, CharT) enabled<T, CharT>
-// #else
-//   TEST_ENABLED_AFTER_CXX23(T, CharT) disabled<T, CharT>
-// #endif
-template <class T, class CharT, class F = std::formatter<T, CharT>>
-// [formatter.requirements]/5
-// If F is a disabled specialization of formatter, these values are false:
-concept disabled = !std::is_default_constructible_v<F> && !std::is_copy_constructible_v<F> &&
-                   !std::is_move_constructible_v<F> && !std::is_copy_assignable_v<F> && !std::is_move_assignable_v<F>;
-
-template <class T, class CharT>
-void assert_formatter_is_disabled() {
-  static_assert(disabled<T, CharT>);
-}
-
-template <class T, class CharT>
-void assert_formatter_is_enabled() {
-  // Only formatters for CharT == char || CharT == wchar_t are enabled for the
-  // standard formatters. When CharT is a 
diff erent type the formatter should
-  // be disabled.
-  if constexpr (std::same_as<CharT, char>
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-                || std::same_as<CharT, wchar_t>
-#endif
-  )
-    static_assert(enabled<T, CharT>);
-  else
-    assert_formatter_is_disabled<T, CharT>();
-}
-
-// Tests for P0645 Text Formatting
-template <class CharT>
-void test_P0645() {
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  // Tests the special formatter that converts a char to a wchar_t.
-  assert_formatter_is_enabled<char, wchar_t>();
-#endif
-  assert_formatter_is_enabled<CharT, CharT>();
-
-  assert_formatter_is_enabled<CharT*, CharT>();
-  assert_formatter_is_enabled<const CharT*, CharT>();
-  assert_formatter_is_enabled<CharT[42], CharT>();
-  assert_formatter_is_enabled<const CharT[42], CharT>();
-  assert_formatter_is_enabled<std::basic_string<CharT>, CharT>();
-  assert_formatter_is_enabled<std::basic_string_view<CharT>, CharT>();
-
-  assert_formatter_is_enabled<bool, CharT>();
-
-  assert_formatter_is_enabled<signed char, CharT>();
-  assert_formatter_is_enabled<signed short, CharT>();
-  assert_formatter_is_enabled<signed int, CharT>();
-  assert_formatter_is_enabled<signed long, CharT>();
-  assert_formatter_is_enabled<signed long long, CharT>();
-#ifndef TEST_HAS_NO_INT128
-  assert_formatter_is_enabled<__int128_t, CharT>();
-#endif
-
-  assert_formatter_is_enabled<unsigned char, CharT>();
-  assert_formatter_is_enabled<unsigned short, CharT>();
-  assert_formatter_is_enabled<unsigned int, CharT>();
-  assert_formatter_is_enabled<unsigned long, CharT>();
-  assert_formatter_is_enabled<unsigned long long, CharT>();
-#ifndef TEST_HAS_NO_INT128
-  assert_formatter_is_enabled<__uint128_t, CharT>();
-#endif
-
-  assert_formatter_is_enabled<float, CharT>();
-  assert_formatter_is_enabled<double, CharT>();
-  assert_formatter_is_enabled<long double, CharT>();
-
-  assert_formatter_is_enabled<std::nullptr_t, CharT>();
-  assert_formatter_is_enabled<void*, CharT>();
-  assert_formatter_is_enabled<const void*, CharT>();
-}
-
-// Tests for P1361 Integration of chrono with text formatting
-//
-// Some tests are commented out since these types haven't been implemented in
-// chrono yet. After P1361 has been implemented these formatters should be all
-// enabled.
-template <class CharT>
-void test_P1361() {
-// The chrono formatters require localization support.
-// [time.format]/7
-//   If the chrono-specs is omitted, the chrono object is formatted as if by
-//   streaming it to std::ostringstream os with the formatting
-//   locale imbued and copying os.str() through the output iterator of the
-//   context with additional padding and adjustments as specified by the format
-//   specifiers.
-// In libc++ std:::ostringstream requires localization support.
-#ifndef TEST_HAS_NO_LOCALIZATION
-
-  assert_formatter_is_disabled<std::chrono::microseconds, CharT>();
-
-  assert_formatter_is_disabled<std::chrono::sys_time<std::chrono::microseconds>, CharT>();
-  //assert_formatter_is_enabled<std::chrono::utc_time<std::chrono::microseconds>, CharT>();
-  //assert_formatter_is_enabled<std::chrono::tai_time<std::chrono::microseconds>, CharT>();
-  //assert_formatter_is_enabled<std::chrono::gps_time<std::chrono::microseconds>, CharT>();
-  assert_formatter_is_disabled<std::chrono::file_time<std::chrono::microseconds>, CharT>();
-  assert_formatter_is_disabled<std::chrono::local_time<std::chrono::microseconds>, CharT>();
-
-  assert_formatter_is_enabled<std::chrono::day, CharT>();
-  assert_formatter_is_enabled<std::chrono::month, CharT>();
-  assert_formatter_is_enabled<std::chrono::year, CharT>();
-
-  assert_formatter_is_disabled<std::chrono::weekday, CharT>();
-  assert_formatter_is_disabled<std::chrono::weekday_indexed, CharT>();
-  assert_formatter_is_disabled<std::chrono::weekday_last, CharT>();
-
-  assert_formatter_is_disabled<std::chrono::month_day, CharT>();
-  assert_formatter_is_disabled<std::chrono::month_day_last, CharT>();
-  assert_formatter_is_disabled<std::chrono::month_weekday, CharT>();
-  assert_formatter_is_disabled<std::chrono::month_weekday_last, CharT>();
-
-  assert_formatter_is_disabled<std::chrono::year_month, CharT>();
-  assert_formatter_is_disabled<std::chrono::year_month_day, CharT>();
-  assert_formatter_is_disabled<std::chrono::year_month_day_last, CharT>();
-  assert_formatter_is_disabled<std::chrono::year_month_weekday, CharT>();
-  assert_formatter_is_disabled<std::chrono::year_month_weekday_last, CharT>();
-
-  assert_formatter_is_disabled<std::chrono::hh_mm_ss<std::chrono::microseconds>, CharT>();
-
-  //assert_formatter_is_enabled<std::chrono::sys_info, CharT>();
-  //assert_formatter_is_enabled<std::chrono::local_info, CharT>();
-
-  //assert_formatter_is_enabled<std::chrono::zoned_time, CharT>();
-
-#endif // TEST_HAS_NO_LOCALIZATION
-}
-
-// Tests for P1636 Formatters for library types
-//
-// The paper hasn't been voted in so currently all formatters are disabled.
-// TODO validate whether the test is correct after the paper has been accepted.
-template <class CharT>
-void test_P1636() {
-  assert_formatter_is_disabled<std::basic_streambuf<CharT>, CharT>();
-  assert_formatter_is_disabled<std::bitset<42>, CharT>();
-  assert_formatter_is_disabled<std::complex<double>, CharT>();
-  assert_formatter_is_disabled<std::error_code, CharT>();
-#ifndef TEST_HAS_NO_FILESYSTEM_LIBRARY
-  assert_formatter_is_disabled<std::filesystem::path, CharT>();
-#endif
-  assert_formatter_is_disabled<std::shared_ptr<int>, CharT>();
-#ifndef TEST_HAS_NO_LOCALIZATION
-  assert_formatter_is_disabled<std::sub_match<CharT*>, CharT>();
-#endif
-#ifndef TEST_HAS_NO_THREADS
-  assert_formatter_is_disabled<std::thread::id, CharT>();
-#endif
-  assert_formatter_is_disabled<std::unique_ptr<int>, CharT>();
-}
-
-// Tests for P2286 Formatting ranges
-//
-// The paper hasn't been voted in so currently all formatters are disabled.
-// TODO validate whether the test is correct after the paper has been accepted.
-template <class CharT>
-void test_P2286() {
-  assert_formatter_is_disabled<std::array<int, 42>, CharT>();
-  assert_formatter_is_disabled<std::vector<int>, CharT>();
-  assert_formatter_is_disabled<std::deque<int>, CharT>();
-  assert_formatter_is_disabled<std::forward_list<int>, CharT>();
-  assert_formatter_is_disabled<std::list<int>, CharT>();
-
-  assert_formatter_is_disabled<std::set<int>, CharT>();
-  assert_formatter_is_disabled<std::map<int, int>, CharT>();
-  assert_formatter_is_disabled<std::multiset<int>, CharT>();
-  assert_formatter_is_disabled<std::multimap<int, int>, CharT>();
-
-  assert_formatter_is_disabled<std::unordered_set<int>, CharT>();
-  assert_formatter_is_disabled<std::unordered_map<int, int>, CharT>();
-  assert_formatter_is_disabled<std::unordered_multiset<int>, CharT>();
-  assert_formatter_is_disabled<std::unordered_multimap<int, int>, CharT>();
-
-  assert_formatter_is_disabled<std::stack<int>, CharT>();
-  assert_formatter_is_disabled<std::queue<int>, CharT>();
-  assert_formatter_is_disabled<std::priority_queue<int>, CharT>();
-
-  assert_formatter_is_disabled<std::span<int>, CharT>();
-
-  assert_formatter_is_disabled<std::valarray<int>, CharT>();
-
-  assert_formatter_is_disabled<std::pair<int, int>, CharT>();
-  assert_formatter_is_disabled<std::tuple<int>, CharT>();
-}
-
-class c {
-  void f();
-  void fc() const;
-  static void sf();
-};
-enum e { a };
-enum class ec { a };
-template <class CharT>
-void test_disabled() {
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  assert_formatter_is_disabled<const char*, wchar_t>();
-#endif
-  assert_formatter_is_disabled<const char*, char8_t>();
-  assert_formatter_is_disabled<const char*, char16_t>();
-  assert_formatter_is_disabled<const char*, char32_t>();
-
-  assert_formatter_is_disabled<c, CharT>();
-  assert_formatter_is_disabled<const c, CharT>();
-  assert_formatter_is_disabled<volatile c, CharT>();
-  assert_formatter_is_disabled<const volatile c, CharT>();
-
-  assert_formatter_is_disabled<e, CharT>();
-  assert_formatter_is_disabled<const e, CharT>();
-  assert_formatter_is_disabled<volatile e, CharT>();
-  assert_formatter_is_disabled<const volatile e, CharT>();
-
-  assert_formatter_is_disabled<ec, CharT>();
-  assert_formatter_is_disabled<const ec, CharT>();
-  assert_formatter_is_disabled<volatile ec, CharT>();
-  assert_formatter_is_disabled<const volatile ec, CharT>();
-
-  assert_formatter_is_disabled<int*, CharT>();
-  assert_formatter_is_disabled<const int*, CharT>();
-  assert_formatter_is_disabled<volatile int*, CharT>();
-  assert_formatter_is_disabled<const volatile int*, CharT>();
-
-  assert_formatter_is_disabled<c*, CharT>();
-  assert_formatter_is_disabled<const c*, CharT>();
-  assert_formatter_is_disabled<volatile c*, CharT>();
-  assert_formatter_is_disabled<const volatile c*, CharT>();
-
-  assert_formatter_is_disabled<e*, CharT>();
-  assert_formatter_is_disabled<const e*, CharT>();
-  assert_formatter_is_disabled<volatile e*, CharT>();
-  assert_formatter_is_disabled<const volatile e*, CharT>();
-
-  assert_formatter_is_disabled<ec*, CharT>();
-  assert_formatter_is_disabled<const ec*, CharT>();
-  assert_formatter_is_disabled<volatile ec*, CharT>();
-  assert_formatter_is_disabled<const volatile ec*, CharT>();
-
-  assert_formatter_is_disabled<void (*)(), CharT>();
-  assert_formatter_is_disabled<void (c::*)(), CharT>();
-  assert_formatter_is_disabled<void (c::*)() const, CharT>();
-
-  assert_formatter_is_disabled<std::optional<int>, CharT>();
-  assert_formatter_is_disabled<std::variant<int>, CharT>();
-
-  assert_formatter_is_disabled<std::shared_ptr<c>, CharT>();
-  assert_formatter_is_disabled<std::unique_ptr<c>, CharT>();
-
-  assert_formatter_is_disabled<std::array<c, 42>, CharT>();
-  assert_formatter_is_disabled<std::vector<c>, CharT>();
-  assert_formatter_is_disabled<std::deque<c>, CharT>();
-  assert_formatter_is_disabled<std::forward_list<c>, CharT>();
-  assert_formatter_is_disabled<std::list<c>, CharT>();
-
-  assert_formatter_is_disabled<std::set<c>, CharT>();
-  assert_formatter_is_disabled<std::map<c, int>, CharT>();
-  assert_formatter_is_disabled<std::multiset<c>, CharT>();
-  assert_formatter_is_disabled<std::multimap<c, int>, CharT>();
-
-  assert_formatter_is_disabled<std::unordered_set<c>, CharT>();
-  assert_formatter_is_disabled<std::unordered_map<c, int>, CharT>();
-  assert_formatter_is_disabled<std::unordered_multiset<c>, CharT>();
-  assert_formatter_is_disabled<std::unordered_multimap<c, int>, CharT>();
-
-  assert_formatter_is_disabled<std::stack<c>, CharT>();
-  assert_formatter_is_disabled<std::queue<c>, CharT>();
-  assert_formatter_is_disabled<std::priority_queue<c>, CharT>();
-
-  assert_formatter_is_disabled<std::span<c>, CharT>();
-
-  assert_formatter_is_disabled<std::valarray<c>, CharT>();
-
-  assert_formatter_is_disabled<std::pair<c, int>, CharT>();
-  assert_formatter_is_disabled<std::tuple<c>, CharT>();
-
-  assert_formatter_is_disabled<std::optional<c>, CharT>();
-  assert_formatter_is_disabled<std::variant<c>, CharT>();
-}
-
-template <class CharT>
-void test() {
-  test_P0645<CharT>();
-  test_P1361<CharT>();
-  test_P1636<CharT>();
-  test_P2286<CharT>();
-  test_disabled<CharT>();
-}
-
-void test() {
-  test<char>();
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  test<wchar_t>();
-#endif
-  test<char8_t>();
-  test<char16_t>();
-  test<char32_t>();
-
-  test<int>();
-}

diff  --git a/libcxx/test/std/utilities/format/format.functions/P2418.pass.cpp b/libcxx/test/std/utilities/format/format.functions/P2418.pass.cpp
index 1ccade8e542c2..004e6c6c45946 100644
--- a/libcxx/test/std/utilities/format/format.functions/P2418.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.functions/P2418.pass.cpp
@@ -28,8 +28,7 @@
 
 template <class CharT>
 struct std::formatter<MoveOnly, CharT> : std::formatter<int, CharT> {
-  // TODO FMT Make this a const member function after the base class has been adapted.
-  auto format(const MoveOnly& m, auto& ctx) -> decltype(ctx.out()) {
+  auto format(const MoveOnly& m, auto& ctx) const -> decltype(ctx.out()) {
     return std::formatter<int, CharT>::format(m.get(), ctx);
   }
 };

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 641542b749e21..e2c3e98fa0994 100644
--- a/libcxx/test/std/utilities/format/format.functions/format_tests.h
+++ b/libcxx/test/std/utilities/format/format.functions/format_tests.h
@@ -84,7 +84,7 @@ struct std::formatter<status, CharT> {
   }
 
   template <class Out>
-  auto format(status s, basic_format_context<Out, CharT>& ctx) -> decltype(ctx.out()) {
+  auto format(status s, basic_format_context<Out, CharT>& ctx) const -> decltype(ctx.out()) {
     const char* names[] = {"foo", "bar", "foobar"};
     char buffer[7];
     const char* begin = names[0];


        


More information about the libcxx-commits mailing list