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.