summaryrefslogtreecommitdiff
path: root/libstdc++-v3/python/libstdcxx/v6/printers.py
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2015-04-22 10:21:45 +0000
committer <>2015-04-25 21:44:09 +0000
commitf80b5ea1605c9f9408c5aa386ba71c16d918ebbf (patch)
treebb7eafaa81fc4b8c5c215bc08d517fd158db234a /libstdc++-v3/python/libstdcxx/v6/printers.py
parentc27a97d04853380f1e80525391b3f0d156ed4c84 (diff)
downloadgcc-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.py287
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)