public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch] Add libstdc++ type printers for class templates
@ 2014-07-14 14:34 Jonathan Wakely
  2014-07-14 19:31 ` Jonathan Wakely
  2014-07-14 20:11 ` [patch] Add libstdc++ type printers for class templates Tom Tromey
  0 siblings, 2 replies; 8+ messages in thread
From: Jonathan Wakely @ 2014-07-14 14:34 UTC (permalink / raw)
  To: libstdc++, gcc-patches; +Cc: tromey, pmuldoon

[-- Attachment #1: Type: text/plain, Size: 1329 bytes --]

This defines a new style of Python type printer that recognizes
templates and can be used to omit default template arguments from the
typename GDB prints, e.g. showing std::vector<T, std::allocator<T>> as
simply std::vector<T>.  Additionally, T will get processed by the type
recognizers so if it's a standard typedef or template it will also get
displayed in its abbreviated form.

e.g. with current trunk:

Breakpoint 1, main () at p.cc:45
45        std::vector<std::deque<std::list<int>>> nested;
(gdb) whatis nested
type = std::vector<std::deque<std::list<int, std::allocator<int> >, std::allocator<std::list<int, std::allocator<int> > > >, std::allocator<std::deque<std::list<int, std::allocator<int> >, std::allocator<std::list<int, std::allocator<int> > > > > >

and with this patch:

(gdb) whatis nested
type = std::vector<std::deque<std::list<int>>>

N.B. I am not printing spaces between the closing angle brackets. If
people prefer I can put them in, or only do it for C++11 types, so
that copying and pasting types from GDB will always work (if you're
copying a C++11 type then you must be planning to use it with a C++11
compiler, which will handle >> without spaces).

This passes the python testsuite but I'll wait for comments before
committing, in case my use of the GDB API or Python can be improved by
anyone.

[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 8650 bytes --]

commit 538e6eddc52681d9b3ca8fb5d97f194492ee68da
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Jul 10 20:31:11 2014 +0100

    	* python/libstdcxx/v6/printers.py (TemplateTypePrinter): Add type
    	printer for class templates.
    	(register_type_printers): Use TemplateTypePrinter for containers
    	and other class templates with default template arguments.
    	* testsuite/libstdc++-prettyprinters/whatis.cc: Test new recognizers.

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 1fa08fb..ea34f22 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -922,6 +922,57 @@ class Printer(object):
 
 libstdcxx_printer = None
 
+class TemplateTypePrinter(object):
+    """A type printer for class templates.
+
+    Recognizes type names that match a regular expression.
+    Replaces them with a formatted string which can use replacement field
+    {N} to refer to the \N subgroup of the regex match.
+    Type printers are recusively applied to the subgroups.
+
+    This allows recognizing e.g. "std::vector<(.*), std::allocator<\\1> >"
+    and replacing it with "std::vector<{1}>", omitting the template argument
+    that uses the default type.
+    """
+
+    def __init__(self, name, pattern, subst):
+        self.name = name
+        self.pattern = re.compile(pattern)
+        self.subst = subst
+        self.enabled = True
+
+    class _recognizer(object):
+        def __init__(self, pattern, subst):
+            self.pattern = pattern
+            self.subst = subst
+            self.type_obj = None
+
+        def recognize(self, type_obj):
+            if type_obj.tag is None:
+                return None
+
+            m = self.pattern.match(type_obj.tag)
+            if m:
+                subs = list(m.groups())
+                for i, sub in enumerate(subs):
+                    if ('{%d}' % (i+1)) in self.subst:
+                        # apply recognizers to subgroup
+                        rep = gdb.types.apply_type_recognizers(
+                                gdb.types.get_type_recognizers(),
+                                gdb.lookup_type(sub))
+                        if rep:
+                            subs[i] = rep
+                subs = [None] + subs
+                return self.subst.format(*subs)
+            return None
+
+    def instantiate(self):
+        return self._recognizer(self.pattern, self.subst)
+
+def add_one_template_type_printer(obj, name, match, subst):
+    printer = TemplateTypePrinter(name, '^std::' + match + '$', 'std::' + subst)
+    gdb.types.register_type_printer(obj, printer)
+
 class FilteringTypePrinter(object):
     def __init__(self, match, name):
         self.match = match
@@ -1013,6 +1064,56 @@ def register_type_printers(obj):
     add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
     add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')
 
+    # Do not show defaulted template arguments in class templates
+    add_one_template_type_printer(obj, 'unique_ptr<T>',
+            'unique_ptr<(.*), std::default_delete<\\1 ?> >',
+            'unique_ptr<{1}>')
+
+    add_one_template_type_printer(obj, 'deque<T>',
+            'deque<(.*), std::allocator<\\1 ?> >',
+            'deque<{1}>')
+    add_one_template_type_printer(obj, 'forward_list<T>',
+            'forward_list<(.*), std::allocator<\\1 ?> >',
+            'forward_list<{1}>')
+    add_one_template_type_printer(obj, 'list<T>',
+            'list<(.*), std::allocator<\\1 ?> >',
+            'list<{1}>')
+    add_one_template_type_printer(obj, 'vector<T>',
+            'vector<(.*), std::allocator<\\1 ?> >',
+            'vector<{1}>')
+    add_one_template_type_printer(obj, 'map<Key, T>',
+            'map<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
+            'map<{1}, {2}>')
+    add_one_template_type_printer(obj, 'multimap<Key, T>',
+            'multimap<(.*), (.*), std::less<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
+            'multimap<{1}, {2}>')
+    add_one_template_type_printer(obj, 'set<T>',
+            'set<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
+            'set<{1}>')
+    add_one_template_type_printer(obj, 'multiset<T>',
+            'multiset<(.*), std::less<\\1 ?>, std::allocator<\\1 ?> >',
+            'multiset<{1}>')
+    add_one_template_type_printer(obj, 'unordered_map<Key, T>',
+            'unordered_map<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
+            'unordered_map<{1}, {2}>')
+    add_one_template_type_printer(obj, 'unordered_multimap<Key, T>',
+            'unordered_multimap<(.*), (.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<std::pair<\\1 const, \\2 ?> > >',
+            'unordered_multimap<{1}, {2}>')
+    add_one_template_type_printer(obj, 'unordered_set<T>',
+            'unordered_set<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
+            'unordered_set<{1}>')
+    add_one_template_type_printer(obj, 'unordered_multiset<T>',
+            'unordered_multiset<(.*), std::hash<\\1 ?>, std::equal_to<\\1 ?>, std::allocator<\\1 ?> >',
+            'unordered_multiset<{1}>')
+
+    # strip the "fundamentals_v1" inline namespace from these types
+    add_one_template_type_printer(obj, 'optional<T>',
+            'experimental::fundamentals_v1::optional<(.*)>',
+            'experimental::optional<\\1>')
+    add_one_template_type_printer(obj, 'basic_string_view<C>',
+            'experimental::fundamentals_v1::basic_string_view<(.*), std::char_traits<\\1> >',
+            'experimental::basic_string_view<\\1>')
+
 def register_libstdcxx_printers (obj):
     "Register libstdc++ pretty-printers with objfile Obj."
 
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
index fbbb772..b398972 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/whatis.cc
@@ -21,6 +21,15 @@
 #include <string>
 #include <iostream>
 #include <regex>
+#include <memory>
+#include <deque>
+#include <forward_list>
+#include <list>
+#include <vector>
+#include <map>
+#include <set>
+#include <unordered_map>
+#include <unordered_set>
 
 template<class T>
 void
@@ -159,6 +168,31 @@ std::basic_string<signed char> *sstring_ptr;
 holder< std::basic_string<signed char> > sstring_holder;
 // { dg-final { whatis-test sstring_holder "holder<std::basic_string<signed char, std::char_traits<signed char>, std::allocator<signed char> > >" } }
 
+std::vector<std::deque<std::unique_ptr<char>>> *seq1_ptr;
+holder< std::vector<std::deque<std::unique_ptr<char>>> > seq1_holder;
+// { dg-final { whatis-test seq1_holder "holder<std::vector<std::deque<std::unique_ptr<char>>> >" } }
+
+std::list<std::forward_list<std::unique_ptr<char>>> *seq2_ptr;
+holder< std::list<std::forward_list<std::unique_ptr<char>>> > seq2_holder;
+// { dg-final { whatis-test seq2_holder "holder<std::list<std::forward_list<std::unique_ptr<char>>> >" } }
+
+std::map<int, std::set<int>> *assoc1_ptr;
+holder< std::map<int, std::set<int>> > assoc1_holder;
+// { dg-final { whatis-test assoc1_holder "holder<std::map<int, std::set<int>> >" } }
+
+std::multimap<int, std::multiset<int>> *assoc2_ptr;
+holder< std::multimap<int, std::multiset<int>> > assoc2_holder;
+// { dg-final { whatis-test assoc2_holder "holder<std::multimap<int, std::multiset<int>> >" } }
+
+std::unordered_map<int, std::unordered_set<int>> *unord1_ptr;
+holder< std::unordered_map<int, std::unordered_set<int>> > unord1_holder;
+// { dg-final { whatis-test unord1_holder "holder<std::unordered_map<int, std::unordered_set<int>> >" } }
+
+std::unordered_multimap<int, std::unordered_multiset<int>> *unord2_ptr;
+holder< std::unordered_multimap<int, std::unordered_multiset<int>> > unord2_holder;
+// { dg-final { whatis-test unord2_holder "holder<std::unordered_multimap<int, std::unordered_multiset<int>> >" } }
+
+
 int
 main()
 {
@@ -236,6 +270,18 @@ main()
   placeholder(&ustring_holder);
   placeholder(&sstring_ptr);
   placeholder(&sstring_holder);
+  placeholder(&seq1_ptr);
+  placeholder(&seq1_holder);
+  placeholder(&seq2_ptr);
+  placeholder(&seq2_holder);
+  placeholder(&assoc1_ptr);
+  placeholder(&assoc1_holder);
+  placeholder(&assoc2_ptr);
+  placeholder(&assoc2_holder);
+  placeholder(&unord1_ptr);
+  placeholder(&unord1_holder);
+  placeholder(&unord2_ptr);
+  placeholder(&unord2_holder);
 
   return 0;
 }

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2014-08-05  6:23 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-14 14:34 [patch] Add libstdc++ type printers for class templates Jonathan Wakely
2014-07-14 19:31 ` Jonathan Wakely
2014-07-14 20:39   ` Tom Tromey
2014-07-15  2:25     ` Jonathan Wakely
2014-07-15 11:58       ` Jonathan Wakely
2014-08-05  6:23       ` Converting function pointers to PC values in Python (was: [patch] Add libstdc++ type printers for class templates) Samuel Bronson
2014-07-14 20:11 ` [patch] Add libstdc++ type printers for class templates Tom Tromey
2014-07-14 23:50   ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).