https://gcc.gnu.org/g:4b64a1051a927a65a9acefbbb5714a8118c320bc
commit r13-8877-g4b64a1051a927a65a9acefbbb5714a8118c320bc Author: Jonathan Wakely <jwak...@redhat.com> Date: Wed Jun 26 20:22:54 2024 +0100 libstdc++: Fix std::format for chrono::duration with unsigned rep [PR115668] 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 well 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. (cherry picked from commit dafa750c8a6f0a088677871bfaad054881737ab1) Diff: --- libstdc++-v3/include/bits/chrono_io.h | 5 ++++- libstdc++-v3/testsuite/20_util/duration/io.cc | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h index 1838ad1a8c6..d63f7c40d83 100644 --- a/libstdc++-v3/include/bits/chrono_io.h +++ b/libstdc++-v3/include/bits/chrono_io.h @@ -1608,7 +1608,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 2043f0c4e9d..b7028a4e6c6 100644 --- a/libstdc++-v3/testsuite/20_util/duration/io.cc +++ b/libstdc++-v3/testsuite/20_util/duration/io.cc @@ -101,6 +101,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" ); } int main()