Mordante updated this revision to Diff 511865.
Mordante added a comment.
Herald added a subscriber: krytarowski.

CI fixes.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144331/new/

https://reviews.llvm.org/D144331

Files:
  libcxx/docs/FeatureTestMacroTable.rst
  libcxx/docs/ReleaseNotes.rst
  libcxx/docs/Status/Cxx2b.rst
  libcxx/docs/Status/Cxx2bPapers.csv
  libcxx/docs/Status/FormatPaper.csv
  libcxx/include/__format/parser_std_format_spec.h
  libcxx/include/__threading_support
  libcxx/include/thread
  libcxx/include/version
  libcxx/test/libcxx/transitive_includes/cxx03.csv
  libcxx/test/libcxx/transitive_includes/cxx11.csv
  libcxx/test/libcxx/transitive_includes/cxx14.csv
  libcxx/test/libcxx/transitive_includes/cxx17.csv
  libcxx/test/libcxx/transitive_includes/cxx20.csv
  libcxx/test/libcxx/transitive_includes/cxx2b.csv
  
libcxx/test/std/language.support/support.limits/support.limits.general/thread.version.compile.pass.cpp
  
libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
  
libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.format.pass.cpp
  
libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.tests.h
  
libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.vformat.pass.cpp
  
libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.pass.cpp
  
libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/parse.pass.cpp
  
libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/stream.pass.cpp
  
libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
  libcxx/utils/generate_feature_test_macro_components.py

Index: libcxx/utils/generate_feature_test_macro_components.py
===================================================================
--- libcxx/utils/generate_feature_test_macro_components.py
+++ libcxx/utils/generate_feature_test_macro_components.py
@@ -327,6 +327,13 @@
     "test_suite_guard": "!defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)",
     "libcxx_guard": "!defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)",
     "unimplemented": True,
+  }, {
+    "name": "__cpp_lib_formatters",
+    "values": { "c++2b": 202302 },
+    "headers": ["stacktrace", "thread"],
+    "test_suite_guard": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)",
+    "libcxx_guard": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)",
+    "unimplemented": True,
   }, {
     "name": "__cpp_lib_forward_like",
     "values": { "c++2b": 202207 },
Index: libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
===================================================================
--- libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
+++ libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
@@ -175,7 +175,8 @@
 // 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.
+// Note the paper has been abandoned, the types are kept since other papers may
+// introduce these formatters.
 template <class CharT>
 void test_P1636() {
   assert_is_not_formattable<std::basic_streambuf<CharT>, CharT>();
@@ -191,7 +192,7 @@
     assert_is_not_formattable<std::sub_match<CharT*>, CharT>();
 #endif
 #ifndef TEST_HAS_NO_THREADS
-  assert_is_not_formattable<std::thread::id, CharT>();
+  assert_is_formattable<std::thread::id, CharT>();
 #endif
   assert_is_not_formattable<std::unique_ptr<int>, CharT>();
 }
Index: libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/stream.pass.cpp
===================================================================
--- libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/stream.pass.cpp
+++ libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/stream.pass.cpp
@@ -9,6 +9,10 @@
 // UNSUPPORTED: no-threads
 // UNSUPPORTED: no-localization
 
+// TODO FMT This test should not require std::to_chars(floating-point)
+// This test requires std::to_chars(floating-point), which is in the dylib
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0}}
+
 // <thread>
 
 // class thread::id
@@ -18,16 +22,38 @@
 // operator<<(basic_ostream<charT, traits>& out, thread::id id);
 
 #include <thread>
+#include <format>
 #include <sstream>
 #include <cassert>
 
+#include "make_string.h"
 #include "test_macros.h"
 
