diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -320,6 +320,8 @@ ------------------------------------------------- ----------------- ``__cpp_lib_expected`` ``202202L`` ------------------------------------------------- ----------------- + ``__cpp_lib_formatters`` *unimplemented* + ------------------------------------------------- ----------------- ``__cpp_lib_forward_like`` ``202207L`` ------------------------------------------------- ----------------- ``__cpp_lib_invoke_r`` ``202106L`` diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -39,6 +39,7 @@ ------------------ - P1328R1 - ``constexpr type_info::operator==()`` +- P1413R3 - Formatting ``thread::id`` (the ``stacktrace`` is not done yet) Improvements and New Features ----------------------------- diff --git a/libcxx/docs/Status/Cxx2b.rst b/libcxx/docs/Status/Cxx2b.rst --- a/libcxx/docs/Status/Cxx2b.rst +++ b/libcxx/docs/Status/Cxx2b.rst @@ -42,6 +42,9 @@ .. [#note-P0533R9] P0533R9: ``isfinite``, ``isinf``, ``isnan`` and ``isnormal`` are implemented. .. [#note-P1413R3] P1413R3: ``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but clang doesn't issue a diagnostic for deprecated using template declarations. + .. [#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: diff --git a/libcxx/docs/Status/Cxx2bPapers.csv b/libcxx/docs/Status/Cxx2bPapers.csv --- a/libcxx/docs/Status/Cxx2bPapers.csv +++ b/libcxx/docs/Status/Cxx2bPapers.csv @@ -113,7 +113,7 @@ "`P2713R1 `__","LWG", "Escaping improvements in ``std::format``","February 2023","","","|format|" "`P2675R1 `__","LWG", "``format``'s width estimation is too approximate and not forward compatible","February 2023","","","|format|" "`P2572R1 `__","LWG", "``std::format`` fill character allowances","February 2023","","","|format|" -"`P2693R1 `__","LWG", "Formatting ``thread::id`` and ``stacktrace``","February 2023","","","|format|" +"`P2693R1 `__","LWG", "Formatting ``thread::id`` and ``stacktrace``","February 2023","|Partial| [#note-P2693R1]_","","|format|" "`P2679R2 `__","LWG", "Fixing ``std::start_lifetime_as`` for arrays","February 2023","","","" "`P2674R1 `__","LWG", "A trait for implicit lifetime types","February 2023","","","" "`P2655R3 `__","LWG", "``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type","February 2023","","","" diff --git a/libcxx/docs/Status/FormatPaper.csv b/libcxx/docs/Status/FormatPaper.csv --- a/libcxx/docs/Status/FormatPaper.csv +++ b/libcxx/docs/Status/FormatPaper.csv @@ -40,5 +40,5 @@ `[format.range.fmtstr] `_,"Formatting for ranges: strings",,Mark de Wever,|In Progress|, `[format.range.fmtstr] `_,"Formatting for ranges: strings",,Mark de Wever,|In Progress|, "`P2693R1 `__","Formatting ``thread::id`` and ``stacktrace``" -`[thread.thread.id] `_,"Formatting ``thread::id``",,Mark de Wever,|In Progress|, +`[thread.thread.id] `_,"Formatting ``thread::id``",,Mark de Wever,|Complete|,Clang 17 `[stacktrace.format] `_,"Formatting ``stacktrace``",A ```` implementation,Mark de Wever,, diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h --- a/libcxx/include/__format/parser_std_format_spec.h +++ b/libcxx/include/__format/parser_std_format_spec.h @@ -142,6 +142,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 { diff --git a/libcxx/include/__threading_support b/libcxx/include/__threading_support --- a/libcxx/include/__threading_support +++ b/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>; diff --git a/libcxx/include/thread b/libcxx/include/thread --- a/libcxx/include/thread +++ b/libcxx/include/thread @@ -64,6 +64,9 @@ basic_ostream& operator<<(basic_ostream& out, thread::id id); +template +struct formatter; + namespace this_thread { @@ -84,7 +87,14 @@ */ #include <__assert> // all public C++ headers provide the assertion handler +#include <__availability> +#include <__concepts/arithmetic.h> #include <__config> +#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/unique_ptr.h> #include <__mutex_base> @@ -219,6 +229,46 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) {return __os << __id.__id_;} +#if _LIBCPP_STD_VER > 20 +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT 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. + + using _Tp = decltype(__get_underlying_id(__id)); + + if constexpr (integral<_Tp>) + return __formatter::__format_integer( + __get_underlying_id(__id), __ctx, __parser_.__get_parsed_std_specifications(__ctx)); +# if 0 + // This alternative is disabled on purpose. Without a platform using + // pointers it's not possible to properly verify the output is correct. + else if constexpr (is_pointer_v<_Tp>) + return __formatter::__format_integer( + reinterpret_cast(__get_underlying_id(__id)), + __ctx, + __parser_.__get_parsed_std_specifications(__ctx)); +# endif + else + // TODO FMT use static_assert(false, ...); + static_assert(sizeof(_CharT) == 0, "unsupported thread::id type, please file a bug report"); + } + + __format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__right}; +}; +#endif // _LIBCPP_STD_VER + class _LIBCPP_TYPE_VIS thread { __libcpp_thread_t __t_; diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -85,6 +85,7 @@ __cpp_lib_expected 202202L __cpp_lib_filesystem 201703L __cpp_lib_format 202106L +__cpp_lib_formatters 202302L __cpp_lib_forward_like 202207L __cpp_lib_gcd_lcm 201606L __cpp_lib_generic_associative_lookup 201304L @@ -394,6 +395,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 diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv --- a/libcxx/test/libcxx/transitive_includes/cxx03.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv @@ -812,20 +812,26 @@ system_error string system_error type_traits system_error version +thread array +thread charconv thread chrono 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 diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv --- a/libcxx/test/libcxx/transitive_includes/cxx11.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv @@ -813,20 +813,26 @@ system_error string system_error type_traits system_error version +thread array +thread charconv thread chrono 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 diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv --- a/libcxx/test/libcxx/transitive_includes/cxx14.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv @@ -822,20 +822,26 @@ system_error string system_error type_traits system_error version +thread array +thread charconv thread chrono 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 diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv --- a/libcxx/test/libcxx/transitive_includes/cxx17.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv @@ -822,20 +822,26 @@ system_error string system_error type_traits system_error version +thread array +thread charconv thread chrono 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 diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv --- a/libcxx/test/libcxx/transitive_includes/cxx20.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv @@ -829,19 +829,25 @@ system_error string system_error type_traits system_error version +thread array +thread charconv 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 diff --git a/libcxx/test/libcxx/transitive_includes/cxx2b.csv b/libcxx/test/libcxx/transitive_includes/cxx2b.csv --- a/libcxx/test/libcxx/transitive_includes/cxx2b.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx2b.csv @@ -624,18 +624,25 @@ system_error string system_error type_traits system_error version +thread array +thread charconv thread compare thread cstddef thread cstdint +thread cstdlib thread cstring -thread ctime +thread initializer_list 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 diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/thread.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/thread.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/thread.version.compile.pass.cpp +++ b/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 -/* Constant Value - __cpp_lib_jthread 201911L [C++20] +/* Constant Value + __cpp_lib_formatters 202302L [C++2b] + __cpp_lib_jthread 201911L [C++20] */ #include @@ -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" diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/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] @@ -429,6 +430,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 @@ -1076,6 +1081,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 @@ -1837,6 +1846,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 @@ -2877,6 +2890,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 @@ -4103,6 +4120,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 diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.format.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.format.pass.cpp new file mode 100644 --- /dev/null +++ b/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 + +// This test requires the dylib support introduced in D92214. +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}} +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}} + +// + +// template +// struct formatter; + +// template +// string format(format_string fmt, Args&&... args); +// template +// wstring format(wformat_string fmt, Args&&... args); + +#include +#include + +#include "assert_macros.h" +#include "concat_macros.h" +#include "format.functions.tests.h" +#include "test_format_string.h" +#include "test_macros.h" + +auto test = []( + std::basic_string_view expected, test_format_string fmt, Args&&... args) { + std::basic_string out = std::format(fmt, std::forward(args)...); + TEST_REQUIRE(out == expected, + TEST_WRITE_CONCATENATED( + "\nFormat string ", fmt, "\nExpected output ", expected, "\nActual output ", out, '\n')); +}; + +auto test_exception = [](std::string_view, std::basic_string_view, Args&&...) { + // After P2216 most exceptions thrown by std::format become ill-formed. + // Therefore this tests does nothing. +}; + +int main(int, char**) { + format_tests(test, test_exception); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + format_tests(test, test_exception); +#endif + + return 0; +} diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.tests.h b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.tests.h new file mode 100644 --- /dev/null +++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.tests.h @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// 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 + +#include "format.functions.common.h" +#include "test_macros.h" + +template +void format_test_integral(TestFunction check, ExceptionTest check_exception, auto&& input) { + 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); + + check(SV(" 0"), SV("{:{}}"), input, 5); + check(SV("0****"), SV("{:*<{}}"), input, 5); + check(SV("__0__"), SV("{:_^{}}"), input, 5); + check(SV("::::0"), SV("{::>{}}"), input, 5); // This is not a range, so : is allowed as fill character. + + 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 fmt : fmt_invalid_types("")) + check_exception("The replacement field misses a terminating '}'", fmt, input); +} + +template +void format_tests(TestFunction check, ExceptionTest check_exception) { + // note it is not guaranteed a thread::id is an integral, for other types + // different formatting results may occur, format needs to do the same as + // the stream operator. + format_test_integral(check, check_exception, std::thread::id()); +} + +#endif // TEST_STD_THREAD_THREAD_THREADS_THREAD_THREAD_CLASS_THREAD_THREAD_ID_FORMAT_FUNCTIONS_TESTS_H diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.vformat.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.vformat.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.functions.vformat.pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// 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: libcpp-has-no-incomplete-format + +// TODO FMT Fix this test using GCC, it currently times out. +// UNSUPPORTED: gcc-12 + +// This test requires the dylib support introduced in D92214. +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}} +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}} + +// + +// template +// struct formatter; + +// string vformat(string_view fmt, format_args args); +// wstring vformat(wstring_view fmt, wformat_args args); + +#include +#include + +#include "assert_macros.h" +#include "concat_macros.h" +#include "format.functions.tests.h" +#include "test_macros.h" + +auto test = []( + std::basic_string_view expected, std::basic_string_view fmt, Args&&... args) { + std::basic_string out = std::vformat(fmt, std::make_format_args>(args...)); + TEST_REQUIRE(out == expected, + TEST_WRITE_CONCATENATED( + "\nFormat string ", fmt, "\nExpected output ", expected, "\nActual output ", out, '\n')); +}; + +auto test_exception = + []( + [[maybe_unused]] std::string_view what, + [[maybe_unused]] std::basic_string_view 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>(args...))); + }; + +int main(int, char**) { + format_tests(test, test_exception); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + format_tests(test, test_exception); +#endif + + return 0; +} diff --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.pass.cpp copy from libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.pass.cpp copy to libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.pass.cpp --- a/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.pass.cpp +++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/format.pass.cpp @@ -8,27 +8,28 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // UNSUPPORTED: libcpp-has-no-incomplete-format +// TODO FMT Fix this test using GCC, it currently times out. +// UNSUPPORTED: gcc-12 + // This test requires the dylib support introduced in D92214. // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}} // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}} -// +// -// template -// struct range-default-formatter +// template +// struct formatter; // template // typename FormatContext::iterator -// format(const T& ref, FormatContext& ctx) const; +// 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. +// the format functions test. #include #include -#include -#include -#include +#include #include "test_format_context.h" #include "test_macros.h" @@ -37,13 +38,13 @@ #define SV(S) MAKE_STRING_VIEW(CharT, S) template -void test_format(StringViewT expected, std::set arg) { +void test_format(StringViewT expected, std::thread::id arg) { using CharT = typename StringViewT::value_type; using String = std::basic_string; using OutIt = std::back_insert_iterator; using FormatCtxT = std::basic_format_context; - std::formatter, CharT> formatter; + const std::formatter formatter; String result; OutIt out = std::back_inserter(result); @@ -54,7 +55,7 @@ template void test_fmt() { - test_format(SV("{42}"), std::set{42}); + test_format(SV("0"), std::thread::id()); } void test() { diff --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtset/parse.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/parse.pass.cpp copy from libcxx/test/std/utilities/format/format.range/format.range.fmtset/parse.pass.cpp copy to libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/parse.pass.cpp --- a/libcxx/test/std/utilities/format/format.range/format.range.fmtset/parse.pass.cpp +++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/parse.pass.cpp @@ -6,28 +6,31 @@ //===----------------------------------------------------------------------===// // 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 + // This test requires the dylib support introduced in D92214. // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}} // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}} -// +// -// template -// struct range-default-formatter +// template +// struct formatter; // template // 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. +// the format functions test. #include #include -#include -#include +#include #include "test_format_context.h" #include "test_macros.h" @@ -39,7 +42,7 @@ constexpr void test_parse(StringViewT fmt) { using CharT = typename StringViewT::value_type; auto parse_ctx = std::basic_format_parse_context(fmt); - std::formatter, CharT> formatter; + std::formatter formatter; static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); @@ -49,10 +52,10 @@ template constexpr void test_fmt() { test_parse(SV("")); - test_parse(SV(":5")); + test_parse(SV("1")); test_parse(SV("}")); - test_parse(SV(":5}")); + test_parse(SV("1}")); } constexpr bool test() { diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/stream.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/stream.pass.cpp --- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/stream.pass.cpp +++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/stream.pass.cpp @@ -18,16 +18,36 @@ // operator<<(basic_ostream& out, thread::id id); #include +#include #include #include +#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 +static void test() { + std::thread::id id0 = std::this_thread::get_id(); + std::basic_ostringstream 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 + // text representation for charT + // this definition is used for both streaming and formatting. + // + // Test whether the output is identical. + std::basic_string s = std::format(MAKE_STRING_VIEW(CharT, "{}"), id0); + assert(s == os.str()); +#endif +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif return 0; } diff --git a/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp b/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp --- a/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp +++ b/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp @@ -174,7 +174,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 void test_P1636() { assert_is_not_formattable, CharT>(); @@ -190,7 +191,7 @@ assert_is_not_formattable, CharT>(); #endif #ifndef TEST_HAS_NO_THREADS - assert_is_not_formattable(); + assert_is_formattable(); #endif assert_is_not_formattable, CharT>(); } diff --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.pass.cpp b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.pass.cpp --- a/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.pass.cpp +++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.pass.cpp @@ -8,6 +8,9 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // UNSUPPORTED: libcpp-has-no-incomplete-format +// TODO FMT Fix this test using GCC, it currently times out. +// UNSUPPORTED: gcc-12 + // This test requires the dylib support introduced in D92214. // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}} // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}} diff --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtset/parse.pass.cpp b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/parse.pass.cpp --- a/libcxx/test/std/utilities/format/format.range/format.range.fmtset/parse.pass.cpp +++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/parse.pass.cpp @@ -8,6 +8,9 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // UNSUPPORTED: libcpp-has-no-incomplete-format +// TODO FMT Fix this test using GCC, it currently times out. +// UNSUPPORTED: gcc-12 + // This test requires the dylib support introduced in D92214. // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{.+}} // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx11.{{.+}} diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -329,6 +329,13 @@ "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_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 },