https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118099
--- Comment #6 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Jonathan Wakely <[email protected]>: https://gcc.gnu.org/g:f46b50adcf752de0e1e0e24e17f42a5075770f48 commit r17-5972-gf46b50adcf752de0e1e0e24e17f42a5075770f48 Author: Jonathan Wakely <[email protected]> Date: Thu Oct 22 23:39:56 2026 +0100 libstdc++: Replace bump+rewind in basic_filebuf::overflow [PR118099] The fix for PR 118099 handled failure to write the pending output sequence to the external file (i.e. when _M_convert_to_external returns false or throws an exception) by rewinding the last character written to the output sequence. This commit changes basic_filebuf::overflow to not advance the put area's next pointer at all, so no rewinding is needed. Instead we can just increment the size passed to _M_convert_to_external to account for the extra character in the put area. This relies on the previous commit which changed _M_convert_to_external to no longer use pptr() when retrying after a partial codecvt conversion. If _M_convert_to_external was still looking at pptr() directly and expecting it to have been bumped then we could not change overflow to no longer bump it. Because this change depends on that fix in _M_convert_to_external there is a potential ABI issue that needs care. If the new bump-less version of basic_filebuf::overflow gets inlined into a translation unit but the linker resolves its call to _M_convert_to_external to an old definition that still calls pptr(), we would not transfer the overflow character to the external file when retrying after a partial conversion. Although this scenario seems unlikely because std::filebuf and std::wfilebuf are both explicitly instantiated in libstdc++.so (and the explicit instantiations use the new definition of _M_convert_to_external) it would be safer to ensure the problem cannot occur. This commit adds an _M_convert_to_external(const _CharT*, streamsize) overload which takes a const pointer and moves all the logic from the old (non-const) overload to that new one. This ensures that the new bump-less overflow uses a new symbol with the new behaviour, and will never bind to an old definition that inspects pptr(). The old overload taking a non-const pointer needs to be preserved for ABI compatibility, but can be defined to simply forward its arguments to the new overload. With this change, instantiations of the old version of overflow can safely bind to either the old definition of _M_convert_to_external (which calls pptr()) or the new definition (which forwards to the new overload and so doesn't use pptr()) because both definitions are compatible with the old overflow. Instantiations of the new version of overflow will only ever bind to the new overload because it has a different mangled name. libstdc++-v3/ChangeLog: PR libstdc++/118099 * config/abi/pre/gnu.ver: Tighten old patterns for basic_filebuf and export new symbols. * include/bits/fstream.tcc (basic_filebuf::overflow): Do not bump the next pointer for the overflow character. Pass const pointers to _M_convert_to_external. (_M_convert_to_external(_CharT*, streamsize)): Replace with ... (_M_convert_to_external(const _CharT*, streamsize)): Define new overload. * include/std/fstream (_M_convert_to_external): Declare new overload. Define old overload always_inline and suppress it for _GLIBCXX_INLINE_VERSION. Reviewed-by: Tomasz KamiÅski <[email protected]>
