]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Fix std::format for chrono::duration with unsigned rep [PR115668]
authorJonathan Wakely <jwakely@redhat.com>
Wed, 26 Jun 2024 19:22:54 +0000 (20:22 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Thu, 27 Jun 2024 08:39:41 +0000 (09:39 +0100)
Using std::chrono::abs is only valid if numeric_limits<rep>::is_signed
is true, so using it unconditionally made it ill-formed to format a
duration with an unsigned rep.

The duration formatter might as negate the duration itself instead of
using chrono::abs, because it already needs to check for a negative
value.

libstdc++-v3/ChangeLog:

PR libstdc++/115668
* include/bits/chrono_io.h (formatter<duration<R,P, C>::format):
Do not use chrono::abs.
* testsuite/20_util/duration/io.cc: Check formatting a duration
with unsigned rep.

libstdc++-v3/include/bits/chrono_io.h
libstdc++-v3/testsuite/20_util/duration/io.cc

index 3b34992b42a02ab34cfa2d9507fdae779565173c..72c66a0fef0ddd7394c1f372bd16e48e65309776 100644 (file)
@@ -1607,7 +1607,10 @@ namespace __format
        format(const chrono::duration<_Rep, _Period>& __d,
               basic_format_context<_Out, _CharT>& __fc) const
        {
-         return _M_f._M_format(chrono::abs(__d), __fc, __d < __d.zero());
+         if constexpr (numeric_limits<_Rep>::is_signed)
+           if (__d < __d.zero())
+             return _M_f._M_format(-__d, __fc, true);
+         return _M_f._M_format(__d, __fc, false);
        }
 
     private:
index 2f940ef86b791178ea2be926e4ffd3ee3d2d8e6e..6b00689672c85254f2db75809cc280a836a9a845 100644 (file)
@@ -100,6 +100,12 @@ test_format()
   std::chrono::duration<float, std::milli> d{0.5};
   s = std::format("{}", d);
   VERIFY( s == "0.5ms" );
+
+  std::chrono::duration<unsigned, std::milli> u{500}; // PR libstdc++/115668
+  s = std::format("{}", u);
+  VERIFY( s == "500ms" );
+  s = std::format("{:%Q %q}", u);
+  VERIFY( s == "500 ms" );
 }
 
 void