diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index f787da69e5fc1f39fb70341cf1f69f5dd8dcf124..fd4cc9205aa27fcae9f9d3fd9ccad7e8f193f14d 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -2478,7 +2478,8 @@ namespace __format _Seq get() && { - _Seq_sink::_M_overflow(); + if (this->_M_used().size() != 0) + _Seq_sink::_M_overflow(); return std::move(_M_seq); } }; @@ -2534,7 +2535,8 @@ namespace __format format_to_n_result<_OutIter> _M_finish() && { - _Iter_sink::_M_overflow(); + if (this->_M_used().size() != 0) + _Iter_sink::_M_overflow(); iter_difference_t<_OutIter> __count(_M_count); return { std::move(_M_out), __count }; } @@ -2561,8 +2563,11 @@ namespace __format protected: void - _M_overflow() + _M_overflow() override { + if (this->_M_unused().size() != 0) + return; // No need to switch to internal buffer yet. + auto __s = this->_M_used(); _M_count += __s.size(); @@ -2626,15 +2631,18 @@ namespace __format format_to_n_result<_OutIter> _M_finish() && { - _Iter_sink::_M_overflow(); - iter_difference_t<_OutIter> __count(_M_count); auto __s = this->_M_used(); - auto __last = _M_first; - if (__s.data() == _M_buf) // Wrote at least _M_max characters. - __last += _M_max; - else - __last += iter_difference_t<_OutIter>(__s.size()); - return { __last, __count }; + if (__s.data() == _M_buf) + { + // Switched to internal buffer, so must have written _M_max. + iter_difference_t<_OutIter> __count(_M_count + __s.size()); + return { _M_first + _M_max, __count }; + } + else // Not using internal buffer yet + { + iter_difference_t<_OutIter> __count(__s.size()); + return { _M_first + __count, __count }; + } } }; @@ -3883,11 +3891,8 @@ namespace __format [[__gnu__::__always_inline__]] size_t - count() - { - _Counting_sink::_M_overflow(); - return this->_M_count; - } + count() const + { return this->_M_count + this->_M_used().size(); } }; #else template<typename _CharT> diff --git a/libstdc++-v3/testsuite/std/format/functions/format_to_n.cc b/libstdc++-v3/testsuite/std/format/functions/format_to_n.cc index 846bda30fdf3ccf96403c4ae0f5c448360ec115f..f7df3ed36dc27f4bb64f53c567f41f15840614c4 100644 --- a/libstdc++-v3/testsuite/std/format/functions/format_to_n.cc +++ b/libstdc++-v3/testsuite/std/format/functions/format_to_n.cc @@ -88,9 +88,26 @@ test_move_only() VERIFY( wlen == 11 ); } +void +test_pr110990() +{ + // PR libstdc++/110990 - format_to_n returns wrong value + + char buf[2]; + auto [ptr, len] = std::format_to_n(buf, 2, "x"); + VERIFY( len == 1 ); + VERIFY( ptr == buf + len ); + + wchar_t wbuf[3]; + auto [wptr, wlen] = std::format_to_n(wbuf, 3, L"yz"); + VERIFY( wlen == 2 ); + VERIFY( wptr == wbuf + wlen ); +} + int main() { test(); test_wchar(); test_move_only(); + test_pr110990(); }