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