From b6418b8d5a1806306b90f923107e2c8acff88f3b Mon Sep 17 00:00:00 2001 From: Daniel Marshall Date: Fri, 19 Feb 2021 09:15:50 +0000 Subject: [PATCH 1/4] fix year_month_day_last::day() --- stl/inc/chrono | 6 +++--- .../tests/P0355R7_calendars_and_time_zones_dates/test.cpp | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index 25d3b2ac196..c8fd1f3e629 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -1331,15 +1331,15 @@ namespace chrono { return *this; } - inline constexpr day _Last_day_table[] = { - day{31}, day{28}, day{31}, day{30}, day{31}, day{30}, day{31}, day{31}, day{30}, day{31}, day{30}, day{31}}; + inline constexpr day _Last_day_table[] = {day{31}, day{28}, day{31}, day{30}, day{31}, day{30}, day{31}, day{31}, + day{30}, day{31}, day{30}, day{31}, day{42}, day{42}, day{42}, day{42}}; _NODISCARD constexpr day _Last_day(const year& _Year, const month& _Month) { if (_Month == month{2} && _Year.is_leap()) { return day{29}; } - return _Last_day_table[static_cast(_Month) - 1]; + return _Last_day_table[(static_cast(_Month) - 1) & 15u]; } class year_month_day_last; diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp index 4bb31c8a863..42a92635232 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp @@ -967,6 +967,7 @@ constexpr void year_month_day_last_test() { if (is_constant_evaluated()) { static_assert((2020y / 1 / last).ok()); static_assert(!(2020y / 13 / last).ok()); + static_assert(!(2020y / 0 / last).day().ok()); } else { for (int iy = y_min; iy <= y_max; ++iy) { for (auto m = 0u; m <= 255u; ++m) { @@ -975,7 +976,7 @@ constexpr void year_month_day_last_test() { if (y.ok() && mdl.ok()) { assert((y / mdl).ok()); } else { - assert(!(y / mdl).ok()); + assert(!(y / static_cast(m) / last).ok()); } } } From 4129294bc0b7897644c6c40d9a04cacc49e858e5 Mon Sep 17 00:00:00 2001 From: Daniel Marshall Date: Fri, 19 Feb 2021 09:36:56 +0000 Subject: [PATCH 2/4] fix test --- .../std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp index 42a92635232..321cc3a5dd7 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp @@ -976,7 +976,8 @@ constexpr void year_month_day_last_test() { if (y.ok() && mdl.ok()) { assert((y / mdl).ok()); } else { - assert(!(y / static_cast(m) / last).ok()); + assert(!(y / mdl).ok()); + assert((y / mdl).day().ok() || (y / mdl).day() == day{42}); } } } From 792f6dc67c0bc1090cdeaef94744aa0f9bf81c83 Mon Sep 17 00:00:00 2001 From: Daniel Marshall Date: Sat, 20 Feb 2021 09:51:43 +0000 Subject: [PATCH 3/4] Add comment --- stl/inc/chrono | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/chrono b/stl/inc/chrono index c8fd1f3e629..c4f730b5b25 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -1331,6 +1331,7 @@ namespace chrono { return *this; } + // To prevent UB by going out of bounds, four extra days with an invalid day are added. inline constexpr day _Last_day_table[] = {day{31}, day{28}, day{31}, day{30}, day{31}, day{30}, day{31}, day{31}, day{30}, day{31}, day{30}, day{31}, day{42}, day{42}, day{42}, day{42}}; From 6311ac3f196140be1ceea3ce142f9c91cae66076 Mon Sep 17 00:00:00 2001 From: Daniel Marshall Date: Sun, 21 Feb 2021 08:45:50 +0000 Subject: [PATCH 4/4] STL's feedback --- stl/inc/chrono | 4 ++-- .../std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index c4f730b5b25..759c2029e1d 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -1333,14 +1333,14 @@ namespace chrono { // To prevent UB by going out of bounds, four extra days with an invalid day are added. inline constexpr day _Last_day_table[] = {day{31}, day{28}, day{31}, day{30}, day{31}, day{30}, day{31}, day{31}, - day{30}, day{31}, day{30}, day{31}, day{42}, day{42}, day{42}, day{42}}; + day{30}, day{31}, day{30}, day{31}, day{255}, day{255}, day{255}, day{255}}; _NODISCARD constexpr day _Last_day(const year& _Year, const month& _Month) { if (_Month == month{2} && _Year.is_leap()) { return day{29}; } - return _Last_day_table[(static_cast(_Month) - 1) & 15u]; + return _Last_day_table[(static_cast(_Month) - 1) & 0xF]; } class year_month_day_last; diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp index 321cc3a5dd7..6a59c863a07 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_dates/test.cpp @@ -967,7 +967,7 @@ constexpr void year_month_day_last_test() { if (is_constant_evaluated()) { static_assert((2020y / 1 / last).ok()); static_assert(!(2020y / 13 / last).ok()); - static_assert(!(2020y / 0 / last).day().ok()); + static_assert(!(2020y / 0 / last).day().ok()); // implementation-specific assumption, see GH-1647 } else { for (int iy = y_min; iy <= y_max; ++iy) { for (auto m = 0u; m <= 255u; ++m) { @@ -977,7 +977,7 @@ constexpr void year_month_day_last_test() { assert((y / mdl).ok()); } else { assert(!(y / mdl).ok()); - assert((y / mdl).day().ok() || (y / mdl).day() == day{42}); + assert((y / mdl).day().ok() || (y / mdl).day() == day{255}); // implementation-specific assumption } } }