From: Jonathan Wakely Date: Wed, 26 Jun 2024 19:22:54 +0000 (+0100) Subject: libstdc++: Fix std::format for chrono::duration with unsigned rep [PR115668] X-Git-Tag: basepoints/gcc-16~7863 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dafa750c8a6f0a088677871bfaad054881737ab1;p=thirdparty%2Fgcc.git libstdc++: Fix std::format for chrono::duration with unsigned rep [PR115668] Using std::chrono::abs is only valid if numeric_limits::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::format): Do not use chrono::abs. * testsuite/20_util/duration/io.cc: Check formatting a duration with unsigned rep. --- diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h index 3b34992b42a0..72c66a0fef0d 100644 --- a/libstdc++-v3/include/bits/chrono_io.h +++ b/libstdc++-v3/include/bits/chrono_io.h @@ -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: diff --git a/libstdc++-v3/testsuite/20_util/duration/io.cc b/libstdc++-v3/testsuite/20_util/duration/io.cc index 2f940ef86b79..6b00689672c8 100644 --- a/libstdc++-v3/testsuite/20_util/duration/io.cc +++ b/libstdc++-v3/testsuite/20_util/duration/io.cc @@ -100,6 +100,12 @@ test_format() std::chrono::duration d{0.5}; s = std::format("{}", d); VERIFY( s == "0.5ms" ); + + std::chrono::duration u{500}; // PR libstdc++/115668 + s = std::format("{}", u); + VERIFY( s == "500ms" ); + s = std::format("{:%Q %q}", u); + VERIFY( s == "500 ms" ); } void