-int main(int, char**)
-{
-    std::thread::id id0 = std::this_thread::get_id();
-    std::ostringstream os;
-    os << id0;
+template <class CharT>
+static void test() {
+  std::thread::id id0 = std::this_thread::get_id();
+  std::basic_ostringstream<CharT> os;
+  os << id0;
+
+#if TEST_STD_VER > 20 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
+  // C++23 added a formatter specialization for thread::id.
+  // This changed the requirement of ostream to have a
+  // [thread.thread.id]/2
+  //   The text representation for the character type charT of an object of
+  //   type thread::id is an unspecified sequence of charT ...
+  // This definition is used for both streaming and formatting.
+  //
+  // Test whether the output is identical.
+  std::basic_string<CharT> s = std::format(MAKE_STRING_VIEW(CharT, "{}"), id0);
+  assert(s == os.str());
+#endif
+}
+
+int main(int, char**) {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
 
   return 0;
 }
Index: libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/parse.pass.cpp
===================================================================
--- /dev/null
+++ libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/parse.pass.cpp
@@ -0,0 +1,71 @@
+//===----------------------------------------------------------------------===//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// UNSUPPORTED: no-threads
+// UNSUPPORTED: libcpp-has-no-incomplete-format
+
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
+// <thread>
+
+// template<class charT>
+// struct formatter<thread::id, charT>;
+
+// template<class ParseContext>
+//   constexpr typename ParseContext::iterator
+//     parse(ParseContext& ctx);
+
+// Note this tests the basics of this function. It's tested in more detail in
+// the format functions test.
+
+#include <cassert>
+#include <concepts>
+#include <thread>
+
+#include "test_format_context.h"
+#include "test_macros.h"
+#include "make_string.h"
+
+#define SV(S) MAKE_STRING_VIEW(CharT, S)
+
+template <class StringViewT>
+constexpr void test_parse(StringViewT fmt) {
+  using CharT    = typename StringViewT::value_type;
+  auto parse_ctx = std::basic_format_parse_context<CharT>(fmt);
+  std::formatter<std::thread::id, CharT> formatter;
+  static_assert(std::semiregular<decltype(formatter)>);
+
+  std::same_as<typename StringViewT::iterator> auto it = formatter.parse(parse_ctx);
+  assert(it == fmt.end() - (!fmt.empty() && fmt.back() == '}'));
+}
+
+template <class CharT>
+constexpr void test_fmt() {
+  test_parse(SV(""));
+  test_parse(SV("1"));
+
+  test_parse(SV("}"));
+  test_parse(SV("1}"));
+}
+
+constexpr bool test() {
+  test_fmt<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_fmt<wchar_t>();
+#endif
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}
Index: libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.pass.cpp
===================================================================
--- /dev/null
+++ libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// UNSUPPORTED: no-threads
+// UNSUPPORTED: libcpp-has-no-incomplete-format
+
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
+// <thread>
+
+// template<class charT>
+// struct formatter<thread::id, charT>;
+
+// template<class FormatContext>
+//   typename FormatContext::iterator
+//     format(const T& r, FormatContext& ctx) const;
+
+// Note this tests the basics of this function. It's tested in more detail in
+// the format functions test.
+
+#include <cassert>
+#include <concepts>
+#include <thread>
+
+#include "test_format_context.h"
+#include "test_macros.h"
+#include "make_string.h"
+
+#define SV(S) MAKE_STRING_VIEW(CharT, S)
+
+template <class StringViewT>
+void test_format(StringViewT expected, std::thread::id arg) {
+  using CharT      = typename StringViewT::value_type;
+  using String     = std::basic_string<CharT>;
+  using OutIt      = std::back_insert_iterator<String>;
+  using FormatCtxT = std::basic_format_context<OutIt, CharT>;
+
+  const std::formatter<std::thread::id, CharT> formatter;
+
+  String result;
+  OutIt out             = std::back_inserter(result);
+  FormatCtxT format_ctx = test_format_context_create<OutIt, CharT>(out, std::make_format_args<FormatCtxT>(arg));
+  formatter.format(arg, format_ctx);
+  assert(result == expected);
+}
+
+template <class CharT>
+void test_fmt() {
+#if !defined(__APPLE__) && !defined(__FreeBSD__)
+  test_format(SV("0"), std::thread::id());
+#else
+  test_format(SV("0x0"), std::thread::id());
+#endif
+}
+
+void test() {
+  test_fmt<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_fmt<wchar_t>();
+#endif
+}
+
+int main(int, char**) {
+  test();
+
+  return 0;
+}
Index: libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.vformat.pass.cpp
===================================================================
--- /dev/null
+++ libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.vformat.pass.cpp
@@ -0,0 +1,67 @@
+//===----------------------------------------------------------------------===//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// UNSUPPORTED: no-threads
+// UNSUPPORTED: libcpp-has-no-incomplete-format
+
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
+// TODO FMT This test should not require std::to_chars(floating-point)
+// This test requires std::to_chars(floating-point), which is in the dylib
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0}}
+
+// <thread>
+
+// template<class charT>
+// struct formatter<thread::id, charT>;
+
+// string vformat(string_view fmt, format_args args);
+// wstring vformat(wstring_view fmt, wformat_args args);
+
+#include <format>
+#include <cassert>
+
+#include "assert_macros.h"
+#include "concat_macros.h"
+#include "format.functions.tests.h"
+#include "test_macros.h"
+
+auto test = []<class CharT, class... Args>(
+                std::basic_string_view<CharT> expected, std::basic_string_view<CharT> fmt, Args&&... args) {
+  std::basic_string<CharT> out = std::vformat(fmt, std::make_format_args<context_t<CharT>>(args...));
+  TEST_REQUIRE(out == expected,
+               TEST_WRITE_CONCATENATED(
+                   "\nFormat string   ", fmt, "\nExpected output ", expected, "\nActual output   ", out, '\n'));
+};
+
+auto test_exception =
+    []<class CharT, class... Args>(
+        [[maybe_unused]] std::string_view what,
+        [[maybe_unused]] std::basic_string_view<CharT> fmt,
+        [[maybe_unused]] Args&&... args) {
+      TEST_VALIDATE_EXCEPTION(
+          std::format_error,
+          [&]([[maybe_unused]] const std::format_error& e) {
+            TEST_LIBCPP_REQUIRE(
+                e.what() == what,
+                TEST_WRITE_CONCATENATED(
+                    "\nFormat string   ", fmt, "\nExpected exception ", what, "\nActual exception   ", e.what(), '\n'));
+          },
+          TEST_IGNORE_NODISCARD std::vformat(fmt, std::make_format_args<context_t<CharT>>(args...)));
+    };
+
+int main(int, char**) {
+  format_tests<char>(test, test_exception);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  format_tests<wchar_t>(test, test_exception);
+#endif
+
+  return 0;
+}
Index: libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.tests.h
===================================================================
--- /dev/null
+++ libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.tests.h
@@ -0,0 +1,78 @@
+//===----------------------------------------------------------------------===//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TEST_STD_THREAD_THREAD_THREADS_THREAD_THREAD_CLASS_THREAD_THREAD_ID_FORMAT_FUNCTIONS_TESTS_H
+#define TEST_STD_THREAD_THREAD_THREADS_THREAD_THREAD_CLASS_THREAD_THREAD_ID_FORMAT_FUNCTIONS_TESTS_H
+
+#include <thread>
+
+#include "format.functions.common.h"
+#include "test_macros.h"
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void format_tests(TestFunction check, ExceptionTest check_exception) {
+  // Note the output of std::thread::id is unspecified. The output text is the
+  // same as the stream operator. Since that format is already released this
+  // test follows the practice on existing systems.
+  std::thread::id input{};
+
+  /***** Test the type specific part *****/
+#if !defined(__APPLE__) && !defined(__FreeBSD__)
+  check(SV("0"), SV("{}"), input);
+
+  // *** align-fill & width ***
+  check(SV("    0"), SV("{:5}"), input);
+  check(SV("0****"), SV("{:*<5}"), input);
+  check(SV("__0__"), SV("{:_^5}"), input);
+  check(SV("::::0"), SV("{::>5}"), input); // This is not a range, so : is allowed as fill character.
+
+  check(SV("    0"), SV("{:{}}"), input, 5);
+  check(SV("0****"), SV("{:*<{}}"), input, 5);
+  check(SV("__0__"), SV("{:_^{}}"), input, 5);
+  check(SV("####0"), SV("{:#>{}}"), input, 5);
+#else  // !defined(__APPLE__) && !defined(__FreeBSD__)
+  check(SV("0x0"), SV("{}"), input);
+
+  // *** align-fill & width ***
+  check(SV("    0x0"), SV("{:7}"), input);
+  check(SV("0x0****"), SV("{:*<7}"), input);
+  check(SV("__0x0__"), SV("{:_^7}"), input);
+  check(SV("::::0x0"), SV("{::>7}"), input); // This is not a range, so : is allowed as fill character.
+
+  check(SV("    0x0"), SV("{:{}}"), input, 7);
+  check(SV("0x0****"), SV("{:*<{}}"), input, 7);
+  check(SV("__0x0__"), SV("{:_^{}}"), input, 7);
+  check(SV("####0x0"), SV("{:#>{}}"), input, 7);
+#endif // !defined(__APPLE__) && !defined(__FreeBSD__)
+
+  /***** Test the type generic part *****/
+  check_exception("The format-spec fill field contains an invalid character", SV("{:}<}"), input);
+  check_exception("The format-spec fill field contains an invalid character", SV("{:{<}"), input);
+
+  // *** sign ***
+  check_exception("The replacement field misses a terminating '}'", SV("{:-}"), input);
+  check_exception("The replacement field misses a terminating '}'", SV("{:+}"), input);
+  check_exception("The replacement field misses a terminating '}'", SV("{: }"), input);
+
+  // *** alternate form ***
+  check_exception("The replacement field misses a terminating '}'", SV("{:#}"), input);
+
+  // *** zero-padding ***
+  check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
+
+  // *** precision ***
+  check_exception("The replacement field misses a terminating '}'", SV("{:.}"), input);
+
+  // *** locale-specific form ***
+  check_exception("The replacement field misses a terminating '}'", SV("{:L}"), input);
+
+  // *** type ***
+  for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>(""))
+    check_exception("The replacement field misses a terminating '}'", fmt, input);
+}
+
+#endif // TEST_STD_THREAD_THREAD_THREADS_THREAD_THREAD_CLASS_THREAD_THREAD_ID_FORMAT_FUNCTIONS_TESTS_H
Index: libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.format.pass.cpp
===================================================================
--- /dev/null
+++ libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.format.pass.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// UNSUPPORTED: no-threads
+// UNSUPPORTED: libcpp-has-no-incomplete-format
+
+// TODO FMT Fix this test using GCC, it currently times out.
+// UNSUPPORTED: gcc-12
+
+// TODO FMT This test should not require std::to_chars(floating-point)
+// This test requires std::to_chars(floating-point), which is in the dylib
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0}}
+
+// <thread>
+
+// template<class charT>
+// struct formatter<thread::id, charT>;
+
+// template<class... Args>
+//   string format(format_string<Args...> fmt, Args&&... args);
+// template<class... Args>
+//   wstring format(wformat_string<Args...> fmt, Args&&... args);
+
+#include <format>
+#include <cassert>
+
+#include "assert_macros.h"
+#include "concat_macros.h"
+#include "format.functions.tests.h"
+#include "test_format_string.h"
+#include "test_macros.h"
+
+auto test = []<class CharT, class... Args>(
+                std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) {
+  std::basic_string<CharT> out = std::format(fmt, std::forward<Args>(args)...);
+  TEST_REQUIRE(out == expected,
+               TEST_WRITE_CONCATENATED(
+                   "\nFormat string   ", fmt, "\nExpected output ", expected, "\nActual output   ", out, '\n'));
+};
+
+auto test_exception = []<class CharT, class... Args>(std::string_view, std::basic_string_view<CharT>, Args&&...) {
+  // After P2216 most exceptions thrown by std::format become ill-formed.
+  // Therefore this tests does nothing.
+};
+
+int main(int, char**) {
+  format_tests<char>(test, test_exception);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  format_tests<wchar_t>(test, test_exception);
+#endif
+
+  return 0;
+}
Index: libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
===================================================================
--- libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -79,6 +79,7 @@
     __cpp_lib_expected                             202202L [C++2b]
     __cpp_lib_filesystem                           201703L [C++17]
     __cpp_lib_format                               202106L [C++20]
