diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2015-04-22 10:21:45 +0000 |
---|---|---|
committer | <> | 2015-04-25 21:44:09 +0000 |
commit | f80b5ea1605c9f9408c5aa386ba71c16d918ebbf (patch) | |
tree | bb7eafaa81fc4b8c5c215bc08d517fd158db234a /libstdc++-v3/python/libstdcxx/v6/printers.py | |
parent | c27a97d04853380f1e80525391b3f0d156ed4c84 (diff) | |
download | gcc-tarball-f80b5ea1605c9f9408c5aa386ba71c16d918ebbf.tar.gz |
Imported from /home/lorry/working-area/delta_gcc-tarball/gcc-5.1.0.tar.bz2.gcc-5.1.0
Diffstat (limited to 'libstdc++-v3/python/libstdcxx/v6/printers.py')
-rw-r--r-- | libstdc++-v3/python/libstdcxx/v6/printers.py | 287 |
1 files changed, 269 insertions, 18 deletions
diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py index 1fa08fbd57..5a414c59a7 100644 --- a/libstdc++-v3/python/libstdcxx/v6/printers.py +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py @@ -1,6 +1,6 @@ # Pretty-printers for libstdc++. -# Copyright (C) 2008-2014 Free Software Foundation, Inc. +# Copyright (C) 2008-2015 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -327,22 +327,35 @@ class StdTuplePrinter: return self def __next__ (self): - nodes = self.head.type.fields () # Check for further recursions in the inheritance tree. + # For a GCC 5+ tuple self.head is None after visiting all nodes: + if not self.head: + raise StopIteration + nodes = self.head.type.fields () + # For a GCC 4.x tuple there is a final node with no fields: if len (nodes) == 0: raise StopIteration # Check that this iteration has an expected structure. - if len (nodes) != 2: + if len (nodes) > 2: raise ValueError("Cannot parse more than 2 nodes in a tuple tree.") - # - Left node is the next recursion parent. - # - Right node is the actual class contained in the tuple. + if len (nodes) == 1: + # This is the last node of a GCC 5+ std::tuple. + impl = self.head.cast (nodes[0].type) + self.head = None + else: + # Either a node before the last node, or the last node of + # a GCC 4.x tuple (which has an empty parent). - # Process right node. - impl = self.head.cast (nodes[1].type) + # - Left node is the next recursion parent. + # - Right node is the actual class contained in the tuple. + + # Process right node. + impl = self.head.cast (nodes[1].type) + + # Process left node and set it as head. + self.head = self.head.cast (nodes[0].type) - # Process left node and set it as head. - self.head = self.head.cast (nodes[0].type) self.count = self.count + 1 # Finally, check the implementation. If it is @@ -460,7 +473,7 @@ class StdDebugIteratorPrinter: # and return the wrapped iterator value. def to_string (self): itype = self.val.type.template_argument(0) - return self.val['_M_current'].cast(itype) + return self.val.cast(itype) class StdMapPrinter: "Print a std::map or std::multimap" @@ -660,6 +673,7 @@ class StdStringPrinter: def __init__(self, typename, val): self.val = val + self.new_string = typename.find("::__cxx11::basic_string") != -1 def to_string(self): # Make sure &string works, too. @@ -671,13 +685,18 @@ class StdStringPrinter: # the string according to length, not according to first null # encountered. ptr = self.val ['_M_dataplus']['_M_p'] - realtype = type.unqualified ().strip_typedefs () - reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer () - header = ptr.cast(reptype) - 1 - len = header.dereference ()['_M_length'] + if self.new_string: + length = self.val['_M_string_length'] + # https://sourceware.org/bugzilla/show_bug.cgi?id=17728 + ptr = ptr.cast(ptr.type.strip_typedefs()) + else: + realtype = type.unqualified ().strip_typedefs () + reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer () + header = ptr.cast(reptype) - 1 + length = header.dereference ()['_M_length'] if hasattr(ptr, "lazy_string"): - return ptr.lazy_string (length = len) - return ptr.string (length = len) + return ptr.lazy_string (length = length) + return ptr.string (length = length) def display_hint (self): return 'string' @@ -836,6 +855,129 @@ class StdForwardListPrinter: return 'empty %s' % (self.typename) return '%s' % (self.typename) +class SingleObjContainerPrinter(object): + "Base class for printers of containers of single objects" + + def __init__ (self, val, viz): + self.contained_value = val + self.visualizer = viz + + def _recognize(self, type): + """Return TYPE as a string after applying type printers""" + global _use_type_printing + if not _use_type_printing: + return str(type) + return gdb.types.apply_type_recognizers(gdb.types.get_type_recognizers(), + type) or str(type) + + class _contained(Iterator): + def __init__ (self, val): + self.val = val + + def __iter__ (self): + return self + + def __next__(self): + if self.val is None: + raise StopIteration + retval = self.val + self.val = None + return ('[contained value]', retval) + + def children (self): + if self.contained_value is None: + return self._contained (None) + if hasattr (self.visualizer, 'children'): + return self.visualizer.children () + return self._contained (self.contained_value) + + def display_hint (self): + # if contained value is a map we want to display in the same way + if hasattr (self.visualizer, 'children') and hasattr (self.visualizer, 'display_hint'): + return self.visualizer.display_hint () + return None + + +class StdExpAnyPrinter(SingleObjContainerPrinter): + "Print a std::experimental::any" + + def __init__ (self, typename, val): + self.typename = 'std::experimental::any' + self.val = val + self.contained_type = None + contained_value = None + visualizer = None + mgr = self.val['_M_manager'] + if mgr != 0: + func = gdb.block_for_pc(int(mgr.cast(gdb.lookup_type('intptr_t')))) + if not func: + raise ValueError("Invalid function pointer in std::experimental::any") + rx = r"""({0}::_Manager_\w+<.*>)::_S_manage\({0}::_Op, {0} const\*, {0}::_Arg\*\)""".format(typename) + m = re.match(rx, func.function.name) + if not m: + raise ValueError("Unknown manager function in std::experimental::any") + + # FIXME need to expand 'std::string' so that gdb.lookup_type works + mgrname = re.sub("std::string(?!\w)", str(gdb.lookup_type('std::string').strip_typedefs()), m.group(1)) + mgrtype = gdb.lookup_type(mgrname) + self.contained_type = mgrtype.template_argument(0) + valptr = None + if '::_Manager_internal' in mgrname: + valptr = self.val['_M_storage']['_M_buffer'].address + elif '::_Manager_external' in mgrname: + valptr = self.val['_M_storage']['_M_ptr'] + elif '::_Manager_alloc' in mgrname: + datatype = gdb.lookup_type(mgrname + '::_Data') + valptr = self.val['_M_storage']['_M_ptr'].cast(datatype.pointer()) + valptr = valptr.dereference()['_M_data'].address + else: + raise ValueError("Unknown manager function in std::experimental::any") + contained_value = valptr.cast(self.contained_type.pointer()).dereference() + visualizer = gdb.default_visualizer(contained_value) + super(StdExpAnyPrinter, self).__init__ (contained_value, visualizer) + + def to_string (self): + if self.contained_type is None: + return '%s [no contained value]' % self.typename + desc = "%s containing " % self.typename + if hasattr (self.visualizer, 'children'): + return desc + self.visualizer.to_string () + valtype = self._recognize (self.contained_type) + return desc + valtype + +class StdExpOptionalPrinter(SingleObjContainerPrinter): + "Print a std::experimental::optional" + + def __init__ (self, typename, val): + valtype = self._recognize (val.type.template_argument(0)) + self.typename = "std::experimental::optional<%s>" % valtype + self.val = val + contained_value = val['_M_payload'] if self.val['_M_engaged'] else None + visualizer = gdb.default_visualizer (val['_M_payload']) + super (StdExpOptionalPrinter, self).__init__ (contained_value, visualizer) + + def to_string (self): + if self.contained_value is None: + return self.typename + " [no contained value]" + if hasattr (self.visualizer, 'children'): + return self.typename + " containing " + self.visualizer.to_string () + return self.typename + +class StdExpStringViewPrinter: + "Print a std::experimental::basic_string_view" + + def __init__ (self, typename, val): + self.val = val + + def to_string (self): + ptr = self.val['_M_str'] + len = self.val['_M_len'] + if hasattr (ptr, "lazy_string"): + return ptr.lazy_string (length = len) + return ptr.string (length = len) + + def display_hint (self): + return 'string' # A "regular expression" printer which conforms to the # "SubPrettyPrinter" protocol from gdb.printing. @@ -865,12 +1007,12 @@ class Printer(object): self.subprinters = [] self.lookup = {} self.enabled = True - self.compiled_rx = re.compile('^([a-zA-Z0-9_:]+)<.*>$') + self.compiled_rx = re.compile('^([a-zA-Z0-9_:]+)(<.*>)?$') def add(self, name, function): # A small sanity check. # FIXME - if not self.compiled_rx.match(name + '<>'): + if not self.compiled_rx.match(name): raise ValueError('libstdc++ programming error: "%s" does not match' % name) printer = RxPrinter(name, function) self.subprinters.append(printer) @@ -922,6 +1064,57 @@ class Printer(object): libstdcxx_printer = None +class TemplateTypePrinter(object): + r"""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 +1206,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." @@ -1042,6 +1285,7 @@ def build_libstdcxx_dictionary (): # In order from: # http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01847.html libstdcxx_printer.add_version('std::', 'basic_string', StdStringPrinter) + libstdcxx_printer.add_version('std::', '__cxx11::basic_string', StdStringPrinter) libstdcxx_printer.add_container('std::', 'bitset', StdBitsetPrinter) libstdcxx_printer.add_container('std::', 'deque', StdDequePrinter) libstdcxx_printer.add_container('std::', 'list', StdListPrinter) @@ -1113,6 +1357,13 @@ def build_libstdcxx_dictionary (): libstdcxx_printer.add('std::__debug::forward_list', StdForwardListPrinter) + # Library Fundamentals TS components + libstdcxx_printer.add_version('std::experimental::fundamentals_v1::', + 'any', StdExpAnyPrinter) + libstdcxx_printer.add_version('std::experimental::fundamentals_v1::', + 'optional', StdExpOptionalPrinter) + libstdcxx_printer.add_version('std::experimental::fundamentals_v1::', + 'basic_string_view', StdExpStringViewPrinter) # Extensions. libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter) |