[libcxx-commits] [libcxx] [libc++][chrono] Fixes year_month year wrapping. (PR #74938)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Dec 9 08:20:57 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Mark de Wever (mordante)

<details>
<summary>Changes</summary>

Adding months to a year_month should wrap the year when the month becomes greater than twelve or less than one.

This fixes the issue for year_month. Other classes with a year and month do not have this issue. This has been verified and tests are added to avoid possible regressions.

Also fixes some variable copy-paste errors in the tests.

Fixes https://github.com/llvm/llvm-project/issues/73162

---

Patch is 31.90 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/74938.diff


15 Files Affected:

- (modified) libcxx/include/__chrono/year_month.h (+24-4) 
- (modified) libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.members/plus_minus_equal_month.pass.cpp (+10) 
- (modified) libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/minus.pass.cpp (+7-2) 
- (modified) libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/plus.pass.cpp (+17-13) 
- (modified) libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.members/plus_minus_equal_month.pass.cpp (+34) 
- (modified) libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/plus.pass.cpp (+31-20) 
- (modified) libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/plus_minus_equal_month.pass.cpp (+19-9) 
- (modified) libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/minus.pass.cpp (+14-9) 
- (modified) libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/plus.pass.cpp (+25-17) 
- (modified) libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/plus_minus_equal_month.pass.cpp (+10) 
- (modified) libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/minus.pass.cpp (+20-12) 
- (modified) libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/plus.pass.cpp (+37-24) 
- (modified) libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.members/plus_minus_equal_month.pass.cpp (+22-13) 
- (modified) libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/minus.pass.cpp (+20-12) 
- (modified) libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/plus.pass.cpp (+39-26) 


``````````diff
diff --git a/libcxx/include/__chrono/year_month.h b/libcxx/include/__chrono/year_month.h
index f4eea8427fc51..d1657b61015b9 100644
--- a/libcxx/include/__chrono/year_month.h
+++ b/libcxx/include/__chrono/year_month.h
@@ -36,10 +36,10 @@ class year_month {
         : __y_{__yval}, __m_{__mval} {}
     _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year  year()  const noexcept { return __y_; }
     _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; }
-    _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator+=(const months& __dm) noexcept { this->__m_ += __dm; return *this; }
-    _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator-=(const months& __dm) noexcept { this->__m_ -= __dm; return *this; }
-    _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator+=(const years& __dy)  noexcept { this->__y_ += __dy; return *this; }
-    _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator-=(const years& __dy)  noexcept { this->__y_ -= __dy; return *this; }
+    _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator+=(const months& __dm) noexcept;
+    _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator-=(const months& __dm) noexcept;
+    _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator+=(const years& __dy) noexcept;
+    _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& operator-=(const years& __dy) noexcept;
     _LIBCPP_HIDE_FROM_ABI inline constexpr bool ok() const noexcept { return __y_.ok() && __m_.ok(); }
 };
 
@@ -92,6 +92,26 @@ _LIBCPP_HIDE_FROM_ABI constexpr
 year_month operator-(const year_month& __lhs, const years& __rhs) noexcept
 { return __lhs + -__rhs; }
 
+_LIBCPP_HIDE_FROM_ABI inline constexpr year_month& year_month::operator+=(const months& __dm) noexcept {
+  *this = *this + __dm;
+  return *this;
+}
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr year_month& year_month::operator-=(const months& __dm) noexcept {
+  *this = *this - __dm;
+  return *this;
+}
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr year_month& year_month::operator+=(const years& __dy) noexcept {
+  *this = *this + __dy;
+  return *this;
+}
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr year_month& year_month::operator-=(const years& __dy) noexcept {
+  *this = *this - __dy;
+  return *this;
+}
+
 } // namespace chrono
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.members/plus_minus_equal_month.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.members/plus_minus_equal_month.pass.cpp
index 6d1273ead7391..cc9fff83a1cff 100644
--- a/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.members/plus_minus_equal_month.pass.cpp
+++ b/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.members/plus_minus_equal_month.pass.cpp
@@ -38,6 +38,16 @@ constexpr bool test() {
     assert(ym.year() == y);
   }
 
+  { // Test year wrapping
+    year_month ym{year{2020}, month{4}};
+
+    ym += months{12};
+    assert((ym == year_month{year{2021}, month{4}}));
+
+    ym -= months{12};
+    assert((ym == year_month{year{2020}, month{4}}));
+  }
+
   return true;
 }
 
