diff mbox series

libstdc++: Add pretty printer for std::span

Message ID 20220404105257.199452-1-fent@in.tum.de
State New
Headers show
Series libstdc++: Add pretty printer for std::span | expand

Commit Message

Philipp Fent April 4, 2022, 10:52 a.m. UTC
This improves the debug output for C++20 spans.
Before:
{static extent = 18446744073709551615, _M_ptr = 0x7fffffffb9a8,
_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(+)

Comments

Jonathan Wakely April 4, 2022, 11:39 a.m. UTC | #1
On Mon, 4 Apr 2022 at 11:54, Philipp Fent via Libstdc++
<libstdc++@gcc.gnu.org> wrote:
>
> This improves the debug output for C++20 spans.
> Before:
> {static extent = 18446744073709551615, _M_ptr = 0x7fffffffb9a8,
> _M_extent = {_M_extent_value = 2}}
> Now with StdSpanPrinter:
> std::span of length 2 = {1, 2}

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


> ---
>  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<std::size_t>(-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
>  // <http://www.gnu.org/licenses/>.
>
> +#include <array>
>  #include <compare>
>  #include <iostream>
> +#include <span>
>
>  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
>
Jonathan Wakely April 14, 2022, 3:49 p.m. UTC | #2
On Mon, 4 Apr 2022 at 11:54, Philipp Fent via Libstdc++
<libstdc++@gcc.gnu.org> wrote:
>
> This improves the debug output for C++20 spans.
> Before:
> {static extent = 18446744073709551615, _M_ptr = 0x7fffffffb9a8,
> _M_extent = {_M_extent_value = 2}}
> Now with StdSpanPrinter:
> std::span of length 2 = {1, 2}
Philipp Fent April 19, 2022, 9:34 a.m. UTC | #3
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.
Jonathan Wakely April 19, 2022, 10:28 a.m. UTC | #4
On Tue, 19 Apr 2022 at 10:34, Philipp Fent wrote:
>
> 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.

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

There's no need for you to provide the backported patches, I will take
care of that.
Philipp Fent April 19, 2022, 11:32 a.m. UTC | #5
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
Philipp
Jonathan Wakely April 19, 2022, 11:36 a.m. UTC | #6
On Tue, 19 Apr 2022 at 12:33, Philipp Fent via Libstdc++
<libstdc++@gcc.gnu.org> wrote:
>
> 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.

Huh, I see no content in my sent copy either. Weird. I distinctly
remember pasting the https://gcc.gnu.org/dco.html link into the email,
but gmail must have had other ideas. Sorry about that!

Thanks for the sign-off, I'll get this committed today.

The GCC 11 backport will have to wait a few days because the branch is
currently frozen for the 11.3 release.
diff mbox series

Patch

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<std::size_t>(-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
 // <http://www.gnu.org/licenses/>.
 
+#include <array>
 #include <compare>
 #include <iostream>
+#include <span>
 
 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
 }