Re: [PATCH 2/2] libstdc++: Add pretty printer for std::stringstream

2022-09-12 Thread Philipp Fent via Gcc-patches

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.


[PATCH v2] libstdc++: Add pretty printer for std::stringstreams

2022-09-06 Thread Philipp Fent via Gcc-patches
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 
---
 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
+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 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -110,6 +111,20 @@ main()
   __gnu_cxx::slist::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&>(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++-v

[PATCH 2/2] libstdc++: Add pretty printer for std::stringstream

2022-09-04 Thread Philipp Fent via Gcc-patches
Signed-off-by: Philipp Fent 
---
 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']
+# 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)
+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']
+
+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)
 
 # 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..7efec6d0f8b 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/debug.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/debug.cc
@@ -29,6 +29,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -110,6 +111,10 @@ main()
   __gnu_cxx::slist::iterator slliter = sll.begin();
 // { dg-final { note-test slliter {47} } }
 
+  std::stringstream sstream;
+  sstream << "abc";
+// { dg-final { note-test sstream "\"abc\"" } }
+
   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..584989ce09f 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple.cc
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -169,6 +170,10 @@ main()
   __gnu_cxx::slist::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::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..6edd7e929fe 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/simple11.cc
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -162,6 +163,10 @@ main()
   __gnu_cxx::slist::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::cout << "\n";
   return 0;// Mark SPOT
 }
-- 
2.37.3



[PATCH 1/2] libstdc++: Fix pretty printer tests of tuple indexes

2022-09-04 Thread Philipp Fent via Gcc-patches
Signed-off-by: Philipp Fent 
---
 libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc | 2 +-
 libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc 
b/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc
index cc91803e247..af335d0d3c7 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/48362.cc
@@ -29,7 +29,7 @@ main()
 // { dg-final { note-test t1 {empty std::tuple} } }
 
   std::tuple> t2{ "Johnny", 5, {} };
-// { dg-final { regexp-test t2 {std::tuple containing = {\[1\] = "Johnny", 
\[2\] = 5, \[3\] = empty std::tuple}} } }
+// { dg-final { regexp-test t2 {std::tuple containing = {\[0\] = "Johnny", 
\[1\] = 5, \[2\] = empty std::tuple}} } }
 
   std::cout << "\n";
   return 0; // Mark SPOT
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc 
b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
index f97640a0189..bc5978ee69d 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
@@ -166,9 +166,9 @@ main()
 // { dg-final { note-test runiq_ptr {std::unique_ptr = {get() = 0x0}} } }
 
   ExTuple tpl(6,7);
-// { dg-final { note-test tpl {std::tuple containing = {[1] = 6, [2] = 7}} } }
+// { dg-final { note-test tpl {std::tuple containing = {[0] = 6, [1] = 7}} } }
   ExTuple &rtpl = tpl;
-// { dg-final { note-test rtpl {std::tuple containing = {[1] = 6, [2] = 7}} } }
+// { dg-final { note-test rtpl {std::tuple containing = {[0] = 6, [1] = 7}} } }
 
   std::error_code e0;
   // { dg-final { note-test e0 {std::error_code = { }} } }
-- 
2.37.3



[PATCH] libstdc++: Add pretty printer for std::initializer_list

2022-04-24 Thread Philipp Fent via Gcc-patches
Re-using the std::span printer, this now shows the contents of the
initializer list instead of the pointer and length members.

Signed-off-by: Philipp Fent 
---
 libstdc++-v3/python/libstdcxx/v6/printers.py  | 23 +--
 .../libstdc++-prettyprinters/cxx11.cc |  6 +
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py 
b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 6d8b765f2..48798b6c1 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -1657,7 +1657,7 @@ class StdRegexStatePrinter:
 class StdSpanPrinter:
 "Print a std::span"
 
-class _iterator(Iterator):
+class iterator(Iterator):
 def __init__(self, begin, size):
 self.count = 0
 self.begin = begin
@@ -1686,7 +1686,24 @@ class StdSpanPrinter:
 return '%s of length %d' % (self.typename, self.size)
 
 def children(self):
-return self._iterator(self.val['_M_ptr'], self.size)
+return self.iterator(self.val['_M_ptr'], self.size)
+
+def display_hint(self):
+return 'array'
+
+class StdInitializerListPrinter:
+"Print a std::initializer_list"
+
+def __init__(self, typename, val):
+self.typename = typename
+self.val = val
+self.size = val['_M_len']
+
+def to_string(self):
+return '%s of length %d' % (self.typename, self.size)
+
+def children(self):
+return StdSpanPrinter.iterator(self.val['_M_array'], self.size)
 
 def display_hint(self):
 return 'array'
