diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h index 0e4d23c9bb77a8fe98900f99ead1f1433e075cd2..c7d2c9862fcf7917ff7452715f4699a1d6a8991b 100644 --- a/libstdc++-v3/include/bits/chrono_io.h +++ b/libstdc++-v3/include/bits/chrono_io.h @@ -1720,8 +1720,20 @@ namespace __format basic_format_context<_Out, _CharT>& __fc) const { if constexpr (numeric_limits<_Rep>::is_signed) - if (__d < __d.zero()) - return _M_f._M_format(-__d, __fc, true); + if (__d < __d.zero()) [[unlikely]] + { + if constexpr (is_integral_v<_Rep>) + { + // -d is undefined for the most negative integer. + // Convert duration to corresponding unsigned rep. + using _URep = make_unsigned_t<_Rep>; + auto __ucnt = -static_cast<_URep>(__d.count()); + auto __ud = chrono::duration<_URep, _Period>(__ucnt); + return _M_f._M_format(__ud, __fc, true); + } + else + return _M_f._M_format(-__d, __fc, true); + } return _M_f._M_format(__d, __fc, false); } diff --git a/libstdc++-v3/testsuite/20_util/duration/io.cc b/libstdc++-v3/testsuite/20_util/duration/io.cc index 6b00689672c85254f2db75809cc280a836a9a845..57020f4f953767bf1fad7eca88d3caf9bb464834 100644 --- a/libstdc++-v3/testsuite/20_util/duration/io.cc +++ b/libstdc++-v3/testsuite/20_util/duration/io.cc @@ -106,6 +106,14 @@ test_format() VERIFY( s == "500ms" ); s = std::format("{:%Q %q}", u); VERIFY( s == "500 ms" ); + + // PR libstdc++/116755 extra minus sign for most negative value + auto minsec = std::chrono::seconds::min(); + s = std::format("{}", minsec); + auto expected = std::format("{}s", minsec.count()); + VERIFY( s == expected ); + s = std::format("{:%Q%q}", minsec); + VERIFY( s == expected ); } void