diff --git a/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/minus.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/minus.pass.cpp
index 5bacee9af7f82..977c566e745ac 100644
--- a/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/minus.pass.cpp
+++ b/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/minus.pass.cpp
@@ -46,12 +46,17 @@ constexpr bool test() {
   { // year_month - months
 
     year_month ym{year{1234}, std::chrono::November};
-    for (int i = 0; i <= 10; ++i) // TODO test wrap-around
-    {
+    for (int i = 0; i <= 10; ++i) {
       year_month ym1 = ym - months{i};
       assert(static_cast<int>(ym1.year()) == 1234);
       assert(ym1.month() == month(11 - i));
     }
+    // Test the year wraps around.
+    for (int i = 12; i <= 15; ++i) {
+      year_month ym1 = ym - months{i};
+      assert(static_cast<int>(ym1.year()) == 1233);
+      assert(ym1.month() == month(11 - i + 12));
+    }
   }
 
   { // year_month - year_month
diff --git a/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/plus.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/plus.pass.cpp
index 315d74b75bbcc..60747a29714d1 100644
--- a/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/plus.pass.cpp
+++ b/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/plus.pass.cpp
@@ -29,10 +29,10 @@
 
 #include "test_macros.h"
 
-using year = std::chrono::year;
-using years = std::chrono::years;
-using month = std::chrono::month;
-using months = std::chrono::months;
+using year       = std::chrono::year;
+using years      = std::chrono::years;
+using month      = std::chrono::month;
+using months     = std::chrono::months;
 using year_month = std::chrono::year_month;
 
 // year_month + years
@@ -40,10 +40,8 @@ constexpr bool test_ym_plus_y() {
   ASSERT_NOEXCEPT(std::declval<year_month>() + std::declval<years>());
   ASSERT_NOEXCEPT(std::declval<years>() + std::declval<year_month>());
 
-  ASSERT_SAME_TYPE(
-      year_month, decltype(std::declval<year_month>() + std::declval<years>()));
-  ASSERT_SAME_TYPE(
-      year_month, decltype(std::declval<years>() + std::declval<year_month>()));
+  ASSERT_SAME_TYPE(year_month, decltype(std::declval<year_month>() + std::declval<years>()));
+  ASSERT_SAME_TYPE(year_month, decltype(std::declval<years>() + std::declval<year_month>()));
 
   year_month ym{year{1234}, std::chrono::January};
   for (int i = 0; i <= 10; ++i) {
@@ -64,10 +62,17 @@ constexpr bool test_ym_plus_m() {
   ASSERT_NOEXCEPT(std::declval<year_month>() + std::declval<months>());
   ASSERT_NOEXCEPT(std::declval<months>() + std::declval<year_month>());
 
-  ASSERT_SAME_TYPE(year_month, decltype(std::declval<year_month>() +
-                                        std::declval<months>()));
-  ASSERT_SAME_TYPE(year_month, decltype(std::declval<months>() +
-                                        std::declval<year_month>()));
+  ASSERT_SAME_TYPE(year_month, decltype(std::declval<year_month>() + std::declval<months>()));
+  ASSERT_SAME_TYPE(year_month, decltype(std::declval<months>() + std::declval<year_month>()));
+
+  {
+    // [time.cal.ym.nonmembers]/4
+    // Returns: A year_month value z such that z.ok() && z - ym == dm is true.
+    year_month ym = {year{1234}, std::chrono::January};
+    months dm     = months{42};
+    year_month z  = ym + dm;
+    assert(z.ok() && z - ym == dm);
+  }
 
   year_month ym{year{1234}, std::chrono::January};
   for (int i = 0; i <= 11; ++i) {
@@ -89,7 +94,6 @@ constexpr bool test_ym_plus_m() {
     assert(ym2.month() == month(1 + i % 12));
     assert(ym1 == ym2);
   }
-
   return true;
 }
 
diff --git a/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.members/plus_minus_equal_month.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.members/plus_minus_equal_month.pass.cpp
index f656d8f6cc056..40db399b110b8 100644
--- a/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.members/plus_minus_equal_month.pass.cpp
+++ b/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.members/plus_minus_equal_month.pass.cpp
@@ -42,6 +42,40 @@ constexpr bool test() {
     assert(static_cast<unsigned>((ymd).month()) == i + 1);
   }
 
+  { // Validate the ok status when the day is not present in the new month.
+    year_month_day ymd{year{2020}, month{3}, day{31}};
+    ymd += months{1};
+    assert((ymd == year_month_day{year{2020}, month{4}, day{31}}));
+    assert(!ymd.ok());
+
+    ymd -= months{1};
+    assert((ymd == year_month_day{year{2020}, month{3}, day{31}}));
+    assert(ymd.ok());
+  }
+
+  { // Validate the ok status when the day becomes present in the new month.
+    year_month_day ymd{year{2020}, month{4}, day{31}};
+    assert(!ymd.ok());
+
+    ymd += months{1};
+    assert((ymd == year_month_day{year{2020}, month{5}, day{31}}));
+    assert(ymd.ok());
+
+    ymd -= months{2};
+    assert((ymd == year_month_day{year{2020}, month{3}, day{31}}));
+    assert(ymd.ok());
+  }
+
+  { // Test year wrapping
+    year_month_day ymd{year{2020}, month{4}, day{31}};
+
+    ymd += months{12};
+    assert((ymd == year_month_day{year{2021}, month{4}, day{31}}));
+
+    ymd -= months{12};
+    assert((ymd == year_month_day{year{2020}, month{4}, day{31}}));
+  }
+
   return true;
 }
 
diff --git a/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/plus.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/plus.pass.cpp
index 27626e40fceb7..b172cb1384570 100644
--- a/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/plus.pass.cpp
+++ b/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/plus.pass.cpp
@@ -39,32 +39,43 @@ using year_month_day = std::chrono::year_month_day;
 constexpr bool test() {
   { // year_month_day + months
     year_month_day ym{year{1234}, std::chrono::January, day{12}};
-    for (int i = 0; i <= 10; ++i) // TODO test wrap-around
-    {
-      year_month_day ym1 = ym + months{i};
-      year_month_day ym2 = months{i} + ym;
-      assert(static_cast<int>(ym1.year()) == 1234);
-      assert(static_cast<int>(ym2.year()) == 1234);
-      assert(ym1.month() == month(1 + i));
-      assert(ym2.month() == month(1 + i));
-      assert(ym1.day() == day{12});
-      assert(ym2.day() == day{12});
-      assert(ym1 == ym2);
+    for (int i = 0; i <= 10; ++i) {
+      year_month_day ymd1 = ym + months{i};
+      year_month_day ymd2 = months{i} + ym;
+      assert(static_cast<int>(ymd1.year()) == 1234);
+      assert(static_cast<int>(ymd2.year()) == 1234);
+      assert(ymd1.month() == month(1 + i));
+      assert(ymd2.month() == month(1 + i));
+      assert(ymd1.day() == day{12});
+      assert(ymd2.day() == day{12});
+      assert(ymd1 == ymd2);
+    }
+    // Test the year wraps around.
+    for (int i = 12; i <= 15; ++i) {
+      year_month_day ymd1 = ym + months{i};
+      year_month_day ymd2 = months{i} + ym;
+      assert(static_cast<int>(ymd1.year()) == 1235);
+      assert(static_cast<int>(ymd2.year()) == 1235);
+      assert(ymd1.month() == month(1 + i - 12));
+      assert(ymd2.month() == month(1 + i - 12));
+      assert(ymd1.day() == day{12});
+      assert(ymd2.day() == day{12});
+      assert(ymd1 == ymd2);
     }
   }
 
   { // year_month_day + years
     year_month_day ym{year{1234}, std::chrono::January, day{12}};
     for (int i = 0; i <= 10; ++i) {
-      year_month_day ym1 = ym + years{i};
-      year_month_day ym2 = years{i} + ym;
-      assert(static_cast<int>(ym1.year()) == i + 1234);
-      assert(static_cast<int>(ym2.year()) == i + 1234);
-      assert(ym1.month() == std::chrono::January);
-      assert(ym2.month() == std::chrono::January);
-      assert(ym1.day() == day{12});
-      assert(ym2.day() == day{12});
-      assert(ym1 == ym2);
+      year_month_day ymd1 = ym + years{i};
+      year_month_day ymd2 = years{i} + ym;
+      assert(static_cast<int>(ymd1.year()) == i + 1234);
+      assert(static_cast<int>(ymd2.year()) == i + 1234);
+      assert(ymd1.month() == std::chrono::January);
+      assert(ymd2.month() == std::chrono::January);
+      assert(ymd1.day() == day{12});
+      assert(ymd2.day() == day{12});
+      assert(ymd1 == ymd2);
     }
   }
 
diff --git a/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/plus_minus_equal_month.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/plus_minus_equal_month.pass.cpp
index dfa0f002bfb92..1c08479596016 100644
--- a/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/plus_minus_equal_month.pass.cpp
+++ b/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/plus_minus_equal_month.pass.cpp
@@ -29,15 +29,25 @@ constexpr bool test() {
   for (unsigned i = 0; i <= 10; ++i) {
     year y{1234};
     month_day_last mdl{month{i}};
-    year_month_day_last ym(y, mdl);
-    assert(static_cast<unsigned>((ym += months{2}).month()) == i + 2);
-    assert(ym.year() == y);
-    assert(static_cast<unsigned>((ym).month()) == i + 2);
-    assert(ym.year() == y);
-    assert(static_cast<unsigned>((ym -= months{1}).month()) == i + 1);
-    assert(ym.year() == y);
-    assert(static_cast<unsigned>((ym).month()) == i + 1);
-    assert(ym.year() == y);
+    year_month_day_last ymdl(y, mdl);
+    assert(static_cast<unsigned>((ymdl += months{2}).month()) == i + 2);
+    assert(ymdl.year() == y);
+    assert(static_cast<unsigned>((ymdl).month()) == i + 2);
+    assert(ymdl.year() == y);
+    assert(static_cast<unsigned>((ymdl -= months{1}).month()) == i + 1);
+    assert(ymdl.year() == y);
+    assert(static_cast<unsigned>((ymdl).month()) == i + 1);
+    assert(ymdl.year() == y);
+  }
+
+  { // Test year wrapping
+    year_month_day_last ymdl{year{2020}, month_day_last{month{4}}};
+
+    ymdl += months{12};
+    assert((ymdl == year_month_day_last{year{2021}, month_day_last{month{4}}}));
+
+    ymdl -= months{12};
+    assert((ymdl == year_month_day_last{year{2020}, month_day_last{month{4}}}));
   }
 
   return true;
diff --git a/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/minus.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/minus.pass.cpp
index 009790a450e9d..22d1acfbe2827 100644
--- a/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/minus.pass.cpp
+++ b/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/minus.pass.cpp
@@ -38,22 +38,27 @@ constexpr bool test() {
 
   { // year_month_day_last - years
 
-    year_month_day_last ym{year{1234}, month_day_last{December}};
+    year_month_day_last ymdl{year{1234}, month_day_last{December}};
     for (int i = 0; i <= 10; ++i) {
-      year_month_day_last ym1 = ym - years{i};
-      assert(static_cast<int>(ym1.year()) == 1234 - i);
-      assert(ym1.month() == December);
+      year_month_day_last ymdl1 = ymdl - years{i};
+      assert(static_cast<int>(ymdl1.year()) == 1234 - i);
+      assert(ymdl1.month() == December);
     }
   }
 
   { // year_month_day_last - months
 
-    // TODO test wrapping
-    year_month_day_last ym{year{1234}, month_day_last{December}};
+    year_month_day_last ymdl{year{1234}, month_day_last{December}};
     for (unsigned i = 0; i <= 10; ++i) {
-      year_month_day_last ym1 = ym - months{i};
-      assert(static_cast<int>(ym1.year()) == 1234);
-      assert(static_cast<unsigned>(ym1.month()) == 12U - i);
+      year_month_day_last ymdl1 = ymdl - months{i};
+      assert(static_cast<int>(ymdl1.year()) == 1234);
+      assert(static_cast<unsigned>(ymdl1.month()) == 12U - i);
+    }
+    // Test the year wraps around.
+    for (unsigned i = 12; i <= 15; ++i) {
+      year_month_day_last ymdl1 = ymdl - months{i};
+      assert(static_cast<int>(ymdl1.year()) == 1233);
+      assert(static_cast<unsigned>(ymdl1.month()) == 12U - i + 12);
     }
   }
 
diff --git a/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/plus.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/plus.pass.cpp
index 4cbc3d1a1994e..1a4609e761baa 100644
--- a/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/plus.pass.cpp
+++ b/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/plus.pass.cpp
@@ -49,29 +49,37 @@ constexpr bool test() {
 
   { // year_month_day_last + months
     year_month_day_last ym{year{1234}, month_day_last{January}};
-    for (int i = 0; i <= 10; ++i) // TODO test wrap-around
-    {
-      year_month_day_last ym1 = ym + months{i};
-      year_month_day_last ym2 = months{i} + ym;
-      assert(static_cast<int>(ym1.year()) == 1234);
-      assert(static_cast<int>(ym2.year()) == 1234);
-      assert(ym1.month() == month(1 + i));
-      assert(ym2.month() == month(1 + i));
-      assert(ym1 == ym2);
+    for (int i = 0; i <= 10; ++i) {
+      year_month_day_last ymdl1 = ym + months{i};
+      year_month_day_last ymdl2 = months{i} + ym;
+      assert(static_cast<int>(ymdl1.year()) == 1234);
+      assert(static_cast<int>(ymdl2.year()) == 1234);
+      assert(ymdl1.month() == month(1 + i));
+      assert(ymdl2.month() == month(1 + i));
+      assert(ymdl1 == ymdl2);
+    }
+    // Test the year wraps around.
+    for (int i = 12; i <= 15; ++i) {
+      year_month_day_last ymdl1 = ym + months{i};
+      year_month_day_last ymdl2 = months{i} + ym;
+      assert(static_cast<int>(ymdl1.year()) == 1235);
+      assert(static_cast<int>(ymdl2.year()) == 1235);
+      assert(ymdl1.month() == month(1 + i - 12));
+      assert(ymdl2.month() == month(1 + i - 12));
+      assert(ymdl1 == ymdl2);
     }
   }
 
   { // year_month_day_last + years
-
     year_month_day_last ym{year{1234}, month_day_last{January}};
     for (int i = 0; i <= 10; ++i) {
-      year_month_day_last ym1 = ym + years{i};
-      year_month_day_last ym2 = years{i} + ym;
-      assert(static_cast<int>(ym1.year()) == i + 1234);
-      assert(static_cast<int>(ym2.year()) == i + 1234);
-      assert(ym1.month() == std::chrono::January);
-      assert(ym2.month() == std::chrono::January);
-      assert(ym1 == ym2);
+      year_month_day_last ymdl1 = ym + years{i};
+      year_month_day_last ymdl2 = years{i} + ym;
+      assert(static_cast<int>(ymdl1.year()) == i + 1234);
+      assert(static_cast<int>(ymdl2.year()) == i + 1234);
+      assert(ymdl1.month() == std::chrono::January);
+      assert(ymdl2.month() == std::chrono::January);
+      assert(ymdl1 == ymdl2);
     }
   }
 
diff --git a/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/plus_minus_equal_month.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/plus_minus_equal_month.pass.cpp
index 8b49540be3fa2..6aaab2dbfb31d 100644
--- a/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/plus_minus_equal_month.pass.cpp
+++ b/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/plus_minus_equal_month.pass.cpp
@@ -54,6 +54,16 @@ constexpr bool test() {
     assert(ymwd.index() == 2);
   }
 
+  { // Test year wrapping
+    year_month_weekday ymwd{year{2020}, month{4}, weekday_indexed{Tuesday, 2}};
+
+    ymwd += months{12};
+    assert((ymwd == year_month_weekday{year{2021}, month{4}, weekday_indexed{Tuesday, 2}}));
+
+    ymwd -= months{12};
+    assert((ymwd == year_month_weekday{year{2020}, month{4}, weekday_indexed{Tuesday, 2}}));
+  }
+
   return true;
 }
 
diff --git a/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/minus.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/minus.pass.cpp
index 2ab3462d7f7d1..5546d34ca22dd 100644
--- a/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/minus.pass.cpp
+++ b/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/minus.pass.cpp
@@ -35,24 +35,32 @@ constexpr bool test() {
   constexpr weekday Tuesday = std::chrono::Tuesday;
 
   { // year_month_weekday - years
-    year_month_weekday ym{year{1234}, November, weekday_indexed{Tuesday, 1}};
+    year_month_weekday ymwd{year{1234}, November, weekday_indexed{Tuesday, 1}};
     for (int i = 0; i <= 10; ++i) {
-      year_month_weekday ym1 = ym - years{i};
-      assert(static_cast<int>(ym1.year()) == 1234 - i);
-      assert(ym1.month() == November);
-      assert(ym1.weekday() == Tuesday);
-      assert(ym1.index() == 1);
+      year_month_weekday ymwd1 = ymwd - years{i};
+      assert(static_cast<int>(ymwd1.year()) == 1234 - i);
+      assert(ymwd1.month() == November);
+      assert(ymwd1.weekday() == Tuesday);
+      assert(ymwd1.index() == 1);
     }
   }
 
   { // year_month_weekday - months
-    year_month_weekday ym{year{1234}, November, weekday_indexed{Tuesday, 2}};
+    year_month_weekday ymwd{year{1234}, November, weekday_indexed{Tuesday, 2}};
     for (unsigned i = 1; i <= 10; ++i) {
-      year_month_weekday ym1 = ym - months{i};
-      assert(ym1.year() == year{1234});
-      assert(ym1.month() == month{11 - i});
-      assert(ym1.weekday() == Tuesday);
-      assert(ym1.index() == 2);
+      year_month_weekday ymwd1 = ymwd - months{i};
+      assert(ymwd1.year() == year{1234});
+      assert(ymwd1.month() == month{11 - i});
+      assert(ymwd1.weekday() == Tuesday);
+      assert(ymwd1.index(...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/74938


More information about the libcxx-commits mailing list