+    __cpp_lib_formatters                           202302L [C++2b]
     __cpp_lib_forward_like                         202207L [C++2b]
     __cpp_lib_gcd_lcm                              201606L [C++17]
     __cpp_lib_generic_associative_lookup           201304L [C++14]
@@ -431,6 +432,10 @@
 #   error "__cpp_lib_format should not be defined before c++20"
 # endif
 
+# ifdef __cpp_lib_formatters
+#   error "__cpp_lib_formatters should not be defined before c++2b"
+# endif
+
 # ifdef __cpp_lib_forward_like
 #   error "__cpp_lib_forward_like should not be defined before c++2b"
 # endif
@@ -1086,6 +1091,10 @@
 #   error "__cpp_lib_format should not be defined before c++20"
 # endif
 
+# ifdef __cpp_lib_formatters
+#   error "__cpp_lib_formatters should not be defined before c++2b"
+# endif
+
 # ifdef __cpp_lib_forward_like
 #   error "__cpp_lib_forward_like should not be defined before c++2b"
 # endif
@@ -1855,6 +1864,10 @@
 #   error "__cpp_lib_format should not be defined before c++20"
 # endif
 
+# ifdef __cpp_lib_formatters
+#   error "__cpp_lib_formatters should not be defined before c++2b"
+# endif
+
 # ifdef __cpp_lib_forward_like
 #   error "__cpp_lib_forward_like should not be defined before c++2b"
 # endif