@@ -2156,6 +2173,8 @@ def build_libstdcxx_dictionary ():
 libstdcxx_printer.add_version('std::tr1::', 'unordered_multiset',
   Tr1UnorderedSetPrinter)
 
+libstdcxx_printer.add_version('std::', 'initializer_list', 
StdInitializerListPrinter)
+
 # std::regex components
 libstdcxx_printer.add_version('std::__detail::', '_State',
   StdRegexStatePrinter)
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc 
b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
index 4262ca88b..621d13bd0 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx11.cc
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "../util/testsuite_allocator.h" // NullablePointer
 
 typedef std::tuple ExTuple;
@@ -191,6 +192,11 @@ main()
   std::error_code ecfut0 = std::make_error_code(std::future_errc{});
   // { dg-final { note-test ecfut0 {std::error_code = {"future": 0}} } }
 
+  std::initializer_list emptyIl = {};
+  // { dg-final { note-test emptyIl {std::initializer_list of length 0} } }
+  std::initializer_list il = {3, 4};
+  // { dg-final { note-test il {std::initializer_list of length 2 = {3, 4}} } }
+
   placeholder(""); // Mark SPOT
   use(efl);
   use(fl);
-- 
2.36.0



Re: [PATCH] libstdc++: Add pretty printer for std::span

2022-04-19 Thread Philipp Fent via Gcc-patches

On 19.04.22 12:28, Jonathan Wakely wrote:

Thanks, but we still need the DCO sign-off as I mailed about last week.


Thanks for the clarification, your last mail didn't appear to have 
content, so I might have missed that part. I've now added my DCO sign-off.


Best
PhilippFrom 64b6779c2694f57981e15b9c1dfa59b192e99a16 Mon Sep 17 00:00:00 2001
From: Philipp Fent 
Date: Mon, 4 Apr 2022 12:52:57 +0200
Subject: [PATCH] libstdc++: Add pretty printer for std::span

This improves the debug output for C++20 spans.
Before:
{static extent = 18446744073709551615, _M_ptr = 0x7fffb9a8,
_M_extent = {_M_extent_value = 2}}
Now with StdSpanPrinter:
std::span of length 2 = {1, 2}

Signed-off-by: Philipp Fent 
---
 libstdc++-v3/python/libstdcxx/v6/printers.py  | 38 +++
 .../libstdc++-prettyprinters/cxx20.cc | 11 ++
 2 files changed, 49 insertions(+)

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index f7a7f9961a7..6d8b765f2da 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -1654,6 +1654,43 @@ class StdRegexStatePrinter:
 s = "{}, {}={}".format(s, v, self.val['_M_' + v])
 return "{%s}" % (s)
 
+class StdSpanPrinter:
+"Print a std::span"
+
+class _iterator(Iterator):
+def __init__(self, begin, size):
+self.count = 0
+self.begin = begin
+self.size = size
+
+def __iter__ (self):
+return self
+
+def __next__ (self):
+if self.count == self.size:
+raise StopIteration
+
+count = self.count
+self.count = self.count + 1
+return '[%d]' % count, (self.begin + count).dereference()
+
+def __init__(self, typename, val):
+self.typename = typename
+self.val = val
+if val.type.template_argument(1) == gdb.parse_and_eval('static_cast(-1)'):
+self.size = val['_M_extent']['_M_extent_value']
+else:
+self.size = val.type.template_argument(1)
+
+def to_string(self):
+return '%s of length %d' % (self.typename, self.size)
+
+def children(self):
+return self._iterator(self.val['_M_ptr'], self.size)
+
+def display_hint(self):
+return 'array'
+
 # A "regular expression" printer which conforms to the
 # "SubPrettyPrinter" protocol from gdb.printing.
 class RxPrinter(object):
@@ -2170,6 +2207,7 @@ def build_libstdcxx_dictionary ():
 libstdcxx_printer.add_version('std::', 'partial_ordering', StdCmpCatPrinter)
 libstdcxx_printer.add_version('std::', 'weak_ordering', StdCmpCatPrinter)
 libstdcxx_printer.add_version('std::', 'strong_ordering', StdCmpCatPrinter)
+libstdcxx_printer.add_version('std::', 'span', StdSpanPrinter)
 
 # Extensions.
 libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter)
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc
index b0de25c27ec..76023df93fa 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc
@@ -18,8 +18,10 @@
 // with this library; see the file COPYING3.  If not see
 // .
 
+#include 
 #include 
 #include 
