libstdc++: Fix arithmetic bug in chrono::year_month::operator+
authorPatrick Palka <ppalka@redhat.com>
Thu, 27 Aug 2020 18:11:24 +0000 (14:11 -0400)
committerPatrick Palka <ppalka@redhat.com>
Thu, 27 Aug 2020 18:11:24 +0000 (14:11 -0400)
This fixes the months-based addition for year_month when the
year_month's month component is 0.

libstdc++-v3/ChangeLog:

* include/std/chrono (year_month::operator+): Properly handle a
month value of 0 by casting the month value to int before
subtracting 1 from it so that the difference is sign-extended in
the subsequent addition.
* testsuite/std/time/year_month/1.cc: Test adding months to a
year_month whose month component is below or above the
normalized range of [1,12].

libstdc++-v3/include/std/chrono
libstdc++-v3/testsuite/std/time/year_month/1.cc

index df2f5d23f527799896fd88340e37409c0d6a3271..9fc8f560d992029fe7b072368de012acca278a95 100644 (file)
@@ -2133,7 +2133,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        {
          // TODO: Optimize?
          auto __m = __ym.month() + __dm;
-         auto __i = unsigned{__ym.month()} - 1 + __dm.count();
+         auto __i = int(unsigned(__ym.month())) - 1 + __dm.count();
          auto __y = (__i < 0
                      ? __ym.year() + years{(__i - 11) / 12}
                      : __ym.year() + years{__i / 12});
index 007cfeb2f7287f57c12d7f408635bb494c2c9146..4c331dcdb5011ad3b7691a789162190320c30884 100644 (file)
@@ -83,4 +83,16 @@ constexpr_year_month()
   static_assert(2017y/33 + months{0} == 2019y/9);
 
   static_assert(2010y/January + months{-12} == 2009y/January);
+
+  static_assert(2010y/month{0} + months{-1} == 2009y/November);
+  static_assert(2010y/month{0} + months{0} == 2009y/December);
+  static_assert(2010y/month{0} + months{1} == 2010y/January);
+  static_assert(2010y/month{0} + months{2} == 2010y/February);
+  static_assert(2010y/month{0} + months{11} == 2010y/November);
+  static_assert(2010y/month{0} + months{12} == 2010y/December);
+  static_assert(2010y/month{0} + months{13} == 2011y/January);
+
+  static_assert(months{-1} + 2010y/month{37} == 2012y/December);
+  static_assert(months{0} + 2010y/month{37} == 2013y/January);
+  static_assert(months{1} + 2010y/month{37} == 2013y/February);
 }