On Tue, 6 Sept 2022 at 22:25, Philipp Fent <f...@in.tum.de> wrote:
>
> To display (o-,i-)stringstreams in the common case, we just print the
> underlying stringbuf, without the many ios_base members. In the
> unconventional case that the underlying streambuf was redirected, we
> report the redirected target.
>
> Signed-off-by: Philipp Fent <f...@in.tum.de>
> ---
>  libstdc++-v3/python/libstdcxx/v6/printers.py  | 56 +++++++++++++++++++
>  .../libstdc++-prettyprinters/debug.cc         | 15 +++++
>  .../libstdc++-prettyprinters/simple.cc        | 15 +++++
>  .../libstdc++-prettyprinters/simple11.cc      | 15 +++++
>  4 files changed, 101 insertions(+)
>
> diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py 
> b/libstdc++-v3/python/libstdcxx/v6/printers.py
> index d70c8d5d616..bd4289c1c62 100644
> --- a/libstdc++-v3/python/libstdcxx/v6/printers.py
> +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
> @@ -969,6 +969,57 @@ class StdStringPrinter:
>      def display_hint (self):
>          return 'string'
>
> +def access_streambuf_ptrs(streambuf):
> +    "Access the streambuf put area pointers"
> +    pbase = streambuf['_M_out_beg']
> +    pptr = streambuf['_M_out_cur']
> +    egptr = streambuf['_M_in_end']
> +    return pbase, pptr, egptr
> +
> +class StdStringBufPrinter:
> +    "Print a std::basic_stringbuf"
> +
> +    def __init__(self, _, val):
> +        self.val = val
> +
> +    def to_string(self):
> +        (pbase, pptr, egptr) = access_streambuf_ptrs(self.val)
> +        # 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 = egptr - pbase)
> +        return self.val['_M_string']
> +
> +    def display_hint(self):
> +        return 'string'
> +
> +class StdStringStreamPrinter:
> +    "Print a std::basic_stringstream"
> +
> +    def __init__(self, typename, val):
> +        self.val = val
> +        self.typename = typename
> +
> +        # Check if the stream was redirected:
> +        # This is essentially: val['_M_streambuf'] == 
> val['_M_stringbuf'].address
> +        # However, GDB can't resolve the virtual inheritance, so we do that 
> manually

Oh yuck, sorry you had to figure that out.

The patch looks good, thanks. I'll get it pushed to trunk.