+#include 
 
 struct X
 {
@@ -54,6 +56,15 @@ main()
   auto c10 = 0.0 <=> __builtin_nan("");
 // { dg-final { note-test c10 "std::partial_ordering::unordered" } }
 
+  auto il = {1, 2};
+  auto s1 = std::span(il);
+  static_assert(s1.extent == std::size_t(-1));
+// { dg-final { note-test s1 {std::span of length 2 = {1, 2}} } }
+  auto a = std::array{3, 4};
+  auto s2 = std::span(a);
+  static_assert(s2.extent == std::size_t(2));
+// { dg-final { note-test s2 {std::span of length 2 = {3, 4}} } }
+
   std::cout << "\n";
   return 0;			// Mark SPOT
 }
-- 
2.35.3



Re: [PATCH] libstdc++: Add pretty printer for std::span

2022-04-19 Thread Philipp Fent via Gcc-patches

On 04.04.22 13:39, Jonathan Wakely wrote:

Nice, thanks. I'll get this committed in time for GCC 12 (and backport
it to release branches too).


I've attached a rebased patch for trunk and tested it on x86_64-linux.
I also backported it for the release branches, gcc-11 tests also pass, 
on gcc-10 the prettyprinters testsuite reports "unsupported", and gcc-9 
didn't have std::span yet.From 0f4ae81980ea1181aca4deca0508628f9f30e72b Mon Sep 17 00:00:00 2001
From: Philipp Fent 
Date: Mon, 4 Apr 2022 12:52:57 +0200
Subject: [PATCH] libstdc++: Add pretty printer for std::span

This improves the debug output for C++20 spans.
Before:
{static extent = 18446744073709551615, _M_ptr = 0x7fffb9a8,
_M_extent = {_M_extent_value = 2}}
Now with StdSpanPrinter:
std::span of length 2 = {1, 2}
---
 libstdc++-v3/python/libstdcxx/v6/printers.py  | 38 +++
 .../libstdc++-prettyprinters/cxx20.cc | 11 ++
 2 files changed, 49 insertions(+)

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 74c629a710c..790d83fecff 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -1535,6 +1535,43 @@ class StdErrorCodePrinter:
 pass
 return '%s = {"%s": %s}' % (self.typename, category, strval)
 
+class StdSpanPrinter:
+"Print a std::span"
+
+class _iterator(Iterator):
+def __init__(self, begin, size):
+self.count = 0
+self.begin = begin
+self.size = size
+
+def __iter__ (self):
+return self
+
+def __next__ (self):
+if self.count == self.size:
+raise StopIteration
+
+count = self.count
+self.count = self.count + 1
+return '[%d]' % count, (self.begin + count).dereference()
+
+def __init__(self, typename, val):
+self.typename = typename
+self.val = val
+if val.type.template_argument(1) == gdb.parse_and_eval('static_cast(-1)'):
+self.size = val['_M_extent']['_M_extent_value']
+else:
+self.size = val.type.template_argument(1)
+
+def to_string(self):
+return '%s of length %d' % (self.typename, self.size)
+
+def children(self):
+return self._iterator(self.val['_M_ptr'], self.size)
+
+def display_hint(self):
+return 'array'
+
 # A "regular expression" printer which conforms to the
 # "SubPrettyPrinter" protocol from gdb.printing.
 class RxPrinter(object):
@@ -2043,6 +2080,7 @@ def build_libstdcxx_dictionary ():
 libstdcxx_printer.add_version('std::', 'partial_ordering', StdCmpCatPrinter)
 libstdcxx_printer.add_version('std::', 'weak_ordering', StdCmpCatPrinter)
 libstdcxx_printer.add_version('std::', 'strong_ordering', StdCmpCatPrinter)
+libstdcxx_printer.add_version('std::', 'span', StdSpanPrinter)
 
 # Extensions.
 libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter)
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc
index 9a868c4baf7..0887f1868f2 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc
@@ -18,8 +18,10 @@
 // with this library; see the file COPYING3.  If not see
 // .
 
+#include 
 #include 
 #include 
+#include 
 
 struct X
 {
@@ -54,6 +56,15 @@ main()
   auto c10 = 0.0 <=> __builtin_nan("");
 // { dg-final { note-test c10 "std::partial_ordering::unordered" } }
 
+  auto il = {1, 2};
+  auto s1 = std::span(il);
+  static_assert(s1.extent == std::size_t(-1));
+// { dg-final { note-test s1 {std::span of length 2 = {1, 2}} } }
+  auto a = std::array{3, 4};
+  auto s2 = std::span(a);
+  static_assert(s2.extent == std::size_t(2));
+// { dg-final { note-test s2 {std::span of length 2 = {3, 4}} } }
+
   std::cout << "\n";
   return 0;			// Mark SPOT
 }
