From 6e2f3d43355932cfa74723e06cfb0bf10ef896d7 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 11 Apr 2023 11:56:23 +0800 Subject: [PATCH 1/9] Additional test for `duration` formatting --- .../P0355R7_calendars_and_time_zones_formatting/test.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp index 1b4e719d1b..b3d244baf3 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp @@ -247,13 +247,21 @@ void empty_braces_helper( template void test_duration_formatter() { + using LongRatio = ratio; + empty_braces_helper(seconds{5}, STR("5s")); empty_braces_helper(minutes{7}, STR("7min")); empty_braces_helper(hours{9}, STR("9h")); empty_braces_helper(days{2}, STR("2d")); empty_braces_helper(-seconds{5}, STR("-5s")); + empty_braces_helper(duration>{40}, STR("40[2]s")); empty_braces_helper(duration>{40}, STR("40[3]s")); empty_braces_helper(duration>{40}, STR("40[3/7]s")); + empty_braces_helper(duration>{40}, STR("40[1/2]s")); + empty_braces_helper(duration>{40}, STR("40[22/7]s")); + empty_braces_helper(duration>{40}, STR("40[53/101]s")); + empty_braces_helper(duration>{40}, STR("40[201/2147483647]s")); + empty_braces_helper(duration{40}, STR("40[9223372036854775806/9223372036854775807]s")); // formatting small types needs to work as iostreams << VSO-1521926 empty_braces_helper(duration{123}, STR("123as")); From 01d1e1672d635f36b3e7125a5e860d6ca5deeabb Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 11 Apr 2023 11:59:58 +0800 Subject: [PATCH 2/9] Additional tests for `duration` stream output --- .../tests/P0355R7_calendars_and_time_zones_io/test.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp index 5f46e0fc9c..40f0f1965b 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp @@ -90,8 +90,12 @@ void test_duration_output() { assert(test_duration_basic_out(duration>{42}, "42d")); assert(test_duration_basic_out(duration>{24}, "24[2]s")); + assert(test_duration_basic_out(duration>{24}, "24[3]s")); + assert(test_duration_basic_out(duration>{24}, "24[3/7]s")); assert(test_duration_basic_out(duration>{24}, "24[1/2]s")); assert(test_duration_basic_out(duration>{24}, "24[22/7]s")); + assert(test_duration_basic_out(duration>{24}, "24[53/101]s")); + assert(test_duration_basic_out(duration>{24}, "24[201/2147483647]s")); assert(test_duration_basic_out(duration{24}, "24[9223372036854775806/9223372036854775807]s")); assert(test_duration_basic_out(duration{0.140625}, "0.140625s")); @@ -119,8 +123,12 @@ void test_duration_output() { assert(test_duration_basic_out(duration>{42}, L"42d")); assert(test_duration_basic_out(duration>{24}, L"24[2]s")); + assert(test_duration_basic_out(duration>{24}, L"24[3]s")); + assert(test_duration_basic_out(duration>{24}, L"24[3/7]s")); assert(test_duration_basic_out(duration>{24}, L"24[1/2]s")); assert(test_duration_basic_out(duration>{24}, L"24[22/7]s")); + assert(test_duration_basic_out(duration>{24}, L"24[53/101]s")); + assert(test_duration_basic_out(duration>{24}, L"24[201/2147483647]s")); assert(test_duration_basic_out(duration{24}, L"24[9223372036854775806/9223372036854775807]s")); assert(test_duration_basic_out(duration{0.140625}, L"0.140625s")); From 3b0e5c2d3791770024a8580df02c2fbf4a2f0469 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 11 Apr 2023 12:11:56 +0800 Subject: [PATCH 3/9] Fix `hh_mm_ss` conversion for formatting --- stl/inc/chrono | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index 202b9aa847..0cff1406a9 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -4945,8 +4945,8 @@ namespace chrono { } template - _NODISCARD constexpr hh_mm_ss<_Duration> _Hh_mm_ss_part_underflow_to_zero(const _Duration& _Val) { - return hh_mm_ss<_Duration>{_Remove_duration_part(_Val)}; + _NODISCARD constexpr auto _Hh_mm_ss_part_underflow_to_zero(const _Duration& _Val) { + return hh_mm_ss>{_Remove_duration_part(_Val)}; } template From 094cb746d20ed232404e2a651834b183d3d7a6f1 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 11 Apr 2023 12:41:14 +0800 Subject: [PATCH 4/9] Missed duplication --- .../tests/P0355R7_calendars_and_time_zones_formatting/test.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp index b3d244baf3..e718074230 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,8 @@ using namespace std; using namespace chrono; +constexpr auto intmax_max = numeric_limits::max(); + template [[nodiscard]] constexpr const CharT* choose_literal(const char* const str, const wchar_t* const wstr) noexcept { if constexpr (is_same_v) { From 96f039b4610be55099c77b5538e15f5df7250e18 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 11 Apr 2023 23:32:48 +0800 Subject: [PATCH 5/9] Fix calculation of `hh_mm_ss::fractional_width` --- stl/inc/chrono | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index 0cff1406a9..969f7f7c95 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -1578,16 +1578,23 @@ namespace chrono { "N4885 [time.hms.overview]/2 mandates Duration to be a specialization of chrono::duration."); static constexpr unsigned int fractional_width = [] { - auto _Num = _Duration::period::num; - constexpr auto _Den = _Duration::period::den; // Returns the number of fractional digits of _Num / _Den in the range [0, 18]. // If it can't be represented, 6 is returned. // Example: _Fractional_width(1, 8) would return 3 for 0.125. - _STL_ASSERT(_Num > 0 && _Den > 0, "Numerator and denominator can't be less than 1."); - unsigned int _Result = 0; - for (; _Num % _Den != 0 && _Result < 19; _Num = _Num % _Den * 10, ++_Result) { + auto _Den = _Duration::period::den; + _STL_ASSERT(_Duration::period::num > 0 && _Den > 0, "Numerator and denominator can't be less than 1."); + unsigned int _Power_of_2_in_den = 0u; + unsigned int _Power_of_5_in_den = 0u; + for (; _Den % 2 == 0; _Den /= 2, ++_Power_of_2_in_den) { } - return _Result == 19 ? 6 : _Result; + for (; _Den % 5 == 0; _Den /= 5, ++_Power_of_5_in_den) { + } + + if (_Den != 1) { + return 6u; + } + const auto _Result = _STD max(_Power_of_2_in_den, _Power_of_5_in_den); + return _Result > 18u ? 6u : _Result; }(); using precision = duration, ratio<1, _Pow10(fractional_width)>>; From aeef02980ef96e5efeeed0c4e0b7475e2615db12 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Wed, 12 Apr 2023 12:05:47 +0800 Subject: [PATCH 6/9] Restrict the test, leaving UB alone --- .../tests/P0355R7_calendars_and_time_zones_formatting/test.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp index e718074230..70306cf967 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp @@ -264,7 +264,8 @@ void test_duration_formatter() { empty_braces_helper(duration>{40}, STR("40[22/7]s")); empty_braces_helper(duration>{40}, STR("40[53/101]s")); empty_braces_helper(duration>{40}, STR("40[201/2147483647]s")); - empty_braces_helper(duration{40}, STR("40[9223372036854775806/9223372036854775807]s")); + // TRANSITION, duration_cast used in formatting may raise UB + empty_braces_helper(duration{1}, STR("1[9223372036854775806/9223372036854775807]s")); // formatting small types needs to work as iostreams << VSO-1521926 empty_braces_helper(duration{123}, STR("123as")); From 360f1dc54e93027f4afbd04259565cbccd4e05c1 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Sun, 16 Apr 2023 14:29:19 +0800 Subject: [PATCH 7/9] Mention LWG-3921 --- .../tests/P0355R7_calendars_and_time_zones_formatting/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp index a79bef5bf1..c969497229 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp @@ -264,7 +264,7 @@ void test_duration_formatter() { empty_braces_helper(duration>{40}, STR("40[22/7]s")); empty_braces_helper(duration>{40}, STR("40[53/101]s")); empty_braces_helper(duration>{40}, STR("40[201/2147483647]s")); - // TRANSITION, duration_cast used in formatting may raise UB + // TRANSITION, LWG-3921: duration_cast used in formatting may raise UB empty_braces_helper(duration{1}, STR("1[9223372036854775806/9223372036854775807]s")); // formatting small types needs to work as iostreams << VSO-1521926 From e61a93978b148066ca35d3e9c9a36d8e5e6e7816 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 25 Apr 2023 16:24:13 -0700 Subject: [PATCH 8/9] Include more headers. --- .../tests/P0355R7_calendars_and_time_zones_formatting/test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp index c969497229..b15d9cc5cb 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp @@ -5,11 +5,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include From a608930a3cc37a26ba7594e538c4a36fc23e3333 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 27 Apr 2023 12:32:02 -0700 Subject: [PATCH 9/9] Defend against macroization. --- stl/inc/chrono | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index b9be53bd98..96e1157fda 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -1593,7 +1593,7 @@ namespace chrono { if (_Den != 1) { return 6u; } - const auto _Result = _STD max(_Power_of_2_in_den, _Power_of_5_in_den); + const auto _Result = (_STD max)(_Power_of_2_in_den, _Power_of_5_in_den); return _Result > 18u ? 6u : _Result; }(); using precision =