@@ -2903,6 +2916,10 @@
 #   endif
 # endif
 
+# ifdef __cpp_lib_formatters
+#   error "__cpp_lib_formatters should not be defined before c++2b"
+# endif
+
 # ifdef __cpp_lib_forward_like
 #   error "__cpp_lib_forward_like should not be defined before c++2b"
 # endif
@@ -4140,6 +4157,19 @@
 #   endif
 # endif
 
+# if !defined(_LIBCPP_VERSION)
+#   ifndef __cpp_lib_formatters
+#     error "__cpp_lib_formatters should be defined in c++2b"
+#   endif
+#   if __cpp_lib_formatters != 202302L
+#     error "__cpp_lib_formatters should have the value 202302L in c++2b"
+#   endif
+# else // _LIBCPP_VERSION
+#   ifdef __cpp_lib_formatters
+#     error "__cpp_lib_formatters should not be defined because it is unimplemented in libc++!"
+#   endif
+# endif
+
 # ifndef __cpp_lib_forward_like
 #   error "__cpp_lib_forward_like should be defined in c++2b"
 # endif
Index: libcxx/test/std/language.support/support.limits/support.limits.general/thread.version.compile.pass.cpp
===================================================================
--- libcxx/test/std/language.support/support.limits/support.limits.general/thread.version.compile.pass.cpp
+++ libcxx/test/std/language.support/support.limits/support.limits.general/thread.version.compile.pass.cpp
@@ -17,8 +17,9 @@
 
 // Test the feature test macros defined by <thread>
 
