Thanks for the patch. Comments below.
On Sun, 4 Sept 2022 at 19:48, Philipp Fent via Libstdc++ <libstd...@gcc.gnu.org> wrote: > > Signed-off-by: Philipp Fent <f...@in.tum.de> > --- > libstdc++-v3/python/libstdcxx/v6/printers.py | 37 +++++++++++++++++++ > .../libstdc++-prettyprinters/debug.cc | 5 +++ > .../libstdc++-prettyprinters/simple.cc | 5 +++ > .../libstdc++-prettyprinters/simple11.cc | 5 +++ > 4 files changed, 52 insertions(+) > > diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py > b/libstdc++-v3/python/libstdcxx/v6/printers.py > index d70c8d5d616..5083f693387 100644 > --- a/libstdc++-v3/python/libstdcxx/v6/printers.py > +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py > @@ -969,6 +969,39 @@ class StdStringPrinter: > def display_hint (self): > return 'string' > > +class StdStringBufPrinter: > + "Print a std::basic_stringbuf" > + > + def __init__(self, _, val): > + self.val = val > + > + def to_string(self): > + 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). > + # 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. > + 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. > + > + 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?