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)
This commit is contained in:
Jonathan Wakely 2024-06-26 20:22:54 +01:00
parent ef8b60dd48
commit d5e352addf
2 changed files with 10 additions and 1 deletions

View 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:

View 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