-/*  Constant             Value
-    __cpp_lib_jthread    201911L [C++20]
+/*  Constant                Value
+    __cpp_lib_formatters    202302L [C++2b]
+    __cpp_lib_jthread       201911L [C++20]
 */
 
 #include <thread>
@@ -26,24 +27,40 @@
 
 #if TEST_STD_VER < 14
 
+# ifdef __cpp_lib_formatters
+#   error "__cpp_lib_formatters should not be defined before c++2b"
+# endif
+
 # ifdef __cpp_lib_jthread
 #   error "__cpp_lib_jthread should not be defined before c++20"
 # endif
 
 #elif TEST_STD_VER == 14
 
+# ifdef __cpp_lib_formatters
+#   error "__cpp_lib_formatters should not be defined before c++2b"
+# endif
+
 # ifdef __cpp_lib_jthread
 #   error "__cpp_lib_jthread should not be defined before c++20"
 # endif
 
 #elif TEST_STD_VER == 17
 
+# ifdef __cpp_lib_formatters
+#   error "__cpp_lib_formatters should not be defined before c++2b"
+# endif
+
 # ifdef __cpp_lib_jthread
 #   error "__cpp_lib_jthread should not be defined before c++20"
 # endif
 
 #elif TEST_STD_VER == 20
 
+# ifdef __cpp_lib_formatters
+#   error "__cpp_lib_formatters should not be defined before c++2b"
+# endif
+
 # if !defined(_LIBCPP_VERSION)
 #   ifndef __cpp_lib_jthread
 #     error "__cpp_lib_jthread should be defined in c++20"
@@ -59,6 +76,19 @@
 
 #elif TEST_STD_VER > 20
 
+# if !defined(_LIBCPP_VERSION)
+#   ifndef __cpp_lib_formatters
+#     error "__cpp_lib_formatters should be defined in c++2b"
+#   endif
+#   if __cpp_lib_formatters != 202302L
+#     error "__cpp_lib_formatters should have the value 202302L in c++2b"
+#   endif
+# else // _LIBCPP_VERSION
+#   ifdef __cpp_lib_formatters
+#     error "__cpp_lib_formatters should not be defined because it is unimplemented in libc++!"
+#   endif
+# endif
+
 # if !defined(_LIBCPP_VERSION)
 #   ifndef __cpp_lib_jthread
 #     error "__cpp_lib_jthread should be defined in c++2b"
Index: libcxx/test/libcxx/transitive_includes/cxx2b.csv
===================================================================
--- libcxx/test/libcxx/transitive_includes/cxx2b.csv
+++ libcxx/test/libcxx/transitive_includes/cxx2b.csv
@@ -584,14 +584,22 @@
 system_error stdexcept
 system_error string
 system_error version
+thread array
 thread compare
 thread cstddef
+thread cstdint
+thread cstdlib
 thread ctime
 thread iosfwd
 thread limits
+thread locale
 thread ratio
+thread stdexcept
+thread string
+thread string_view
 thread system_error
 thread tuple
