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