From 8a21d59f29ef8d6011c6defa05ff7e8b7decc6d2 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Thu, 18 Apr 2024 17:23:07 +0200 Subject: [PATCH] [libc++][TZDB] Adds local_info formatter. (#86256) This adds the local_info type and its formatting options. The usage of the local_info object will be done in separate patches. Implements parts of: - P0355 Extending to Calendars and Time Zones - P1361 Integration of chrono with text formatting --- libcxx/docs/Status/FormatPaper.csv | 2 +- libcxx/include/CMakeLists.txt | 1 + libcxx/include/__chrono/convert_to_tm.h | 3 + libcxx/include/__chrono/formatter.h | 20 +++ libcxx/include/__chrono/local_info.h | 50 +++++++ libcxx/include/__chrono/ostream.h | 22 +++ libcxx/include/chrono | 16 +++ libcxx/include/libcxx.imp | 1 + libcxx/include/module.modulemap | 1 + libcxx/modules/std/chrono.inc | 1 + .../time.zone.info.local/ostream.pass.cpp | 114 ++++++++++++++++ .../time.syn/formatter.local_info.pass.cpp | 126 ++++++++++++++++++ .../local_info,members.pass.cpp | 57 ++++++++ .../time.zone.info.local/ostream.pass.cpp | 53 ++++++++ .../concept.formattable.compile.pass.cpp | 2 +- 15 files changed, 467 insertions(+), 2 deletions(-) create mode 100644 libcxx/include/__chrono/local_info.h create mode 100644 libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp create mode 100644 libcxx/test/std/time/time.syn/formatter.local_info.pass.cpp create mode 100644 libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/local_info,members.pass.cpp create mode 100644 libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp diff --git a/libcxx/docs/Status/FormatPaper.csv b/libcxx/docs/Status/FormatPaper.csv index 8ace18815f5375..f29f1f7ca74875 100644 --- a/libcxx/docs/Status/FormatPaper.csv +++ b/libcxx/docs/Status/FormatPaper.csv @@ -25,7 +25,7 @@ Section,Description,Dependencies,Assignee,Status,First released version `[time.syn] `_,"Formatter ``chrono::year_month_weekday_last``",,Mark de Wever,|Complete|,16.0 `[time.syn] `_,"Formatter ``chrono::hh_mm_ss>``",,Mark de Wever,|Complete|,17.0 `[time.syn] `_,"Formatter ``chrono::sys_info``",,Mark de Wever,|Complete|,19.0 -`[time.syn] `_,"Formatter ``chrono::local_info``",A ```` implementation,Mark de Wever,, +`[time.syn] `_,"Formatter ``chrono::local_info``",,Mark de Wever,|Complete|,19.0 `[time.syn] `_,"Formatter ``chrono::zoned_time``",A ```` implementation,Mark de Wever,, "`P2693R1 `__","Formatting ``thread::id`` and ``stacktrace``" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index dc364cc8d0a226..4ecd834c5382ae 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -270,6 +270,7 @@ set(files __chrono/high_resolution_clock.h __chrono/leap_second.h __chrono/literals.h + __chrono/local_info.h __chrono/month.h __chrono/month_weekday.h __chrono/monthday.h diff --git a/libcxx/include/__chrono/convert_to_tm.h b/libcxx/include/__chrono/convert_to_tm.h index d2c5cf922ba671..f7256db3bea661 100644 --- a/libcxx/include/__chrono/convert_to_tm.h +++ b/libcxx/include/__chrono/convert_to_tm.h @@ -16,6 +16,7 @@ #include <__chrono/duration.h> #include <__chrono/file_clock.h> #include <__chrono/hh_mm_ss.h> +#include <__chrono/local_info.h> #include <__chrono/month.h> #include <__chrono/month_weekday.h> #include <__chrono/monthday.h> @@ -175,6 +176,8 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) { # if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) } else if constexpr (same_as<_ChronoT, chrono::sys_info>) { // Has no time information. + } else if constexpr (same_as<_ChronoT, chrono::local_info>) { + // Has no time information. # endif } else static_assert(sizeof(_ChronoT) == 0, "Add the missing type specialization"); diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h index 0196deb8c1ffb3..6a14c344fa1188 100644 --- a/libcxx/include/__chrono/formatter.h +++ b/libcxx/include/__chrono/formatter.h @@ -18,6 +18,7 @@ #include <__chrono/duration.h> #include <__chrono/file_clock.h> #include <__chrono/hh_mm_ss.h> +#include <__chrono/local_info.h> #include <__chrono/month.h> #include <__chrono/month_weekday.h> #include <__chrono/monthday.h> @@ -419,6 +420,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_ok(const _Tp& __value) { # if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) else if constexpr (same_as<_Tp, chrono::sys_info>) return true; + else if constexpr (same_as<_Tp, chrono::local_info>) + return true; # endif else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); @@ -463,6 +466,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_name_ok(const _Tp& __value) { # if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) else if constexpr (same_as<_Tp, chrono::sys_info>) return true; + else if constexpr (same_as<_Tp, chrono::local_info>) + return true; # endif else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); @@ -507,6 +512,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __date_ok(const _Tp& __value) { # if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) else if constexpr (same_as<_Tp, chrono::sys_info>) return true; + else if constexpr (same_as<_Tp, chrono::local_info>) + return true; # endif else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); @@ -551,6 +558,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) { # if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) else if constexpr (same_as<_Tp, chrono::sys_info>) return true; + else if constexpr (same_as<_Tp, chrono::local_info>) + return true; # endif else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); @@ -893,6 +902,17 @@ struct formatter : public __formatter_chrono<_CharT> { return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__time_zone); } }; + +template <__fmt_char_type _CharT> +struct formatter : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags{}); + } +}; # endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) #endif // if _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__chrono/local_info.h b/libcxx/include/__chrono/local_info.h new file mode 100644 index 00000000000000..b1a03ad7df2aca --- /dev/null +++ b/libcxx/include/__chrono/local_info.h @@ -0,0 +1,50 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html + +#ifndef _LIBCPP___CHRONO_LOCAL_INFO_H +#define _LIBCPP___CHRONO_LOCAL_INFO_H + +#include +// Enable the contents of the header only when libc++ was built with experimental features enabled. +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) + +# include <__chrono/sys_info.h> +# include <__config> + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +# if _LIBCPP_STD_VER >= 20 + +namespace chrono { + +struct local_info { + static constexpr int unique = 0; + static constexpr int nonexistent = 1; + static constexpr int ambiguous = 2; + + int result; + sys_info first; + sys_info second; +}; + +} // namespace chrono + +# endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) + +#endif // _LIBCPP___CHRONO_LOCAL_INFO_H diff --git a/libcxx/include/__chrono/ostream.h b/libcxx/include/__chrono/ostream.h index 9476406d761075..cb17dbea58bee3 100644 --- a/libcxx/include/__chrono/ostream.h +++ b/libcxx/include/__chrono/ostream.h @@ -15,6 +15,7 @@ #include <__chrono/duration.h> #include <__chrono/file_clock.h> #include <__chrono/hh_mm_ss.h> +#include <__chrono/local_info.h> #include <__chrono/month.h> #include <__chrono/month_weekday.h> #include <__chrono/monthday.h> @@ -280,6 +281,27 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_info& __info) { __abbrev); } +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const local_info& __info) { + auto __result = [&]() -> basic_string<_CharT> { + switch (__info.result) { + case local_info::unique: + return _LIBCPP_STATICALLY_WIDEN(_CharT, "unique"); + case local_info::nonexistent: + return _LIBCPP_STATICALLY_WIDEN(_CharT, "non-existent"); + case local_info::ambiguous: + return _LIBCPP_STATICALLY_WIDEN(_CharT, "ambiguous"); + + default: + return std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "unspecified result ({})"), __info.result); + }; + }; + + return __os << std::format( + _LIBCPP_STATICALLY_WIDEN(_CharT, "{}: {{{}, {}}}"), __result(), __info.first, __info.second); +} + # endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) } // namespace chrono diff --git a/libcxx/include/chrono b/libcxx/include/chrono index f0275ec1eba7ae..96a3e92faa81f2 100644 --- a/libcxx/include/chrono +++ b/libcxx/include/chrono @@ -737,6 +737,20 @@ template basic_ostream& operator<<(basic_ostream& os, const sys_info& si); +struct local_info { // C++20 + static constexpr int unique = 0; + static constexpr int nonexistent = 1; + static constexpr int ambiguous = 2; + + int result; + sys_info first; + sys_info second; +}; + +template // C++20 + basic_ostream& + operator<<(basic_ostream& os, const local_info& li); + // 25.10.5, class time_zone // C++20 enum class choose {earliest, latest}; class time_zone { @@ -834,6 +848,7 @@ namespace std { template struct formatter>, charT>; // C++20 template struct formatter; // C++20 + template struct formatter; // C++20 } // namespace std namespace chrono { @@ -899,6 +914,7 @@ constexpr chrono::year operator ""y(unsigned lo # include <__chrono/day.h> # include <__chrono/hh_mm_ss.h> # include <__chrono/literals.h> +# include <__chrono/local_info.h> # include <__chrono/month.h> # include <__chrono/month_weekday.h> # include <__chrono/monthday.h> diff --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp index c224090e72465e..1d12b6e8d86bba 100644 --- a/libcxx/include/libcxx.imp +++ b/libcxx/include/libcxx.imp @@ -267,6 +267,7 @@ { include: [ "<__chrono/high_resolution_clock.h>", "private", "", "public" ] }, { include: [ "<__chrono/leap_second.h>", "private", "", "public" ] }, { include: [ "<__chrono/literals.h>", "private", "", "public" ] }, + { include: [ "<__chrono/local_info.h>", "private", "", "public" ] }, { include: [ "<__chrono/month.h>", "private", "", "public" ] }, { include: [ "<__chrono/month_weekday.h>", "private", "", "public" ] }, { include: [ "<__chrono/monthday.h>", "private", "", "public" ] }, diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index 62ac4316647483..64652c8307c9e6 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -1124,6 +1124,7 @@ module std_private_chrono_high_resolution_clock [system] { } module std_private_chrono_leap_second [system] { header "__chrono/leap_second.h" } module std_private_chrono_literals [system] { header "__chrono/literals.h" } +module std_private_chrono_local_info [system] { header "__chrono/local_info.h" } module std_private_chrono_month [system] { header "__chrono/month.h" } module std_private_chrono_month_weekday [system] { header "__chrono/month_weekday.h" } module std_private_chrono_monthday [system] { header "__chrono/monthday.h" } diff --git a/libcxx/modules/std/chrono.inc b/libcxx/modules/std/chrono.inc index 575e6347aecce1..1265e21dc54ef6 100644 --- a/libcxx/modules/std/chrono.inc +++ b/libcxx/modules/std/chrono.inc @@ -215,6 +215,7 @@ export namespace std { # endif // if 0 // [time.zone.info], information classes + using std::chrono::local_info; using std::chrono::sys_info; # if 0 diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp new file mode 100644 index 00000000000000..d18076a642ec6a --- /dev/null +++ b/libcxx/test/libcxx/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp @@ -0,0 +1,114 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-localization + +// TODO FMT This test should not require std::to_chars(floating-point) +// XFAIL: availability-fp_to_chars-missing + +// XFAIL: libcpp-has-no-incomplete-tzdb + +// + +// template +// basic_ostream& +// operator<<(basic_ostream& os, const local_info& r); + +// [time.zone.info.local] +// 7 Effects: Streams out the local_info object r in an unspecified format. +// 8 Returns: os. +// +// Tests the output produced by this function. + +#include +#include +#include +#include + +#include "assert_macros.h" +#include "test_macros.h" +#include "make_string.h" +#include "concat_macros.h" + +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static void test(std::basic_string_view expected, std::chrono::local_info&& info) { + std::basic_stringstream sstr; + sstr << info; + std::basic_string output = sstr.str(); + + TEST_REQUIRE(expected == output, + TEST_WRITE_CONCATENATED("\nExpected output ", expected, "\nActual output ", output, '\n')); +} + +template +static void test() { + using namespace std::literals::chrono_literals; + namespace tz = std::chrono; + // result values matching the "known" results + test(SV("unique: " + "{[-10484-10-16 15:30:08, 14423-03-17 15:30:07) 00:00:00 0min \"TZ\", " + "[1970-01-01 00:00:00, 1970-01-01 00:00:00) 00:00:00 0min \"\"}"), + tz::local_info{tz::local_info::unique, + tz::sys_info{tz::sys_seconds::min(), tz::sys_seconds::max(), 0s, 0min, "TZ"}, + tz::sys_info{}}); + + test(SV("non-existent: " + "{[1970-01-01 00:00:00, 2038-12-31 00:00:00) 12:23:45 -67min \"NEG\", " + "[1970-01-01 00:00:00, 2038-12-31 00:00:00) -12:23:45 67min \"POS\"}"), + tz::local_info{ + tz::local_info::nonexistent, + tz::sys_info{static_cast(tz::year_month_day{1970y, tz::January, 1d}), + static_cast(tz::year_month_day{2038y, tz::December, 31d}), + 12h + 23min + 45s, + -67min, + "NEG"}, + tz::sys_info{static_cast(tz::year_month_day{1970y, tz::January, 1d}), + static_cast(tz::year_month_day{2038y, tz::December, 31d}), + -(12h + 23min + 45s), + 67min, + "POS"}}); + + test(SV("ambiguous: " + "{[1970-01-01 00:00:00, 2038-12-31 00:00:00) 12:23:45 -67min \"NEG\", " + "[1970-01-01 00:00:00, 2038-12-31 00:00:00) -12:23:45 67min \"POS\"}"), + tz::local_info{ + tz::local_info::ambiguous, + tz::sys_info{static_cast(tz::year_month_day{1970y, tz::January, 1d}), + static_cast(tz::year_month_day{2038y, tz::December, 31d}), + 12h + 23min + 45s, + -67min, + "NEG"}, + tz::sys_info{static_cast(tz::year_month_day{1970y, tz::January, 1d}), + static_cast(tz::year_month_day{2038y, tz::December, 31d}), + -(12h + 23min + 45s), + 67min, + "POS"}}); + + // result values not matching the "known" results + test( + SV("unspecified result (-1): " + "{[-10484-10-16 15:30:08, 14423-03-17 15:30:07) 00:00:00 0min \"TZ\", " + "[1970-01-01 00:00:00, 1970-01-01 00:00:00) 00:00:00 0min \"\"}"), + tz::local_info{-1, tz::sys_info{tz::sys_seconds::min(), tz::sys_seconds::max(), 0s, 0min, "TZ"}, tz::sys_info{}}); + test(SV("unspecified result (3): " + "{[-10484-10-16 15:30:08, 14423-03-17 15:30:07) 00:00:00 0min \"TZ\", " + "[1970-01-01 00:00:00, 1970-01-01 00:00:00) 00:00:00 0min \"\"}"), + tz::local_info{3, tz::sys_info{tz::sys_seconds::min(), tz::sys_seconds::max(), 0s, 0min, "TZ"}, tz::sys_info{}}); +} + +int main(int, const char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.syn/formatter.local_info.pass.cpp b/libcxx/test/std/time/time.syn/formatter.local_info.pass.cpp new file mode 100644 index 00000000000000..ef36416c3fb232 --- /dev/null +++ b/libcxx/test/std/time/time.syn/formatter.local_info.pass.cpp @@ -0,0 +1,126 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-localization +// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME + +// TODO FMT This test should not require std::to_chars(floating-point) +// XFAIL: availability-fp_to_chars-missing + +// XFAIL: libcpp-has-no-incomplete-tzdb + +// REQUIRES: locale.fr_FR.UTF-8 + +// +// +// template struct formatter; + +#include +#include + +#include +#include +#include +#include +#include + +#include "formatter_tests.h" +#include "make_string.h" +#include "platform_support.h" // locale name macros +#include "test_macros.h" + +template +static void test_no_chrono_specs() { +// This test libc++ specific due to +// [time.zone.info.local]/3 +// Effects: Streams out the local_info object r in an unspecified format. +#ifdef _LIBCPP_VERSION + using namespace std::literals::chrono_literals; + namespace tz = std::chrono; + + std::locale::global(std::locale(LOCALE_fr_FR_UTF_8)); + + // Non localized output + + // result values matching the "known" results + check(SV("unique: " + "{[-10484-10-16 15:30:08, 14423-03-17 15:30:07) 00:00:00 0min \"TZ\", " + "[1970-01-01 00:00:00, 1970-01-01 00:00:00) 00:00:00 0min \"\"}"), + SV("{}"), + tz::local_info{tz::local_info::unique, + tz::sys_info{tz::sys_seconds::min(), tz::sys_seconds::max(), 0s, 0min, "TZ"}, + tz::sys_info{}}); + + check(SV("non-existent: " + "{[1970-01-01 00:00:00, 2038-12-31 00:00:00) 12:23:45 -67min \"NEG\", " + "[1970-01-01 00:00:00, 2038-12-31 00:00:00) -12:23:45 67min \"POS\"}"), + SV("{}"), + tz::local_info{ + tz::local_info::nonexistent, + tz::sys_info{static_cast(tz::year_month_day{1970y, tz::January, 1d}), + static_cast(tz::year_month_day{2038y, tz::December, 31d}), + 12h + 23min + 45s, + -67min, + "NEG"}, + tz::sys_info{static_cast(tz::year_month_day{1970y, tz::January, 1d}), + static_cast(tz::year_month_day{2038y, tz::December, 31d}), + -(12h + 23min + 45s), + 67min, + "POS"}}); + + check(SV("ambiguous: " + "{[1970-01-01 00:00:00, 2038-12-31 00:00:00) 12:23:45 -67min \"NEG\", " + "[1970-01-01 00:00:00, 2038-12-31 00:00:00) -12:23:45 67min \"POS\"}"), + SV("{}"), + tz::local_info{ + tz::local_info::ambiguous, + tz::sys_info{static_cast(tz::year_month_day{1970y, tz::January, 1d}), + static_cast(tz::year_month_day{2038y, tz::December, 31d}), + 12h + 23min + 45s, + -67min, + "NEG"}, + tz::sys_info{static_cast(tz::year_month_day{1970y, tz::January, 1d}), + static_cast(tz::year_month_day{2038y, tz::December, 31d}), + -(12h + 23min + 45s), + 67min, + "POS"}}); + + // result values not matching the "known" results + check( + SV("unspecified result (-1): " + "{[-10484-10-16 15:30:08, 14423-03-17 15:30:07) 00:00:00 0min \"TZ\", " + "[1970-01-01 00:00:00, 1970-01-01 00:00:00) 00:00:00 0min \"\"}"), + SV("{}"), + tz::local_info{-1, tz::sys_info{tz::sys_seconds::min(), tz::sys_seconds::max(), 0s, 0min, "TZ"}, tz::sys_info{}}); + check( + SV("unspecified result (3): " + "{[-10484-10-16 15:30:08, 14423-03-17 15:30:07) 00:00:00 0min \"TZ\", " + "[1970-01-01 00:00:00, 1970-01-01 00:00:00) 00:00:00 0min \"\"}"), + SV("{}"), + tz::local_info{3, tz::sys_info{tz::sys_seconds::min(), tz::sys_seconds::max(), 0s, 0min, "TZ"}, tz::sys_info{}}); + + std::locale::global(std::locale::classic()); +#endif // _LIBCPP_VERSION +} + +template +static void test() { + test_no_chrono_specs(); + + check_invalid_types({}, std::chrono::local_info{0, {}, {}}); +} + +int main(int, char**) { + test(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/local_info,members.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/local_info,members.pass.cpp new file mode 100644 index 00000000000000..4e2a757a0a970f --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/local_info,members.pass.cpp @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// XFAIL: libcpp-has-no-incomplete-tzdb + +// + +// struct local_info { +// static constexpr int unique = 0; +// static constexpr int nonexistent = 1; +// static constexpr int ambiguous = 2; +// +// int result; +// sys_info first; +// sys_info second; +// }; + +// Validates whether: +// - The static members are present as static constexpr members. +// - The members are present as non-const members. +// - The struct is an aggregate. + +#include +#include +#include + +int main(int, const char**) { + { + constexpr const int& result = std::chrono::local_info::unique; + static_assert(result == 0); + } + { + constexpr const int& result = std::chrono::local_info::nonexistent; + static_assert(result == 1); + } + { + constexpr const int& result = std::chrono::local_info::ambiguous; + static_assert(result == 2); + } + + static_assert(std::is_aggregate_v); + + std::chrono::local_info local_info{.result = 0, .first = std::chrono::sys_info{}, .second = std::chrono::sys_info{}}; + + [[maybe_unused]] int& result = local_info.result; + [[maybe_unused]] std::chrono::sys_info& first = local_info.first; + [[maybe_unused]] std::chrono::sys_info& second = local_info.second; + + return 0; +} diff --git a/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp new file mode 100644 index 00000000000000..d9bf066b068783 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.info/time.zone.info.local/ostream.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-localization + +// TODO FMT This test should not require std::to_chars(floating-point) +// XFAIL: availability-fp_to_chars-missing + +// XFAIL: libcpp-has-no-incomplete-tzdb + +// + +// template +// basic_ostream& +// operator<<(basic_ostream& os, const local_info& r); + +// [time.zone.info.local] +// 3 Effects: Streams out the local_info object r in an unspecified format. +// 4 Returns: os. +// +// There is a private libc++ test that validates the exact output. + +#include +#include +#include +#include + +#include "test_macros.h" + +template +static void test() { + using namespace std::literals::chrono_literals; + std::chrono::sys_info s{std::chrono::sys_seconds{0s}, std::chrono::sys_seconds{0s}, 0h, 0min, ""}; + std::chrono::local_info l{0, s, s}; + std::basic_ostringstream os; + std::basic_ostream& result = std::chrono::operator<<(os, l); + assert(std::addressof(result) == std::addressof(os)); +} + +int main(int, const 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 index f40784ec446fae..fd3416f694ba7c 100644 --- 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 @@ -178,7 +178,7 @@ void test_P1361() { # if !defined(TEST_HAS_NO_INCOMPLETE_TZDB) assert_is_formattable(); - //assert_is_formattable(); + assert_is_formattable(); //assert_is_formattable(); # endif // !defined(TEST_HAS_NO_INCOMPLETE_TZDB)