+thread vector
 thread version
 tuple compare
 tuple cstddef
Index: libcxx/test/libcxx/transitive_includes/cxx20.csv
===================================================================
--- libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -838,19 +838,26 @@
 system_error string
 system_error type_traits
 system_error version
+thread array
 thread compare
 thread cstddef
 thread cstdint
+thread cstdlib
 thread cstring
 thread ctime
 thread functional
 thread iosfwd
 thread limits
+thread locale
 thread new
 thread ratio
+thread stdexcept
+thread string
+thread string_view
 thread system_error
 thread tuple
 thread type_traits
+thread vector
 thread version
 tuple compare
 tuple cstddef
Index: libcxx/test/libcxx/transitive_includes/cxx17.csv
===================================================================
--- libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ libcxx/test/libcxx/transitive_includes/cxx17.csv
@@ -832,6 +832,7 @@
 system_error string
 system_error type_traits
 system_error version
+thread array
 thread chrono
 thread compare
 thread cstddef
@@ -841,11 +842,15 @@
 thread functional
 thread iosfwd
 thread limits
+thread locale
 thread new
 thread ratio
+thread string
+thread string_view
 thread system_error
 thread tuple
 thread type_traits
+thread vector
 thread version
 tuple compare
 tuple cstddef
Index: libcxx/test/libcxx/transitive_includes/cxx14.csv
===================================================================
--- libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ libcxx/test/libcxx/transitive_includes/cxx14.csv
@@ -832,6 +832,7 @@
 system_error string
 system_error type_traits
 system_error version
+thread array
 thread chrono
 thread compare
 thread cstddef
@@ -841,11 +842,15 @@
 thread functional
 thread iosfwd
 thread limits
+thread locale
 thread new
 thread ratio
+thread string
+thread string_view
 thread system_error
 thread tuple
 thread type_traits
+thread vector
 thread version
 tuple compare
 tuple cstddef
Index: libcxx/test/libcxx/transitive_includes/cxx11.csv
===================================================================
--- libcxx/test/libcxx/transitive_includes/cxx11.csv
+++ libcxx/test/libcxx/transitive_includes/cxx11.csv
@@ -830,6 +830,7 @@
 system_error string
 system_error type_traits
 system_error version
+thread array
 thread chrono
 thread compare
 thread cstddef
@@ -839,11 +840,15 @@
 thread functional
 thread iosfwd
 thread limits
+thread locale
 thread new
 thread ratio
+thread string
+thread string_view
 thread system_error
 thread tuple
 thread type_traits
+thread vector
 thread version
 tuple compare
 tuple cstddef
Index: libcxx/test/libcxx/transitive_includes/cxx03.csv
===================================================================
--- libcxx/test/libcxx/transitive_includes/cxx03.csv
+++ libcxx/test/libcxx/transitive_includes/cxx03.csv
@@ -829,6 +829,7 @@
 system_error string
 system_error type_traits
 system_error version
+thread array
 thread chrono
 thread compare
 thread cstddef
@@ -838,11 +839,15 @@
 thread functional
 thread iosfwd
 thread limits
+thread locale
 thread new
 thread ratio
+thread string
+thread string_view
 thread system_error
 thread tuple
 thread type_traits
+thread vector
 thread version
 tuple compare
 tuple cstddef
Index: libcxx/include/version
===================================================================
--- libcxx/include/version
+++ libcxx/include/version
@@ -85,6 +85,7 @@
 __cpp_lib_expected                                      202202L <expected>
 __cpp_lib_filesystem                                    201703L <filesystem>
 __cpp_lib_format                                        202106L <format>
+__cpp_lib_formatters                                    202302L <stacktrace> <thread>
 __cpp_lib_forward_like                                  202207L <utility>
 __cpp_lib_gcd_lcm                                       201606L <numeric>
 __cpp_lib_generic_associative_lookup                    201304L <map> <set>
@@ -397,6 +398,9 @@
 # define __cpp_lib_constexpr_memory                     202202L
 # define __cpp_lib_constexpr_typeinfo                   202106L
 # define __cpp_lib_expected                             202202L
+# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
+// #   define __cpp_lib_formatters                         202302L
+# endif
 # define __cpp_lib_forward_like                         202207L
 # define __cpp_lib_invoke_r                             202106L
 # define __cpp_lib_is_scoped_enum                       202011L
