This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Add libstdc++ type printers for class templates


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.
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;
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]