-- 
2.35.3

From c4331b7532dc2825429e82e46fda1a04dd943bd4 Mon Sep 17 00:00:00 2001
From: Philipp Fent 
Date: Mon, 4 Apr 2022 12:52:57 +0200
Subject: [PATCH] libstdc++: Add pretty printer for std::span

This improves the debug output for C++20 spans.
Before:
{static extent = 18446744073709551615, _M_ptr = 0x7fffb9a8,
_M_extent = {_M_extent_value = 2}}
Now with StdSpanPrinter:
std::span of length 2 = {1, 2}
---
 libstdc++-v3/python/libstdcxx/v6/printers.py  | 38 +++
 .../libstdc++-prettyprinters/cxx20.cc | 11 ++
 2 files changed, 49 insertions(+)

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index f7a7f9961a7..6d8b765f2da 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -1654,6 +1654,43 @@ class StdRegexStatePrinter:
 s = "{}, {}={}".format(s, v, self.val['_M_' + v])
 return "{%s}" % (s)
 
+clas

[PATCH] libstdc++: Add pretty printer for std::span

2022-04-04 Thread Philipp Fent via Gcc-patches
This improves the debug output for C++20 spans.
Before:
{static extent = 18446744073709551615, _M_ptr = 0x7fffb9a8,
_M_extent = {_M_extent_value = 2}}
Now with StdSpanPrinter:
std::span of length 2 = {1, 2}
---
 libstdc++-v3/python/libstdcxx/v6/printers.py  | 38 +++
 .../libstdc++-prettyprinters/cxx20.cc | 11 ++
 2 files changed, 49 insertions(+)

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py 
b/libstdc++-v3/python/libstdcxx/v6/printers.py
index f7a7f9961..6d8b765f2 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -1654,6 +1654,43 @@ class StdRegexStatePrinter:
 s = "{}, {}={}".format(s, v, self.val['_M_' + v])
 return "{%s}" % (s)
 
+class StdSpanPrinter:
+"Print a std::span"
+
+class _iterator(Iterator):
+def __init__(self, begin, size):
+self.count = 0
+self.begin = begin
+self.size = size
+
+def __iter__ (self):
+return self
+
+def __next__ (self):
+if self.count == self.size:
+raise StopIteration
+
+count = self.count
+self.count = self.count + 1
+return '[%d]' % count, (self.begin + count).dereference()
+
+def __init__(self, typename, val):
+self.typename = typename
+self.val = val
+if val.type.template_argument(1) == 
gdb.parse_and_eval('static_cast(-1)'):
+self.size = val['_M_extent']['_M_extent_value']
+else:
+self.size = val.type.template_argument(1)
+
+def to_string(self):
+return '%s of length %d' % (self.typename, self.size)
+
+def children(self):
+return self._iterator(self.val['_M_ptr'], self.size)
+
+def display_hint(self):
+return 'array'
+
 # A "regular expression" printer which conforms to the
 # "SubPrettyPrinter" protocol from gdb.printing.
 class RxPrinter(object):
@@ -2170,6 +2207,7 @@ def build_libstdcxx_dictionary ():
 libstdcxx_printer.add_version('std::', 'partial_ordering', 
StdCmpCatPrinter)
 libstdcxx_printer.add_version('std::', 'weak_ordering', StdCmpCatPrinter)
 libstdcxx_printer.add_version('std::', 'strong_ordering', StdCmpCatPrinter)
+libstdcxx_printer.add_version('std::', 'span', StdSpanPrinter)
 
 # Extensions.
 libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter)
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc 
b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc
index b0de25c27..76023df93 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx20.cc
@@ -18,8 +18,10 @@
 // with this library; see the file COPYING3.  If not see
 // .
 
+#include 
 #include 
 #include 
+#include 
 
 struct X
 {
@@ -54,6 +56,15 @@ main()
   auto c10 = 0.0 <=> __builtin_nan("");
 // { dg-final { note-test c10 "std::partial_ordering::unordered" } }
 
+  auto il = {1, 2};
+  auto s1 = std::span(il);
+  static_assert(s1.extent == std::size_t(-1));
+// { dg-final { note-test s1 {std::span of length 2 = {1, 2}} } }
+  auto a = std::array{3, 4};
+  auto s2 = std::span(a);
+  static_assert(s2.extent == std::size_t(2));
+// { dg-final { note-test s2 {std::span of length 2 = {3, 4}} } }
+
   std::cout << "\n";
   return 0;// Mark SPOT
 }
-- 
2.35.1