Index: libcxx/include/thread
===================================================================
--- libcxx/include/thread
+++ libcxx/include/thread
@@ -64,6 +64,9 @@
 basic_ostream<charT, traits>&
 operator<<(basic_ostream<charT, traits>& out, thread::id id);
 
+template<class charT>
+struct formatter<thread::id, charT>;
+
 namespace this_thread
 {
 
@@ -84,11 +87,18 @@
 */
 
 #include <__assert> // all public C++ headers provide the assertion handler
+#include <__availability>
 #include <__chrono/steady_clock.h>
 #include <__chrono/time_point.h>
+#include <__concepts/arithmetic.h>
 #include <__condition_variable/condition_variable.h>
 #include <__config>
 #include <__exception/terminate.h>
+#include <__format/concepts.h>
+#include <__format/format_parse_context.h>
+#include <__format/formatter.h>
+#include <__format/formatter_integral.h>
+#include <__format/parser_std_format_spec.h>
 #include <__functional/hash.h>
 #include <__memory/addressof.h>
 #include <__memory/unique_ptr.h>
@@ -224,6 +234,45 @@
 operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
 {return __os << __id.__id_;}
 
+#if _LIBCPP_STD_VER >= 23
+template <__fmt_char_type _CharT>
+struct _LIBCPP_TEMPLATE_VIS formatter<__thread_id, _CharT> {
+  public:
+    _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
+        -> decltype(__parse_ctx.begin()) {
+        return __parser_.__parse(__parse_ctx, __format_spec::__fields_fill_align_width);
+    }
+
+    _LIBCPP_HIDE_FROM_ABI auto format(__thread_id __id, auto& __ctx) const -> decltype(__ctx.out()) {
+        // In __threading_support __libcpp_thread_id is either a
+        // unsigned long long or a pthread_t.
+        //
+        // The type of pthread_t is left unspecified in POSIX so it can be any
+        // type. The most logical types are an integral or pointer.
+        // On Linux systems pthread_t is an unsigned long long.
+        // On Apple systems pthread_t is a pointer type.
+        //
+        // Note the output should match what the stream operator does. Since
+        // the ostream operator has been shipped years before this formatter
+        // was added to the Standard, this formatter does what the stream
+        // operator does. This may require platform specific changes.
+
+        using _Tp = decltype(__get_underlying_id(__id));
+        using _Cp = conditional_t<integral<_Tp>, _Tp, conditional_t<is_pointer_v<_Tp>, uintptr_t, void>>;
+        static_assert(!is_same_v<_Cp, void>, "unsupported thread::id type, please file a bug report");
+
+        __format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx);
+        if constexpr (is_pointer_v<_Tp>) {
+          __specs.__std_.__alternate_form_ = true;
+          __specs.__std_.__type_           = __format_spec::__type::__hexadecimal_lower_case;
+        }
+        return __formatter::__format_integer(reinterpret_cast<_Cp>(__get_underlying_id(__id)), __ctx, __specs);
+    }
+
+    __format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__right};
+};
+#endif // _LIBCPP_STD_VER >= 23
+
 class _LIBCPP_TYPE_VIS thread
 {
     __libcpp_thread_t __t_;
Index: libcxx/include/__threading_support
===================================================================
--- libcxx/include/__threading_support
+++ libcxx/include/__threading_support
@@ -643,6 +643,8 @@
     _LIBCPP_INLINE_VISIBILITY
     __thread_id(__libcpp_thread_id __id) : __id_(__id) {}
 
+    _LIBCPP_HIDE_FROM_ABI friend __libcpp_thread_id __get_underlying_id(const __thread_id __id) { return __id.__id_; }
+
     friend __thread_id this_thread::get_id() _NOEXCEPT;
     friend class _LIBCPP_TYPE_VIS thread;
     friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
Index: libcxx/include/__format/parser_std_format_spec.h
===================================================================
--- libcxx/include/__format/parser_std_format_spec.h
+++ libcxx/include/__format/parser_std_format_spec.h
@@ -143,6 +143,7 @@
 #  if _LIBCPP_STD_VER >= 23
 inline constexpr __fields __fields_tuple{.__use_range_fill_ = true};
 inline constexpr __fields __fields_range{.__use_range_fill_ = true};
+inline constexpr __fields __fields_fill_align_width{};
 #  endif
 
 enum class _LIBCPP_ENUM_VIS __alignment : uint8_t {
Index: libcxx/docs/Status/FormatPaper.csv
===================================================================
--- libcxx/docs/Status/FormatPaper.csv
+++ libcxx/docs/Status/FormatPaper.csv
@@ -40,5 +40,5 @@
 `[format.range.fmtstr] <https://wg21.link/format.range.fmtstr>`_,"Formatting for ranges: strings",,Mark de Wever,|In Progress|,
 `[format.range.fmtstr] <https://wg21.link/format.range.fmtstr>`_,"Formatting for ranges: strings",,Mark de Wever,|In Progress|,
 "`P2693R1 <https://wg21.link/P2693R1>`__","Formatting ``thread::id`` and ``stacktrace``"
-`[thread.thread.id] <https://wg21.link/thread.thread.id>`_,"Formatting ``thread::id``",,Mark de Wever,|In Progress|,
+`[thread.thread.id] <https://wg21.link/thread.thread.id>`_,"Formatting ``thread::id``",,Mark de Wever,|Complete|,Clang 17
 `[stacktrace.format] <https://wg21.link/stacktrace.format>`_,"Formatting ``stacktrace``",A ``<stacktrace>`` implementation,Mark de Wever,,
Index: libcxx/docs/Status/Cxx2bPapers.csv
===================================================================
--- libcxx/docs/Status/Cxx2bPapers.csv
+++ libcxx/docs/Status/Cxx2bPapers.csv
@@ -113,7 +113,7 @@
 "`P2713R1 <https://wg21.link/P2713R1>`__","LWG", "Escaping improvements in ``std::format``","February 2023","","","|format|"
 "`P2675R1 <https://wg21.link/P2675R1>`__","LWG", "``format``'s width estimation is too approximate and not forward compatible","February 2023","","","|format|"
 "`P2572R1 <https://wg21.link/P2572R1>`__","LWG", "``std::format`` fill character allowances","February 2023","","","|format|"
-"`P2693R1 <https://wg21.link/P2693R1>`__","LWG", "Formatting ``thread::id`` and ``stacktrace``","February 2023","","","|format|"
+"`P2693R1 <https://wg21.link/P2693R1>`__","LWG", "Formatting ``thread::id`` and ``stacktrace``","February 2023","|Partial| [#note-P2693R1]_","","|format|"
 "`P2679R2 <https://wg21.link/P2679R2>`__","LWG", "Fixing ``std::start_lifetime_as`` for arrays","February 2023","","",""
 "`P2674R1 <https://wg21.link/P2674R1>`__","LWG", "A trait for implicit lifetime types","February 2023","","",""
 "`P2655R3 <https://wg21.link/P2655R3>`__","LWG", "``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type","February 2023","","",""
Index: libcxx/docs/Status/Cxx2b.rst
===================================================================
--- libcxx/docs/Status/Cxx2b.rst
+++ libcxx/docs/Status/Cxx2b.rst
@@ -44,6 +44,9 @@
       clang doesn't issue a diagnostic for deprecated using template declarations.
    .. [#note-P2520R0] P2520R0: Libc++ implemented this paper as a DR in C++20 as well.
    .. [#note-P2711R1] P2711R1: ``join_with_view`` hasn't been done yet since this type isn't implemented yet.
+   .. [#note-P2693R1] P1413R3: The formatter for ``std::thread::id`` is implemented.
+      The formatter for ``stacktrace`` is not implemented, since ``stacktrace`` is
+      not implemented yet.
 
 .. _issues-status-cxx2b:
 
Index: libcxx/docs/ReleaseNotes.rst
===================================================================
--- libcxx/docs/ReleaseNotes.rst
+++ libcxx/docs/ReleaseNotes.rst
@@ -39,6 +39,7 @@
 ------------------
 - P2520R0 - ``move_iterator<T*>`` should be a random access iterator
 - P1328R1 - ``constexpr type_info::operator==()``
+- P1413R3 - Formatting ``thread::id`` (the ``stacktrace`` is not done yet)
 
 Improvements and New Features
 -----------------------------
Index: libcxx/docs/FeatureTestMacroTable.rst
===================================================================
--- libcxx/docs/FeatureTestMacroTable.rst
+++ libcxx/docs/FeatureTestMacroTable.rst
@@ -322,6 +322,8 @@
     ------------------------------------------------- -----------------
     ``__cpp_lib_expected``                            ``202202L``
     ------------------------------------------------- -----------------
+    ``__cpp_lib_formatters``                          *unimplemented*
+    ------------------------------------------------- -----------------
     ``__cpp_lib_forward_like``                        ``202207L``
     ------------------------------------------------- -----------------
     ``__cpp_lib_invoke_r``                            ``202106L``
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to