Hi Jonathan,

I've sent an updated patch addressing your comments here:
https://gcc.gnu.org/pipermail/libstdc++/2022-September/054587.html

Details below.

On 06.09.22 13:27, Jonathan Wakely wrote:
+        pbase = self.val['_M_out_beg']
+        pptr = self.val['_M_out_cur']
+        egptr = self.val['_M_in_end']

It would be nice to encapsulate this into a generic helper for all
streambufs, as this part isn't specific to basic_stringbuf. We could
then reuse it for printing spanbufs and other types in future. It
could be a function that takes a streambuf and returns a tuple of
(pbase, pptr, egptr).

I factored this into a reusable access_streambuf_ptrs().

+        # Logic from basic_stringbuf::_M_high_mark()
+        if pptr:
+            if not egptr or pptr > egptr:
+                return pbase.string(length = pptr - pbase)
+            else:
+                return pbase.string(length = pptr - egptr)

Shouldn't this be egptr - pbase?

This suggests the tests are inadequate. I think this bug would have
been found by a test something like:

std::stringstream ssin("input", std::ios::in);
// { dg-final { note-test ssin "\"input\"" } }

The (egptr - pbase) case is also needed for printing an istringstream.

Good catch! I fixed that bug and added a test for this in the testsuite.


+        return self.val['_M_string']
+
+    def display_hint(self):
+        return 'string'
+
+class StdStringStreamPrinter:
+    "Print a std::basic_stringstream"
+
+    def __init__(self, _, val):
+        self.val = val
+
+    def to_string(self):
+        return self.val['_M_stringbuf']

This assumes that the stream is still using its stringbuf, which is
probably true 99% of the time, but isn't guaranteed. In the following
situation, the printer would give potentially misleading output:

std::stringstream ss("xxx");
ss.rdbuf(std::cin.rdbuf());

I wonder if we want to have a check that self.val['_M_streambuf'] ==
self.val['_M_stringbuf'].address

Alternatively, don't provide a printer for the stringstream at all,
just for the stringbuf, and then when GDB uses its default display for
the stringstream it will show that member.

I didn't know one could redirect a stringstream, since its rdbuf() method hides the basic_ios rdbuf() methods. But of course, that's still possible via the base class... The Patch v2 checks that case in the StdStringStreamPrinter constructor, and follows that redirect in to_string().


+
+    def display_hint(self):
+        return 'string'
+
  class Tr1HashtableIterator(Iterator):
      def __init__ (self, hashtable):
          self.buckets = hashtable['_M_buckets']
@@ -2232,6 +2265,10 @@ def build_libstdcxx_dictionary ():
      libstdcxx_printer.add_version('std::', 'initializer_list',
                                    StdInitializerListPrinter)
      libstdcxx_printer.add_version('std::', 'atomic', StdAtomicPrinter)
+    libstdcxx_printer.add_version('std::', 'basic_stringbuf', 
StdStringBufPrinter)
+    libstdcxx_printer.add_version('std::__cxx11::', 'basic_stringbuf', 
StdStringBufPrinter)
+    libstdcxx_printer.add_version('std::', 'basic_stringstream', 
StdStringStreamPrinter)
+    libstdcxx_printer.add_version('std::__cxx11::', 'basic_stringstream', 
StdStringStreamPrinter)

Wouldn't we want it for ostringstream and istringstream too?

Indeed. The updated patch registers the pretty printer for all flavors.

Reply via email to