[gcc r16-8720] libstdc++: Add comments to non-obvious parts of std::print internals

Jonathan Wakely redi@gcc.gnu.org
Fri Apr 17 12:45:46 GMT 2026


https://gcc.gnu.org/g:209550a04e143edf2bea34cce6d79d92424db96c

commit r16-8720-g209550a04e143edf2bea34cce6d79d92424db96c
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Mar 13 21:07:29 2026 +0000

    libstdc++: Add comments to non-obvious parts of std::print internals
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/print.h (_File_sink): Add comments.

Diff:
---
 libstdc++-v3/include/bits/print.h | 36 +++++++++++++++++++++++-------------
 1 file changed, 23 insertions(+), 13 deletions(-)

diff --git a/libstdc++-v3/include/bits/print.h b/libstdc++-v3/include/bits/print.h
index 67a5a1729135..ab3ff9996126 100644
--- a/libstdc++-v3/include/bits/print.h
+++ b/libstdc++-v3/include/bits/print.h
@@ -58,7 +58,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 namespace __format
 {
-#if _GLIBCXX_USE_STDIO_LOCKING && _GLIBCXX_USE_GLIBC_STDIO_EXT
+#if _GLIBCXX_USE_STDIO_LOCKING && _GLIBCXX_USE_GLBC_STDIO_EXT
   // These are defined in <stdio_ext.h> but we don't want to include that.
   extern "C" int __fwritable(FILE*) noexcept;
   extern "C" int __flbf(FILE*) noexcept;
@@ -111,6 +111,8 @@ namespace __format
       }
 
       // Update the current position in the output buffer.
+      // __n is the number of characters written to the _M_write_buf() span,
+      // so will not exceed the size of the output buffer.
       void
       _M_bump(size_t __n) noexcept
       { _M_file->_IO_write_ptr += __n; }
@@ -160,12 +162,15 @@ namespace __format
 	this->_M_reset(_M_file._M_write_buf());
     }
 
+    // This calls I/O functions which are cancellation points, so they
+    // could exit with a __forced_unwind exception. The noexcept(false)
+    // allows that to propagate instead of terminating the process.
     ~_File_sink() noexcept(false)
     {
       auto __s = this->_M_used();
       if (__s.data() == this->_M_buf) // Unbuffered stream
 	{
-	  _File_sink::_M_overflow();
+	  _File_sink::_M_overflow(); // Transfer _M_buf to stream.
 	  if (_M_add_newline)
 	    ::putc_unlocked('\n', _M_file._M_file);
 	}
@@ -173,7 +178,7 @@ namespace __format
 	{
 	  _M_file._M_bump(__s.size());
 	  if (_M_add_newline)
-	    ::putc_unlocked('\n', _M_file._M_file);
+	    ::putc_unlocked('\n', _M_file._M_file); // '\n' triggers a flush
 	  else if (_M_file._M_line_buffered() && __s.size()
 		     && (__s.back() == '\n'
 			   || __builtin_memchr(__s.data(), '\n', __s.size())))
@@ -188,7 +193,13 @@ namespace __format
   // The file is locked on construction and written to using fwrite_unlocked.
   class _File_sink final : _Buf_sink<char>
   {
-    FILE* _M_file;
+    struct _File // RAII type to lock/unlock the file.
+    {
+      explicit _File(FILE* __f) : _M_file(__f) { ::flockfile(_M_file); }
+      ~_File() { ::funlockfile(_M_file); }
+      FILE* _M_file;
+    } _M_file;
+
     bool _M_add_newline;
 
     // Transfer buffer contents to the FILE, so buffer can be refilled.
@@ -197,13 +208,13 @@ namespace __format
     {
       auto __s = this->_M_used();
 #if _GLIBCXX_HAVE_FWRITE_UNLOCKED
-      auto __n = ::fwrite_unlocked(__s.data(), 1, __s.size(), _M_file);
+      auto __n = ::fwrite_unlocked(__s.data(), 1, __s.size(), _M_file._M_file);
       if (__n != __s.size())
 	__throw_system_error(errno);
 #else
       for (char __c : __s)
-	::putc_unlocked(__c, _M_file);
-      if (::ferror(_M_file))
+	::putc_unlocked(__c, _M_file._M_file);
+      if (::ferror(_M_file._M_file))
 	__throw_system_error(errno);
 #endif
       this->_M_reset(this->_M_buf);
@@ -212,14 +223,13 @@ namespace __format
   public:
     _File_sink(FILE* __f, bool __add_newline) noexcept
     : _Buf_sink<char>(), _M_file(__f), _M_add_newline(__add_newline)
-    { ::flockfile(__f); }
+    { }
 
-    ~_File_sink() noexcept(false)
+    ~_File_sink() noexcept(false) // See above for noexcept(false) rationale.
     {
       _File_sink::_M_overflow();
       if (_M_add_newline)
-	::putc_unlocked('\n', _M_file);
-      ::funlockfile(_M_file);
+	::putc_unlocked('\n', _M_file._M_file);
     }
 
     using _Sink<char>::out;
@@ -239,14 +249,14 @@ namespace __format
     : _M_file(__f), _M_add_newline(__add_newline)
     { }
 
-    ~_File_sink() noexcept(false)
+    ~_File_sink() noexcept(false) // See above for noexcept(false) rationale.
     {
       string __s = std::move(_M_sink).get();
       if (_M_add_newline)
 	__s += '\n';
       auto __n = std::fwrite(__s.data(), 1, __s.size(), _M_file);
       if (__n < __s.size())
-	__throw_system_error(EIO);
+	__throw_system_error(EIO); // Non-POSIX fwrite doesn't set errno.
     }
 
     auto out() { return _M_sink.out(); }


More information about the Libstdc++-cvs mailing list