> +        basetype = [f.type for f in val.type.fields() if f.is_base_class][0]
> +        gdb.set_convenience_variable('__stream', val.cast(basetype).address)
> +        self.streambuf = gdb.parse_and_eval('$__stream->rdbuf()')
> +        self.was_redirected = self.streambuf != val['_M_stringbuf'].address
> +
> +    def to_string(self):
> +        if self.was_redirected:
> +            return "%s redirected to %s" % (self.typename, 
> self.streambuf.dereference())
> +        return self.val['_M_stringbuf']
> +
> +    def display_hint(self):
> +        if self.was_redirected:
> +            return None
> +        return 'string'
> +
>  class Tr1HashtableIterator(Iterator):
>      def __init__ (self, hashtable):
>          self.buckets = hashtable['_M_buckets']
> @@ -2232,6 +2283,11 @@ 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)
> +    for sstream in ('istringstream', 'ostringstream', 'stringstream'):
> +        libstdcxx_printer.add_version('std::', 'basic_' + sstream, 
> StdStringStreamPrinter)
> +        libstdcxx_printer.add_version('std::__cxx11::', 'basic_' + sstream, 
> StdStringStreamPrinter)
>
>      # std::regex components
>      libstdcxx_printer.add_version('std::__detail::', '_State',
> diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/debug.cc 
> b/libstdc++-v3/testsuite/libstdc++-prettyprinters/debug.cc
> index 98bbc182551..3c6195591c5 100644
> --- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/debug.cc
> +++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/debug.cc
> @@ -29,6 +29,7 @@
>  #include <list>
>  #include <map>
>  #include <set>
> +#include <sstream>
>  #include <vector>
>  #include <ext/slist>
>
> @@ -110,6 +111,20 @@ main()
>    __gnu_cxx::slist<int>::iterator slliter = sll.begin();
>  // { dg-final { note-test slliter {47} } }
>
> +  std::stringstream sstream;
> +  sstream << "abc";
> +// { dg-final { note-test sstream "\"abc\"" } }
> +  std::stringstream ssin("input", std::ios::in);
> +// { dg-final { note-test ssin "\"input\"" } }
> +  std::istringstream ssin2("input");
> +// { dg-final { note-test ssin2 "\"input\"" } }
> +  std::ostringstream ssout;
> +  ssout << "out";
> +// { dg-final { note-test ssout "\"out\"" } }
> +  std::stringstream redirected("xxx");
> +  
> static_cast<std::basic_ios<std::stringstream::char_type>&>(redirected).rdbuf(sstream.rdbuf());
> +// { dg-final { regexp-test redirected {std::.*stringstream redirected to 
> .*} } }
> +
>    std::cout << "\n";
>    return 0;                    // Mark SPOT
>  }
> diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc 
> b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
> index 1f85775bff0..1609ae2c8db 100644
> --- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
> +++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
> @@ -30,6 +30,7 @@
>  #include <list>
>  #include <map>
>  #include <set>
> +#include <sstream>
>  #include <vector>
>  #include <ext/slist>
>
> @@ -169,6 +170,20 @@ main()
>    __gnu_cxx::slist<int>::iterator slliter0;
>  // { dg-final { note-test slliter0 {non-dereferenceable iterator for 
> __gnu_cxx::slist} } }
>
> +  std::stringstream sstream;
> +  sstream << "abc";
> +// { dg-final { note-test sstream "\"abc\"" } }
> +  std::stringstream ssin("input", std::ios::in);
> +// { dg-final { note-test ssin "\"input\"" } }
> +  std::istringstream ssin2("input");
> +// { dg-final { note-test ssin2 "\"input\"" } }
> +  std::ostringstream ssout;
> +  ssout << "out";
> +// { dg-final { note-test ssout "\"out\"" } }
> +  std::stringstream redirected("xxx");
> +  
> static_cast<std::basic_ios<std::stringstream::char_type>&>(redirected).rdbuf(sstream.rdbuf());
> +// { dg-final { regexp-test redirected {std::.*stringstream redirected to 
> .*} } }
> +
>    std::cout << "\n";
>    return 0;                    // Mark SPOT
>  }
> diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc 
> b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
> index 6f21675cf41..a4b82e30f9c 100644
> --- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
> +++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
> @@ -30,6 +30,7 @@
>  #include <list>
>  #include <map>
>  #include <set>
> +#include <sstream>
>  #include <vector>
>  #include <ext/slist>
>
> @@ -162,6 +163,20 @@ main()
>    __gnu_cxx::slist<int>::iterator slliter0;
>  // { dg-final { note-test slliter0 {non-dereferenceable iterator for 
> __gnu_cxx::slist} } }
>
> +  std::stringstream sstream;
> +  sstream << "abc";
> +// { dg-final { note-test sstream "\"abc\"" } }
> +  std::stringstream ssin("input", std::ios::in);
> +// { dg-final { note-test ssin "\"input\"" } }
> +  std::istringstream ssin2("input");
> +// { dg-final { note-test ssin2 "\"input\"" } }
> +  std::ostringstream ssout;
> +  ssout << "out";
> +// { dg-final { note-test ssout "\"out\"" } }
> +  std::stringstream redirected("xxx");
> +  
> static_cast<std::basic_ios<std::stringstream::char_type>&>(redirected).rdbuf(sstream.rdbuf());
> +// { dg-final { regexp-test redirected {std::.*stringstream redirected to 
> .*} } }
> +
>    std::cout << "\n";
>    return 0;                    // Mark SPOT
>  }
> --
> 2.37.3
>

Reply via email to