]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/python/libstdcxx/v6/printers.py
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / python / libstdcxx / v6 / printers.py
CommitLineData
b0a6074c 1# Pretty-printers for libstdc++.
b1986f6e 2
fbd26352 3# Copyright (C) 2008-2019 Free Software Foundation, Inc.
b1986f6e 4
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 3 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17
623653ee 18import gdb
b1986f6e 19import itertools
20import re
b0a6074c 21import sys
22
23### Python 2 + Python 3 compatibility code
24
25# Resources about compatibility:
26#
27# * <http://pythonhosted.org/six/>: Documentation of the "six" module
28
29# FIXME: The handling of e.g. std::basic_string (at least on char)
30# probably needs updating to work with Python 3's new string rules.
31#
32# In particular, Python 3 has a separate type (called byte) for
33# bytestrings, and a special b"" syntax for the byte literals; the old
34# str() type has been redefined to always store Unicode text.
35#
36# We probably can't do much about this until this GDB PR is addressed:
37# <https://sourceware.org/bugzilla/show_bug.cgi?id=17138>
38
39if sys.version_info[0] > 2:
40 ### Python 3 stuff
41 Iterator = object
42 # Python 3 folds these into the normal functions.
43 imap = map
44 izip = zip
45 # Also, int subsumes long
46 long = int
47else:
48 ### Python 2 stuff
49 class Iterator:
50 """Compatibility mixin for iterators
51
52 Instead of writing next() methods for iterators, write
53 __next__() methods and use this mixin to make them work in
54 Python 2 as well as Python 3.
55
56 Idea stolen from the "six" documentation:
57 <http://pythonhosted.org/six/#six.Iterator>
58 """
59
60 def next(self):
61 return self.__next__()
62
63 # In Python 2, we still need these from itertools
64 from itertools import imap, izip
b1986f6e 65
510f22a9 66# Try to use the new-style pretty-printing if available.
67_use_gdb_pp = True
68try:
69 import gdb.printing
70except ImportError:
71 _use_gdb_pp = False
72
0ed3336a 73# Try to install type-printers.
74_use_type_printing = False
75try:
76 import gdb.types
77 if hasattr(gdb.types, 'TypePrinter'):
78 _use_type_printing = True
79except ImportError:
80 pass
81
cd587d4d 82# Starting with the type ORIG, search for the member type NAME. This
83# handles searching upward through superclasses. This is needed to
84# work around http://sourceware.org/bugzilla/show_bug.cgi?id=13615.
85def find_type(orig, name):
86 typ = orig.strip_typedefs()
87 while True:
3541f29c 88 # Strip cv-qualifiers. PR 67440.
89 search = '%s::%s' % (typ.unqualified(), name)
cd587d4d 90 try:
91 return gdb.lookup_type(search)
92 except RuntimeError:
93 pass
94 # The type was not found, so try the superclass. We only need
95 # to check the first superclass, so we don't bother with
96 # anything fancier here.
97 field = typ.fields()[0]
98 if not field.is_base_class:
3a30bda9 99 raise ValueError("Cannot find type %s::%s" % (str(orig), name))
cd587d4d 100 typ = field.type
101
6f20076a 102_versioned_namespace = '__8::'
d813c3cd 103
023f288a 104def is_specialization_of(x, template_name):
d4f6ff2a 105 "Test if a type is a given template instantiation."
d813c3cd 106 global _versioned_namespace
023f288a 107 if type(x) is gdb.Type:
108 x = x.tag
d813c3cd 109 if _versioned_namespace:
023f288a 110 return re.match('^std::(%s)?%s<.*>$' % (_versioned_namespace, template_name), x) is not None
111 return re.match('^std::%s<.*>$' % template_name, x) is not None
d813c3cd 112
113def strip_versioned_namespace(typename):
114 global _versioned_namespace
115 if _versioned_namespace:
116 return typename.replace(_versioned_namespace, '')
117 return typename
118
d4f6ff2a 119def strip_inline_namespaces(type_str):
120 "Remove known inline namespaces from the canonical name of a type."
121 type_str = strip_versioned_namespace(type_str)
122 type_str = type_str.replace('std::__cxx11::', 'std::')
123 expt_ns = 'std::experimental::'
124 for lfts_ns in ('fundamentals_v1', 'fundamentals_v2'):
125 type_str = type_str.replace(expt_ns+lfts_ns+'::', expt_ns)
126 fs_ns = expt_ns + 'filesystem::'
127 type_str = type_str.replace(fs_ns+'v1::', fs_ns)
128 return type_str
129
130def get_template_arg_list(type_obj):
131 "Return a type's template arguments as a list"
132 n = 0
133 template_args = []
134 while True:
135 try:
136 template_args.append(type_obj.template_argument(n))
137 except:
138 return template_args
139 n += 1
140
13b767f5 141class SmartPtrIterator(Iterator):
142 "An iterator for smart pointer types with a single 'child' value"
143
144 def __init__(self, val):
145 self.val = val
146
147 def __iter__(self):
148 return self
149
150 def __next__(self):
151 if self.val is None:
152 raise StopIteration
153 self.val, val = None, self.val
154 return ('get()', val)
155
6c2e05ff 156class SharedPointerPrinter:
157 "Print a shared_ptr or weak_ptr"
b1986f6e 158
159 def __init__ (self, typename, val):
d813c3cd 160 self.typename = strip_versioned_namespace(typename)
b1986f6e 161 self.val = val
13b767f5 162 self.pointer = val['_M_ptr']
163
164 def children (self):
165 return SmartPtrIterator(self.pointer)
b1986f6e 166
167 def to_string (self):
6c2e05ff 168 state = 'empty'
169 refcounts = self.val['_M_refcount']['_M_pi']
170 if refcounts != 0:
171 usecount = refcounts['_M_use_count']
172 weakcount = refcounts['_M_weak_count']
173 if usecount == 0:
13b767f5 174 state = 'expired, weak count %d' % weakcount
6c2e05ff 175 else:
13b767f5 176 state = 'use count %d, weak count %d' % (usecount, weakcount - 1)
073fe8cf 177 return '%s<%s> (%s)' % (self.typename, str(self.val.type.template_argument(0)), state)
b1986f6e 178
179class UniquePointerPrinter:
180 "Print a unique_ptr"
181
510f22a9 182 def __init__ (self, typename, val):
b1986f6e 183 self.val = val
13b767f5 184 impl_type = val.type.fields()[0].type.tag
d813c3cd 185 if is_specialization_of(impl_type, '__uniq_ptr_impl'): # New implementation
13b767f5 186 self.pointer = val['_M_t']['_M_t']['_M_head_impl']
d813c3cd 187 elif is_specialization_of(impl_type, 'tuple'):
13b767f5 188 self.pointer = val['_M_t']['_M_head_impl']
bc8a7bf0 189 else:
13b767f5 190 raise ValueError("Unsupported implementation for unique_ptr: %s" % impl_type)
191
192 def children (self):
193 return SmartPtrIterator(self.pointer)
194
195 def to_string (self):
073fe8cf 196 return ('std::unique_ptr<%s>' % (str(self.val.type.template_argument(0))))
b1986f6e 197
67218f06 198def get_value_from_aligned_membuf(buf, valtype):
199 """Returns the value held in a __gnu_cxx::__aligned_membuf."""
200 return buf['_M_storage'].address.cast(valtype.pointer()).dereference()
201
41129c36 202def get_value_from_list_node(node):
203 """Returns the value held in an _List_node<_Val>"""
204 try:
205 member = node.type.fields()[1].name
206 if member == '_M_data':
207 # C++03 implementation, node contains the value as a member
208 return node['_M_data']
209 elif member == '_M_storage':
210 # C++11 implementation, node stores value in __aligned_membuf
67218f06 211 valtype = node.type.template_argument(0)
212 return get_value_from_aligned_membuf(node['_M_storage'], valtype)
41129c36 213 except:
214 pass
215 raise ValueError("Unsupported implementation for %s" % str(node.type))
216
b1986f6e 217class StdListPrinter:
218 "Print a std::list"
219
b0a6074c 220 class _iterator(Iterator):
b1986f6e 221 def __init__(self, nodetype, head):
222 self.nodetype = nodetype
223 self.base = head['_M_next']
224 self.head = head.address
225 self.count = 0
226
227 def __iter__(self):
228 return self
229
b0a6074c 230 def __next__(self):
b1986f6e 231 if self.base == self.head:
232 raise StopIteration
233 elt = self.base.cast(self.nodetype).dereference()
234 self.base = elt['_M_next']
235 count = self.count
236 self.count = self.count + 1
41129c36 237 val = get_value_from_list_node(elt)
238 return ('[%d]' % count, val)
b1986f6e 239
19791f4a 240 def __init__(self, typename, val):
d813c3cd 241 self.typename = strip_versioned_namespace(typename)
b1986f6e 242 self.val = val
243
244 def children(self):
cd587d4d 245 nodetype = find_type(self.val.type, '_Node')
246 nodetype = nodetype.strip_typedefs().pointer()
b1986f6e 247 return self._iterator(nodetype, self.val['_M_impl']['_M_node'])
248
249 def to_string(self):
250 if self.val['_M_impl']['_M_node'].address == self.val['_M_impl']['_M_node']['_M_next']:
19791f4a 251 return 'empty %s' % (self.typename)
252 return '%s' % (self.typename)
b1986f6e 253
db4f7f88 254class NodeIteratorPrinter:
255 def __init__(self, typename, val, contname):
b1986f6e 256 self.val = val
19791f4a 257 self.typename = typename
db4f7f88 258 self.contname = contname
b1986f6e 259
260 def to_string(self):
ec3e3110 261 if not self.val['_M_node']:
db4f7f88 262 return 'non-dereferenceable iterator for std::%s' % (self.contname)
cd587d4d 263 nodetype = find_type(self.val.type, '_Node')
264 nodetype = nodetype.strip_typedefs().pointer()
41129c36 265 node = self.val['_M_node'].cast(nodetype).dereference()
d989a3e0 266 return str(get_value_from_list_node(node))
b1986f6e 267
db4f7f88 268class StdListIteratorPrinter(NodeIteratorPrinter):
269 "Print std::list::iterator"
270
271 def __init__(self, typename, val):
272 NodeIteratorPrinter.__init__(self, typename, val, 'list')
273
274class StdFwdListIteratorPrinter(NodeIteratorPrinter):
275 "Print std::forward_list::iterator"
276
277 def __init__(self, typename, val):
278 NodeIteratorPrinter.__init__(self, typename, val, 'forward_list')
279
b1986f6e 280class StdSlistPrinter:
281 "Print a __gnu_cxx::slist"
282
b0a6074c 283 class _iterator(Iterator):
b1986f6e 284 def __init__(self, nodetype, head):
285 self.nodetype = nodetype
286 self.base = head['_M_head']['_M_next']
287 self.count = 0
288
289 def __iter__(self):
290 return self
291
b0a6074c 292 def __next__(self):
b1986f6e 293 if self.base == 0:
294 raise StopIteration
295 elt = self.base.cast(self.nodetype).dereference()
296 self.base = elt['_M_next']
297 count = self.count
298 self.count = self.count + 1
299 return ('[%d]' % count, elt['_M_data'])
300
510f22a9 301 def __init__(self, typename, val):
b1986f6e 302 self.val = val
303
304 def children(self):
cd587d4d 305 nodetype = find_type(self.val.type, '_Node')
306 nodetype = nodetype.strip_typedefs().pointer()
b1986f6e 307 return self._iterator(nodetype, self.val)
308
309 def to_string(self):
310 if self.val['_M_head']['_M_next'] == 0:
311 return 'empty __gnu_cxx::slist'
312 return '__gnu_cxx::slist'
313
314class StdSlistIteratorPrinter:
315 "Print __gnu_cxx::slist::iterator"
316
510f22a9 317 def __init__(self, typename, val):
b1986f6e 318 self.val = val
319
320 def to_string(self):
ec3e3110 321 if not self.val['_M_node']:
322 return 'non-dereferenceable iterator for __gnu_cxx::slist'
cd587d4d 323 nodetype = find_type(self.val.type, '_Node')
324 nodetype = nodetype.strip_typedefs().pointer()
d989a3e0 325 return str(self.val['_M_node'].cast(nodetype).dereference()['_M_data'])
b1986f6e 326
327class StdVectorPrinter:
328 "Print a std::vector"
329
b0a6074c 330 class _iterator(Iterator):
58486663 331 def __init__ (self, start, finish, bitvec):
332 self.bitvec = bitvec
333 if bitvec:
334 self.item = start['_M_p']
335 self.so = start['_M_offset']
336 self.finish = finish['_M_p']
337 self.fo = finish['_M_offset']
338 itype = self.item.dereference().type
339 self.isize = 8 * itype.sizeof
340 else:
341 self.item = start
342 self.finish = finish
b1986f6e 343 self.count = 0
344
345 def __iter__(self):
346 return self
347
b0a6074c 348 def __next__(self):
b1986f6e 349 count = self.count
350 self.count = self.count + 1
58486663 351 if self.bitvec:
352 if self.item == self.finish and self.so >= self.fo:
353 raise StopIteration
354 elt = self.item.dereference()
f42bd93b 355 if elt & (1 << self.so):
356 obit = 1
357 else:
358 obit = 0
58486663 359 self.so = self.so + 1
360 if self.so >= self.isize:
361 self.item = self.item + 1
362 self.so = 0
363 return ('[%d]' % count, obit)
364 else:
365 if self.item == self.finish:
366 raise StopIteration
367 elt = self.item.dereference()
368 self.item = self.item + 1
369 return ('[%d]' % count, elt)
b1986f6e 370
19791f4a 371 def __init__(self, typename, val):
d813c3cd 372 self.typename = strip_versioned_namespace(typename)
b1986f6e 373 self.val = val
58486663 374 self.is_bool = val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL
b1986f6e 375
376 def children(self):
377 return self._iterator(self.val['_M_impl']['_M_start'],
58486663 378 self.val['_M_impl']['_M_finish'],
379 self.is_bool)
b1986f6e 380
381 def to_string(self):
382 start = self.val['_M_impl']['_M_start']
383 finish = self.val['_M_impl']['_M_finish']
384 end = self.val['_M_impl']['_M_end_of_storage']
58486663 385 if self.is_bool:
386 start = self.val['_M_impl']['_M_start']['_M_p']
387 so = self.val['_M_impl']['_M_start']['_M_offset']
388 finish = self.val['_M_impl']['_M_finish']['_M_p']
389 fo = self.val['_M_impl']['_M_finish']['_M_offset']
390 itype = start.dereference().type
391 bl = 8 * itype.sizeof
392 length = (bl - so) + bl * ((finish - start) - 1) + fo
393 capacity = bl * (end - start)
394 return ('%s<bool> of length %d, capacity %d'
395 % (self.typename, int (length), int (capacity)))
396 else:
397 return ('%s of length %d, capacity %d'
398 % (self.typename, int (finish - start), int (end - start)))
b1986f6e 399
400 def display_hint(self):
401 return 'array'
402
403class StdVectorIteratorPrinter:
404 "Print std::vector::iterator"
405
510f22a9 406 def __init__(self, typename, val):
b1986f6e 407 self.val = val
408
409 def to_string(self):
ec3e3110 410 if not self.val['_M_current']:
411 return 'non-dereferenceable iterator for std::vector'
d989a3e0 412 return str(self.val['_M_current'].dereference())
b1986f6e 413
ebe3b39c 414class StdTuplePrinter:
415 "Print a std::tuple"
416
b0a6074c 417 class _iterator(Iterator):
023f288a 418 @staticmethod
419 def _is_nonempty_tuple (nodes):
420 if len (nodes) == 2:
421 if is_specialization_of (nodes[1].type, '__tuple_base'):
422 return True
423 elif len (nodes) == 1:
424 return True
425 elif len (nodes) == 0:
426 return False
427 raise ValueError("Top of tuple tree does not consist of a single node.")
428
ebe3b39c 429 def __init__ (self, head):
430 self.head = head
431
432 # Set the base class as the initial head of the
433 # tuple.
434 nodes = self.head.type.fields ()
023f288a 435 if self._is_nonempty_tuple (nodes):
7fe76953 436 # Set the actual head to the first pair.
437 self.head = self.head.cast (nodes[0].type)
ebe3b39c 438 self.count = 0
439
440 def __iter__ (self):
441 return self
442
b0a6074c 443 def __next__ (self):
ebe3b39c 444 # Check for further recursions in the inheritance tree.
c62683a7 445 # For a GCC 5+ tuple self.head is None after visiting all nodes:
446 if not self.head:
447 raise StopIteration
448 nodes = self.head.type.fields ()
449 # For a GCC 4.x tuple there is a final node with no fields:
ebe3b39c 450 if len (nodes) == 0:
451 raise StopIteration
452 # Check that this iteration has an expected structure.
c62683a7 453 if len (nodes) > 2:
3a30bda9 454 raise ValueError("Cannot parse more than 2 nodes in a tuple tree.")
ebe3b39c 455
c62683a7 456 if len (nodes) == 1:
457 # This is the last node of a GCC 5+ std::tuple.
458 impl = self.head.cast (nodes[0].type)
459 self.head = None
460 else:
461 # Either a node before the last node, or the last node of
462 # a GCC 4.x tuple (which has an empty parent).
463
464 # - Left node is the next recursion parent.
465 # - Right node is the actual class contained in the tuple.
ebe3b39c 466
c62683a7 467 # Process right node.
468 impl = self.head.cast (nodes[1].type)
469
470 # Process left node and set it as head.
471 self.head = self.head.cast (nodes[0].type)
ebe3b39c 472
ebe3b39c 473 self.count = self.count + 1
474
475 # Finally, check the implementation. If it is
476 # wrapped in _M_head_impl return that, otherwise return
477 # the value "as is".
478 fields = impl.type.fields ()
479 if len (fields) < 1 or fields[0].name != "_M_head_impl":
480 return ('[%d]' % self.count, impl)
481 else:
482 return ('[%d]' % self.count, impl['_M_head_impl'])
483
484 def __init__ (self, typename, val):
d813c3cd 485 self.typename = strip_versioned_namespace(typename)
ebe3b39c 486 self.val = val;
487
488 def children (self):
489 return self._iterator (self.val)
490
491 def to_string (self):
7fe76953 492 if len (self.val.type.fields ()) == 0:
493 return 'empty %s' % (self.typename)
ebe3b39c 494 return '%s containing' % (self.typename)
495
b1986f6e 496class StdStackOrQueuePrinter:
497 "Print a std::stack or std::queue"
498
499 def __init__ (self, typename, val):
d813c3cd 500 self.typename = strip_versioned_namespace(typename)
b1986f6e 501 self.visualizer = gdb.default_visualizer(val['c'])
502
503 def children (self):
504 return self.visualizer.children()
505
506 def to_string (self):
507 return '%s wrapping: %s' % (self.typename,
508 self.visualizer.to_string())
509
510 def display_hint (self):
511 if hasattr (self.visualizer, 'display_hint'):
512 return self.visualizer.display_hint ()
513 return None
514
b0a6074c 515class RbtreeIterator(Iterator):
1dc84a99 516 """
517 Turn an RB-tree-based container (std::map, std::set etc.) into
518 a Python iterable object.
519 """
520
b1986f6e 521 def __init__(self, rbtree):
522 self.size = rbtree['_M_t']['_M_impl']['_M_node_count']
523 self.node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left']
524 self.count = 0
525
526 def __iter__(self):
527 return self
528
529 def __len__(self):
530 return int (self.size)
531
b0a6074c 532 def __next__(self):
b1986f6e 533 if self.count == self.size:
534 raise StopIteration
535 result = self.node
536 self.count = self.count + 1
537 if self.count < self.size:
538 # Compute the next node.
539 node = self.node
540 if node.dereference()['_M_right']:
541 node = node.dereference()['_M_right']
542 while node.dereference()['_M_left']:
543 node = node.dereference()['_M_left']
544 else:
545 parent = node.dereference()['_M_parent']
546 while node == parent.dereference()['_M_right']:
547 node = parent
548 parent = parent.dereference()['_M_parent']
549 if node.dereference()['_M_right'] != parent:
550 node = parent
551 self.node = node
552 return result
553
1fcecb12 554def get_value_from_Rb_tree_node(node):
555 """Returns the value held in an _Rb_tree_node<_Val>"""
556 try:
557 member = node.type.fields()[1].name
558 if member == '_M_value_field':
559 # C++03 implementation, node contains the value as a member
560 return node['_M_value_field']
561 elif member == '_M_storage':
41129c36 562 # C++11 implementation, node stores value in __aligned_membuf
67218f06 563 valtype = node.type.template_argument(0)
564 return get_value_from_aligned_membuf(node['_M_storage'], valtype)
1fcecb12 565 except:
566 pass
3a30bda9 567 raise ValueError("Unsupported implementation for %s" % str(node.type))
1fcecb12 568
b1986f6e 569# This is a pretty printer for std::_Rb_tree_iterator (which is
570# std::map::iterator), and has nothing to do with the RbtreeIterator
571# class above.
572class StdRbtreeIteratorPrinter:
1dc84a99 573 "Print std::map::iterator, std::set::iterator, etc."
b1986f6e 574
510f22a9 575 def __init__ (self, typename, val):
b1986f6e 576 self.val = val
726854a8 577 valtype = self.val.type.template_argument(0).strip_typedefs()
d813c3cd 578 nodetype = '_Rb_tree_node<' + str(valtype) + '>'
579 if _versioned_namespace and typename.startswith('std::' + _versioned_namespace):
580 nodetype = _versioned_namespace + nodetype
581 nodetype = gdb.lookup_type('std::' + nodetype)
726854a8 582 self.link_type = nodetype.strip_typedefs().pointer()
b1986f6e 583
584 def to_string (self):
ec3e3110 585 if not self.val['_M_node']:
586 return 'non-dereferenceable iterator for associative container'
726854a8 587 node = self.val['_M_node'].cast(self.link_type).dereference()
d989a3e0 588 return str(get_value_from_Rb_tree_node(node))
b1986f6e 589
19791f4a 590class StdDebugIteratorPrinter:
591 "Print a debug enabled version of an iterator"
592
510f22a9 593 def __init__ (self, typename, val):
19791f4a 594 self.val = val
595
596 # Just strip away the encapsulating __gnu_debug::_Safe_iterator
597 # and return the wrapped iterator value.
598 def to_string (self):
cbd50187 599 base_type = gdb.lookup_type('__gnu_debug::_Safe_iterator_base')
db4f7f88 600 itype = self.val.type.template_argument(0)
cbd50187 601 safe_seq = self.val.cast(base_type)['_M_sequence']
db4f7f88 602 if not safe_seq:
603 return str(self.val.cast(itype))
604 if self.val['_M_version'] != safe_seq['_M_version']:
cbd50187 605 return "invalid iterator"
d989a3e0 606 return str(self.val.cast(itype))
b1986f6e 607
ee6bf894 608def num_elements(num):
609 """Return either "1 element" or "N elements" depending on the argument."""
610 return '1 element' if num == 1 else '%d elements' % num
611
b1986f6e 612class StdMapPrinter:
613 "Print a std::map or std::multimap"
614
615 # Turn an RbtreeIterator into a pretty-print iterator.
b0a6074c 616 class _iter(Iterator):
b1986f6e 617 def __init__(self, rbiter, type):
618 self.rbiter = rbiter
619 self.count = 0
620 self.type = type
621
622 def __iter__(self):
623 return self
624
b0a6074c 625 def __next__(self):
b1986f6e 626 if self.count % 2 == 0:
b0a6074c 627 n = next(self.rbiter)
1fcecb12 628 n = n.cast(self.type).dereference()
629 n = get_value_from_Rb_tree_node(n)
b1986f6e 630 self.pair = n
631 item = n['first']
632 else:
633 item = self.pair['second']
634 result = ('[%d]' % self.count, item)
635 self.count = self.count + 1
636 return result
637
638 def __init__ (self, typename, val):
d813c3cd 639 self.typename = strip_versioned_namespace(typename)
b1986f6e 640 self.val = val
b1986f6e 641
642 def to_string (self):
ee6bf894 643 return '%s with %s' % (self.typename,
644 num_elements(len(RbtreeIterator (self.val))))
b1986f6e 645
646 def children (self):
cd587d4d 647 rep_type = find_type(self.val.type, '_Rep_type')
648 node = find_type(rep_type, '_Link_type')
649 node = node.strip_typedefs()
650 return self._iter (RbtreeIterator (self.val), node)
b1986f6e 651
652 def display_hint (self):
653 return 'map'
654
655class StdSetPrinter:
656 "Print a std::set or std::multiset"
657
658 # Turn an RbtreeIterator into a pretty-print iterator.
b0a6074c 659 class _iter(Iterator):
b1986f6e 660 def __init__(self, rbiter, type):
661 self.rbiter = rbiter
662 self.count = 0
663 self.type = type
664
665 def __iter__(self):
666 return self
667
b0a6074c 668 def __next__(self):
669 item = next(self.rbiter)
1fcecb12 670 item = item.cast(self.type).dereference()
671 item = get_value_from_Rb_tree_node(item)
b1986f6e 672 # FIXME: this is weird ... what to do?
673 # Maybe a 'set' display hint?
674 result = ('[%d]' % self.count, item)
675 self.count = self.count + 1
676 return result
677
678 def __init__ (self, typename, val):
d813c3cd 679 self.typename = strip_versioned_namespace(typename)
b1986f6e 680 self.val = val
b1986f6e 681
682 def to_string (self):
ee6bf894 683 return '%s with %s' % (self.typename,
684 num_elements(len(RbtreeIterator (self.val))))
b1986f6e 685
686 def children (self):
cd587d4d 687 rep_type = find_type(self.val.type, '_Rep_type')
688 node = find_type(rep_type, '_Link_type')
689 node = node.strip_typedefs()
690 return self._iter (RbtreeIterator (self.val), node)
b1986f6e 691
692class StdBitsetPrinter:
693 "Print a std::bitset"
694
19791f4a 695 def __init__(self, typename, val):
d813c3cd 696 self.typename = strip_versioned_namespace(typename)
b1986f6e 697 self.val = val
698
699 def to_string (self):
700 # If template_argument handled values, we could print the
701 # size. Or we could use a regexp on the type.
19791f4a 702 return '%s' % (self.typename)
b1986f6e 703
704 def children (self):
85e3666c 705 try:
706 # An empty bitset may not have any members which will
707 # result in an exception being thrown.
708 words = self.val['_M_w']
709 except:
710 return []
711
b1986f6e 712 wtype = words.type
713
714 # The _M_w member can be either an unsigned long, or an
715 # array. This depends on the template specialization used.
716 # If it is a single long, convert to a single element list.
717 if wtype.code == gdb.TYPE_CODE_ARRAY:
718 tsize = wtype.target ().sizeof
719 else:
720 words = [words]
85e3666c 721 tsize = wtype.sizeof
b1986f6e 722
723 nwords = wtype.sizeof / tsize
724 result = []
725 byte = 0
726 while byte < nwords:
727 w = words[byte]
728 bit = 0
729 while w != 0:
730 if (w & 1) != 0:
731 # Another spot where we could use 'set'?
732 result.append(('[%d]' % (byte * tsize * 8 + bit), 1))
733 bit = bit + 1
734 w = w >> 1
735 byte = byte + 1
736 return result
737
738class StdDequePrinter:
739 "Print a std::deque"
740
b0a6074c 741 class _iter(Iterator):
b1986f6e 742 def __init__(self, node, start, end, last, buffer_size):
743 self.node = node
744 self.p = start
745 self.end = end
746 self.last = last
747 self.buffer_size = buffer_size
748 self.count = 0
749
750 def __iter__(self):
751 return self
752
b0a6074c 753 def __next__(self):
b1986f6e 754 if self.p == self.last:
755 raise StopIteration
756
757 result = ('[%d]' % self.count, self.p.dereference())
758 self.count = self.count + 1
759
760 # Advance the 'cur' pointer.
761 self.p = self.p + 1
762 if self.p == self.end:
763 # If we got to the end of this bucket, move to the
764 # next bucket.
765 self.node = self.node + 1
766 self.p = self.node[0]
767 self.end = self.p + self.buffer_size
768
769 return result
770
19791f4a 771 def __init__(self, typename, val):
d813c3cd 772 self.typename = strip_versioned_namespace(typename)
b1986f6e 773 self.val = val
774 self.elttype = val.type.template_argument(0)
775 size = self.elttype.sizeof
776 if size < 512:
777 self.buffer_size = int (512 / size)
778 else:
779 self.buffer_size = 1
780
781 def to_string(self):
782 start = self.val['_M_impl']['_M_start']
783 end = self.val['_M_impl']['_M_finish']
784
785 delta_n = end['_M_node'] - start['_M_node'] - 1
786 delta_s = start['_M_last'] - start['_M_cur']
787 delta_e = end['_M_cur'] - end['_M_first']
788
789 size = self.buffer_size * delta_n + delta_s + delta_e
790
ee6bf894 791 return '%s with %s' % (self.typename, num_elements(long(size)))
b1986f6e 792
793 def children(self):
794 start = self.val['_M_impl']['_M_start']
795 end = self.val['_M_impl']['_M_finish']
796 return self._iter(start['_M_node'], start['_M_cur'], start['_M_last'],
797 end['_M_cur'], self.buffer_size)
798
799 def display_hint (self):
800 return 'array'
801
802class StdDequeIteratorPrinter:
803 "Print std::deque::iterator"
804
510f22a9 805 def __init__(self, typename, val):
b1986f6e 806 self.val = val
807
808 def to_string(self):
ec3e3110 809 if not self.val['_M_cur']:
810 return 'non-dereferenceable iterator for std::deque'
d989a3e0 811 return str(self.val['_M_cur'].dereference())
b1986f6e 812
813class StdStringPrinter:
814 "Print a std::basic_string of some kind"
815
510f22a9 816 def __init__(self, typename, val):
b1986f6e 817 self.val = val
63f54259 818 self.new_string = typename.find("::__cxx11::basic_string") != -1
b1986f6e 819
820 def to_string(self):
ffa1c35e 821 # Make sure &string works, too.
822 type = self.val.type
823 if type.code == gdb.TYPE_CODE_REF:
824 type = type.target ()
825
826 # Calculate the length of the string so that to_string returns
827 # the string according to length, not according to first null
828 # encountered.
829 ptr = self.val ['_M_dataplus']['_M_p']
63f54259 830 if self.new_string:
831 length = self.val['_M_string_length']
832 # https://sourceware.org/bugzilla/show_bug.cgi?id=17728
833 ptr = ptr.cast(ptr.type.strip_typedefs())
834 else:
835 realtype = type.unqualified ().strip_typedefs ()
836 reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer ()
837 header = ptr.cast(reptype) - 1
838 length = header.dereference ()['_M_length']
4c4fb6b0 839 if hasattr(ptr, "lazy_string"):
63f54259 840 return ptr.lazy_string (length = length)
841 return ptr.string (length = length)
b1986f6e 842
843 def display_hint (self):
844 return 'string'
845
b0a6074c 846class Tr1HashtableIterator(Iterator):
b1986f6e 847 def __init__ (self, hash):
611894d1 848 self.buckets = hash['_M_buckets']
849 self.bucket = 0
850 self.bucket_count = hash['_M_bucket_count']
851 self.node_type = find_type(hash.type, '_Node').pointer()
852 self.node = 0
853 while self.bucket != self.bucket_count:
854 self.node = self.buckets[self.bucket]
855 if self.node:
856 break
85e3666c 857 self.bucket = self.bucket + 1
b1986f6e 858
859 def __iter__ (self):
860 return self
861
b0a6074c 862 def __next__ (self):
cecc3a9a 863 if self.node == 0:
b1986f6e 864 raise StopIteration
cecc3a9a 865 node = self.node.cast(self.node_type)
866 result = node.dereference()['_M_v']
611894d1 867 self.node = node.dereference()['_M_next'];
868 if self.node == 0:
869 self.bucket = self.bucket + 1
870 while self.bucket != self.bucket_count:
871 self.node = self.buckets[self.bucket]
872 if self.node:
873 break
874 self.bucket = self.bucket + 1
b1986f6e 875 return result
876
b0a6074c 877class StdHashtableIterator(Iterator):
611894d1 878 def __init__(self, hash):
b0a82d23 879 self.node = hash['_M_before_begin']['_M_nxt']
611894d1 880 self.node_type = find_type(hash.type, '__node_type').pointer()
881
882 def __iter__(self):
883 return self
884
b0a6074c 885 def __next__(self):
611894d1 886 if self.node == 0:
887 raise StopIteration
888 elt = self.node.cast(self.node_type).dereference()
889 self.node = elt['_M_nxt']
890 valptr = elt['_M_storage'].address
891 valptr = valptr.cast(elt.type.template_argument(0).pointer())
892 return valptr.dereference()
893
b1986f6e 894class Tr1UnorderedSetPrinter:
895 "Print a tr1::unordered_set"
896
897 def __init__ (self, typename, val):
d813c3cd 898 self.typename = strip_versioned_namespace(typename)
b1986f6e 899 self.val = val
900
ded5331d 901 def hashtable (self):
902 if self.typename.startswith('std::tr1'):
903 return self.val
904 return self.val['_M_h']
905
b1986f6e 906 def to_string (self):
ee6bf894 907 count = self.hashtable()['_M_element_count']
908 return '%s with %s' % (self.typename, num_elements(count))
b1986f6e 909
910 @staticmethod
911 def format_count (i):
912 return '[%d]' % i
913
914 def children (self):
b0a6074c 915 counter = imap (self.format_count, itertools.count())
611894d1 916 if self.typename.startswith('std::tr1'):
b0a6074c 917 return izip (counter, Tr1HashtableIterator (self.hashtable()))
918 return izip (counter, StdHashtableIterator (self.hashtable()))
b1986f6e 919
920class Tr1UnorderedMapPrinter:
921 "Print a tr1::unordered_map"
922
923 def __init__ (self, typename, val):
d813c3cd 924 self.typename = strip_versioned_namespace(typename)
b1986f6e 925 self.val = val
926
ded5331d 927 def hashtable (self):
928 if self.typename.startswith('std::tr1'):
929 return self.val
930 return self.val['_M_h']
931
b1986f6e 932 def to_string (self):
ee6bf894 933 count = self.hashtable()['_M_element_count']
934 return '%s with %s' % (self.typename, num_elements(count))
b1986f6e 935
936 @staticmethod
937 def flatten (list):
938 for elt in list:
939 for i in elt:
940 yield i
941
942 @staticmethod
943 def format_one (elt):
944 return (elt['first'], elt['second'])
945
946 @staticmethod
947 def format_count (i):
948 return '[%d]' % i
949
950 def children (self):
b0a6074c 951 counter = imap (self.format_count, itertools.count())
b1986f6e 952 # Map over the hash table and flatten the result.
611894d1 953 if self.typename.startswith('std::tr1'):
b0a6074c 954 data = self.flatten (imap (self.format_one, Tr1HashtableIterator (self.hashtable())))
611894d1 955 # Zip the two iterators together.
b0a6074c 956 return izip (counter, data)
957 data = self.flatten (imap (self.format_one, StdHashtableIterator (self.hashtable())))
b1986f6e 958 # Zip the two iterators together.
b0a6074c 959 return izip (counter, data)
b1986f6e 960
961 def display_hint (self):
962 return 'map'
963
3c80034b 964class StdForwardListPrinter:
965 "Print a std::forward_list"
966
b0a6074c 967 class _iterator(Iterator):
3c80034b 968 def __init__(self, nodetype, head):
969 self.nodetype = nodetype
970 self.base = head['_M_next']
971 self.count = 0
972
973 def __iter__(self):
974 return self
975
b0a6074c 976 def __next__(self):
3c80034b 977 if self.base == 0:
978 raise StopIteration
979 elt = self.base.cast(self.nodetype).dereference()
980 self.base = elt['_M_next']
981 count = self.count
982 self.count = self.count + 1
bf1e1356 983 valptr = elt['_M_storage'].address
984 valptr = valptr.cast(elt.type.template_argument(0).pointer())
985 return ('[%d]' % count, valptr.dereference())
3c80034b 986
987 def __init__(self, typename, val):
988 self.val = val
d813c3cd 989 self.typename = strip_versioned_namespace(typename)
3c80034b 990
991 def children(self):
cd587d4d 992 nodetype = find_type(self.val.type, '_Node')
993 nodetype = nodetype.strip_typedefs().pointer()
3c80034b 994 return self._iterator(nodetype, self.val['_M_impl']['_M_head'])
995
996 def to_string(self):
997 if self.val['_M_impl']['_M_head']['_M_next'] == 0:
1dc84a99 998 return 'empty %s' % self.typename
999 return '%s' % self.typename
3c80034b 1000
f29d6b5d 1001class SingleObjContainerPrinter(object):
1002 "Base class for printers of containers of single objects"
1003
bd4dc25f 1004 def __init__ (self, val, viz, hint = None):
f29d6b5d 1005 self.contained_value = val
1006 self.visualizer = viz
bd4dc25f 1007 self.hint = hint
f29d6b5d 1008
1009 def _recognize(self, type):
1010 """Return TYPE as a string after applying type printers"""
dacf2aec 1011 global _use_type_printing
1012 if not _use_type_printing:
1013 return str(type)
f29d6b5d 1014 return gdb.types.apply_type_recognizers(gdb.types.get_type_recognizers(),
1015 type) or str(type)
1016
fffc4f5a 1017 class _contained(Iterator):
f29d6b5d 1018 def __init__ (self, val):
1019 self.val = val
1020
1021 def __iter__ (self):
1022 return self
1023
fffc4f5a 1024 def __next__(self):
f29d6b5d 1025 if self.val is None:
1026 raise StopIteration
1027 retval = self.val
1028 self.val = None
1029 return ('[contained value]', retval)
1030
1031 def children (self):
1032 if self.contained_value is None:
1033 return self._contained (None)
1034 if hasattr (self.visualizer, 'children'):
1035 return self.visualizer.children ()
1036 return self._contained (self.contained_value)
1037
1038 def display_hint (self):
1039 # if contained value is a map we want to display in the same way
1040 if hasattr (self.visualizer, 'children') and hasattr (self.visualizer, 'display_hint'):
1041 return self.visualizer.display_hint ()
bd4dc25f 1042 return self.hint
f29d6b5d 1043
f29d6b5d 1044class StdExpAnyPrinter(SingleObjContainerPrinter):
e11be3ea 1045 "Print a std::any or std::experimental::any"
f29d6b5d 1046
1047 def __init__ (self, typename, val):
c730c800 1048 self.typename = strip_versioned_namespace(typename)
1049 self.typename = re.sub('^std::experimental::fundamentals_v\d::', 'std::experimental::', self.typename, 1)
f29d6b5d 1050 self.val = val
1051 self.contained_type = None
1052 contained_value = None
1053 visualizer = None
1054 mgr = self.val['_M_manager']
1055 if mgr != 0:
1056 func = gdb.block_for_pc(int(mgr.cast(gdb.lookup_type('intptr_t'))))
1057 if not func:
e11be3ea 1058 raise ValueError("Invalid function pointer in %s" % self.typename)
fb75ff45 1059 rx = r"""({0}::_Manager_\w+<.*>)::_S_manage\((enum )?{0}::_Op, (const {0}|{0} const) ?\*, (union )?{0}::_Arg ?\*\)""".format(typename)
f29d6b5d 1060 m = re.match(rx, func.function.name)
1061 if not m:
e11be3ea 1062 raise ValueError("Unknown manager function in %s" % self.typename)
f29d6b5d 1063
d813c3cd 1064 mgrname = m.group(1)
f29d6b5d 1065 # FIXME need to expand 'std::string' so that gdb.lookup_type works
d813c3cd 1066 if 'std::string' in mgrname:
1067 mgrname = re.sub("std::string(?!\w)", str(gdb.lookup_type('std::string').strip_typedefs()), m.group(1))
1068
f29d6b5d 1069 mgrtype = gdb.lookup_type(mgrname)
1070 self.contained_type = mgrtype.template_argument(0)
1071 valptr = None
1072 if '::_Manager_internal' in mgrname:
1073 valptr = self.val['_M_storage']['_M_buffer'].address
1074 elif '::_Manager_external' in mgrname:
1075 valptr = self.val['_M_storage']['_M_ptr']
f29d6b5d 1076 else:
e11be3ea 1077 raise ValueError("Unknown manager function in %s" % self.typename)
f29d6b5d 1078 contained_value = valptr.cast(self.contained_type.pointer()).dereference()
1079 visualizer = gdb.default_visualizer(contained_value)
1080 super(StdExpAnyPrinter, self).__init__ (contained_value, visualizer)
1081
1082 def to_string (self):
1083 if self.contained_type is None:
1084 return '%s [no contained value]' % self.typename
1085 desc = "%s containing " % self.typename
1086 if hasattr (self.visualizer, 'children'):
1087 return desc + self.visualizer.to_string ()
1088 valtype = self._recognize (self.contained_type)
d813c3cd 1089 return desc + strip_versioned_namespace(str(valtype))
f29d6b5d 1090
1091class StdExpOptionalPrinter(SingleObjContainerPrinter):
e11be3ea 1092 "Print a std::optional or std::experimental::optional"
f29d6b5d 1093
1094 def __init__ (self, typename, val):
1095 valtype = self._recognize (val.type.template_argument(0))
c730c800 1096 self.typename = strip_versioned_namespace(typename)
1097 self.typename = re.sub('^std::(experimental::|)(fundamentals_v\d::|)(.*)', r'std::\1\3<%s>' % valtype, self.typename, 1)
87da5170 1098 if not self.typename.startswith('std::experimental'):
1099 val = val['_M_payload']
f29d6b5d 1100 self.val = val
1101 contained_value = val['_M_payload'] if self.val['_M_engaged'] else None
1102 visualizer = gdb.default_visualizer (val['_M_payload'])
1103 super (StdExpOptionalPrinter, self).__init__ (contained_value, visualizer)
1104
1105 def to_string (self):
1106 if self.contained_value is None:
1dc84a99 1107 return "%s [no contained value]" % self.typename
f29d6b5d 1108 if hasattr (self.visualizer, 'children'):
1dc84a99 1109 return "%s containing %s" % (self.typename,
1110 self.visualizer.to_string())
f29d6b5d 1111 return self.typename
1112
e11be3ea 1113class StdVariantPrinter(SingleObjContainerPrinter):
1114 "Print a std::variant"
1115
1116 def __init__(self, typename, val):
d4f6ff2a 1117 alternatives = get_template_arg_list(val.type)
c730c800 1118 self.typename = strip_versioned_namespace(typename)
1119 self.typename = "%s<%s>" % (self.typename, ', '.join([self._recognize(alt) for alt in alternatives]))
e11be3ea 1120 self.index = val['_M_index']
1121 if self.index >= len(alternatives):
1122 self.contained_type = None
1123 contained_value = None
1124 visualizer = None
1125 else:
1126 self.contained_type = alternatives[int(self.index)]
d80f17d7 1127 addr = val['_M_u']['_M_first']['_M_storage'].address
e11be3ea 1128 contained_value = addr.cast(self.contained_type.pointer()).dereference()
1129 visualizer = gdb.default_visualizer(contained_value)
bd4dc25f 1130 super (StdVariantPrinter, self).__init__(contained_value, visualizer, 'array')
e11be3ea 1131
e11be3ea 1132 def to_string(self):
1133 if self.contained_value is None:
bd4dc25f 1134 return "%s [no contained value]" % self.typename
e11be3ea 1135 if hasattr(self.visualizer, 'children'):
1dc84a99 1136 return "%s [index %d] containing %s" % (self.typename, self.index,
1137 self.visualizer.to_string())
bd4dc25f 1138 return "%s [index %d]" % (self.typename, self.index)
e11be3ea 1139
67218f06 1140class StdNodeHandlePrinter(SingleObjContainerPrinter):
1141 "Print a container node handle"
1142
1143 def __init__(self, typename, val):
1144 self.value_type = val.type.template_argument(1)
1145 nodetype = val.type.template_argument(2).template_argument(0)
d813c3cd 1146 self.is_rb_tree_node = is_specialization_of(nodetype.name, '_Rb_tree_node')
67218f06 1147 self.is_map_node = val.type.template_argument(0) != self.value_type
1148 nodeptr = val['_M_ptr']
1149 if nodeptr:
1150 if self.is_rb_tree_node:
1151 contained_value = get_value_from_Rb_tree_node(nodeptr.dereference())
1152 else:
1153 contained_value = get_value_from_aligned_membuf(nodeptr['_M_storage'],
1154 self.value_type)
1155 visualizer = gdb.default_visualizer(contained_value)
1156 else:
1157 contained_value = None
1158 visualizer = None
1159 optalloc = val['_M_alloc']
1160 self.alloc = optalloc['_M_payload'] if optalloc['_M_engaged'] else None
1161 super(StdNodeHandlePrinter, self).__init__(contained_value, visualizer,
1162 'array')
1163
1164 def to_string(self):
67218f06 1165 desc = 'node handle for '
1166 if not self.is_rb_tree_node:
1167 desc += 'unordered '
1168 if self.is_map_node:
1169 desc += 'map';
1170 else:
1171 desc += 'set';
1172
1173 if self.contained_value:
1174 desc += ' with element'
1175 if hasattr(self.visualizer, 'children'):
1176 return "%s = %s" % (desc, self.visualizer.to_string())
1177 return desc
1178 else:
1179 return 'empty %s' % desc
1180
f29d6b5d 1181class StdExpStringViewPrinter:
e11be3ea 1182 "Print a std::basic_string_view or std::experimental::basic_string_view"
f29d6b5d 1183
1184 def __init__ (self, typename, val):
1185 self.val = val
1186
1187 def to_string (self):
1188 ptr = self.val['_M_str']
1189 len = self.val['_M_len']
1190 if hasattr (ptr, "lazy_string"):
1191 return ptr.lazy_string (length = len)
1192 return ptr.string (length = len)
1193
1194 def display_hint (self):
1195 return 'string'
3c80034b 1196
5924b28e 1197class StdExpPathPrinter:
1198 "Print a std::experimental::filesystem::path"
1199
1200 def __init__ (self, typename, val):
1201 self.val = val
d1eff9de 1202 start = self.val['_M_cmpts']['_M_impl']['_M_start']
1203 finish = self.val['_M_cmpts']['_M_impl']['_M_finish']
1204 self.num_cmpts = int (finish - start)
1205
1206 def _path_type(self):
1207 t = str(self.val['_M_type'])
1208 if t[-9:] == '_Root_dir':
1209 return "root-directory"
1210 if t[-10:] == '_Root_name':
1211 return "root-name"
1212 return None
5924b28e 1213
1214 def to_string (self):
d1eff9de 1215 path = "%s" % self.val ['_M_pathname']
1216 if self.num_cmpts == 0:
1217 t = self._path_type()
1218 if t:
1219 path = '%s [%s]' % (path, t)
1220 return "filesystem::path %s" % path
1221
1222 class _iterator(Iterator):
1223 def __init__(self, cmpts):
1224 self.item = cmpts['_M_impl']['_M_start']
1225 self.finish = cmpts['_M_impl']['_M_finish']
1226 self.count = 0
1227
1228 def __iter__(self):
1229 return self
1230
1231 def __next__(self):
1232 if self.item == self.finish:
1233 raise StopIteration
1234 item = self.item.dereference()
1235 count = self.count
1236 self.count = self.count + 1
1237 self.item = self.item + 1
1238 path = item['_M_pathname']
1239 t = StdExpPathPrinter(item.type.name, item)._path_type()
1240 if not t:
1241 t = count
1242 return ('[%s]' % t, path)
1243
1244 def children(self):
1245 return self._iterator(self.val['_M_cmpts'])
1246
6bec006a 1247class StdPathPrinter:
1248 "Print a std::filesystem::path"
1249
1250 def __init__ (self, typename, val):
1251 self.val = val
1252 self.typename = typename
1253 impl = self.val['_M_cmpts']['_M_impl']['_M_t']['_M_t']['_M_head_impl']
1254 self.type = impl.cast(gdb.lookup_type('uintptr_t')) & 3
1255 if self.type == 0:
1256 self.impl = impl
1257 else:
1258 self.impl = None
1259
1260 def _path_type(self):
1261 t = str(self.type.cast(gdb.lookup_type(self.typename + '::_Type')))
1262 if t[-9:] == '_Root_dir':
1263 return "root-directory"
1264 if t[-10:] == '_Root_name':
1265 return "root-name"
1266 return None
1267
1268 def to_string (self):
1269 path = "%s" % self.val ['_M_pathname']
1270 if self.type != 0:
1271 t = self._path_type()
1272 if t:
1273 path = '%s [%s]' % (path, t)
1274 return "filesystem::path %s" % path
1275
1276 class _iterator(Iterator):
1277 def __init__(self, impl, pathtype):
1278 if impl:
1279 # We can't access _Impl::_M_size because _Impl is incomplete
1280 # so cast to int* to access the _M_size member at offset zero,
1281 int_type = gdb.lookup_type('int')
1282 cmpt_type = gdb.lookup_type(pathtype+'::_Cmpt')
1283 char_type = gdb.lookup_type('char')
1284 impl = impl.cast(int_type.pointer())
1285 size = impl.dereference()
1286 #self.capacity = (impl + 1).dereference()
1287 if hasattr(gdb.Type, 'alignof'):
1288 sizeof_Impl = max(2 * int_type.sizeof, cmpt_type.alignof)
1289 else:
1290 sizeof_Impl = 2 * int_type.sizeof
1291 begin = impl.cast(char_type.pointer()) + sizeof_Impl
1292 self.item = begin.cast(cmpt_type.pointer())
1293 self.finish = self.item + size
1294 self.count = 0
1295 else:
1296 self.item = None
1297 self.finish = None
1298
1299 def __iter__(self):
1300 return self
1301
1302 def __next__(self):
1303 if self.item == self.finish:
1304 raise StopIteration
1305 item = self.item.dereference()
1306 count = self.count
1307 self.count = self.count + 1
1308 self.item = self.item + 1
1309 path = item['_M_pathname']
1310 t = StdPathPrinter(item.type.name, item)._path_type()
1311 if not t:
1312 t = count
1313 return ('[%s]' % t, path)
1314
1315 def children(self):
1316 return self._iterator(self.impl, self.typename)
1317
5924b28e 1318
785c6c31 1319class StdPairPrinter:
1320 "Print a std::pair object, with 'first' and 'second' as children"
1321
1322 def __init__(self, typename, val):
1323 self.val = val
1324
1325 class _iter(Iterator):
1326 "An iterator for std::pair types. Returns 'first' then 'second'."
1327
1328 def __init__(self, val):
1329 self.val = val
1330 self.which = 'first'
1331
1332 def __iter__(self):
1333 return self
1334
1335 def __next__(self):
1336 if self.which is None:
1337 raise StopIteration
1338 which = self.which
1339 if which == 'first':
1340 self.which = 'second'
1341 else:
1342 self.which = None
1343 return (which, self.val[which])
1344
1345 def children(self):
1346 return self._iter(self.val)
1347
1348 def to_string(self):
1349 return None
1350
1351
510f22a9 1352# A "regular expression" printer which conforms to the
1353# "SubPrettyPrinter" protocol from gdb.printing.
1354class RxPrinter(object):
1355 def __init__(self, name, function):
1356 super(RxPrinter, self).__init__()
1357 self.name = name
1358 self.function = function
1359 self.enabled = True
1360
1361 def invoke(self, value):
1362 if not self.enabled:
1363 return None
df1ac917 1364
1365 if value.type.code == gdb.TYPE_CODE_REF:
1366 if hasattr(gdb.Value,"referenced_value"):
1367 value = value.referenced_value()
1368
510f22a9 1369 return self.function(self.name, value)
1370
1371# A pretty-printer that conforms to the "PrettyPrinter" protocol from
1372# gdb.printing. It can also be used directly as an old-style printer.
1373class Printer(object):
1374 def __init__(self, name):
1375 super(Printer, self).__init__()
1376 self.name = name
1377 self.subprinters = []
1378 self.lookup = {}
1379 self.enabled = True
f29d6b5d 1380 self.compiled_rx = re.compile('^([a-zA-Z0-9_:]+)(<.*>)?$')
510f22a9 1381
1382 def add(self, name, function):
1383 # A small sanity check.
1384 # FIXME
f29d6b5d 1385 if not self.compiled_rx.match(name):
3a30bda9 1386 raise ValueError('libstdc++ programming error: "%s" does not match' % name)
510f22a9 1387 printer = RxPrinter(name, function)
1388 self.subprinters.append(printer)
1389 self.lookup[name] = printer
b1986f6e 1390
cd587d4d 1391 # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION.
1392 def add_version(self, base, name, function):
1393 self.add(base + name, function)
d813c3cd 1394 if _versioned_namespace:
c730c800 1395 vbase = re.sub('^(std|__gnu_cxx)::', r'\g<0>%s' % _versioned_namespace, base)
1396 self.add(vbase + name, function)
cd587d4d 1397
1398 # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
1399 def add_container(self, base, name, function):
1400 self.add_version(base, name, function)
1401 self.add_version(base + '__cxx1998::', name, function)
1402
510f22a9 1403 @staticmethod
1404 def get_basic_type(type):
1405 # If it points to a reference, get the reference.
1406 if type.code == gdb.TYPE_CODE_REF:
1407 type = type.target ()
b1986f6e 1408
510f22a9 1409 # Get the unqualified type, stripped of typedefs.
1410 type = type.unqualified ().strip_typedefs ()
b1986f6e 1411
510f22a9 1412 return type.tag
b1986f6e 1413
510f22a9 1414 def __call__(self, val):
1415 typename = self.get_basic_type(val.type)
1416 if not typename:
1417 return None
b1986f6e 1418
510f22a9 1419 # All the types we match are template types, so we can use a
1420 # dictionary.
1421 match = self.compiled_rx.match(typename)
1422 if not match:
1423 return None
b1986f6e 1424
510f22a9 1425 basename = match.group(1)
df1ac917 1426
1427 if val.type.code == gdb.TYPE_CODE_REF:
1428 if hasattr(gdb.Value,"referenced_value"):
1429 val = val.referenced_value()
1430
510f22a9 1431 if basename in self.lookup:
1432 return self.lookup[basename].invoke(val)
b1986f6e 1433
510f22a9 1434 # Cannot find a pretty printer. Return None.
b1986f6e 1435 return None
1436
510f22a9 1437libstdcxx_printer = None
1438
a29af167 1439class TemplateTypePrinter(object):
1dc84a99 1440 r"""
d4f6ff2a 1441 A type printer for class templates with default template arguments.
a29af167 1442
d4f6ff2a 1443 Recognizes specializations of class templates and prints them without
1444 any template arguments that use a default template argument.
1445 Type printers are recursively applied to the template arguments.
a29af167 1446
d4f6ff2a 1447 e.g. replace "std::vector<T, std::allocator<T> >" with "std::vector<T>".
a29af167 1448 """
1449
d4f6ff2a 1450 def __init__(self, name, defargs):
a29af167 1451 self.name = name
d4f6ff2a 1452 self.defargs = defargs
a29af167 1453 self.enabled = True
1454
1455 class _recognizer(object):
d4f6ff2a 1456 "The recognizer class for TemplateTypePrinter."
1457
1458 def __init__(self, name, defargs):
1459 self.name = name
1460 self.defargs = defargs
1461 # self.type_obj = None
a29af167 1462
1463 def recognize(self, type_obj):
d4f6ff2a 1464 """
1465 If type_obj is a specialization of self.name that uses all the
1466 default template arguments for the class template, then return
1467 a string representation of the type without default arguments.
1468 Otherwise, return None.
1469 """
1470
a29af167 1471 if type_obj.tag is None:
1472 return None
1473
d4f6ff2a 1474 if not type_obj.tag.startswith(self.name):
1475 return None
1476
1477 template_args = get_template_arg_list(type_obj)
1478 displayed_args = []
1479 require_defaulted = False
1480 for n in range(len(template_args)):
1481 # The actual template argument in the type:
1482 targ = template_args[n]
1483 # The default template argument for the class template:
1484 defarg = self.defargs.get(n)
1485 if defarg is not None:
1486 # Substitute other template arguments into the default:
1487 defarg = defarg.format(*template_args)
1488 # Fail to recognize the type (by returning None)
1489 # unless the actual argument is the same as the default.
1490 try:
1491 if targ != gdb.lookup_type(defarg):
1492 return None
1493 except gdb.error:
1494 # Type lookup failed, just use string comparison:
1495 if targ.tag != defarg:
1496 return None
1497 # All subsequent args must have defaults:
1498 require_defaulted = True
1499 elif require_defaulted:
1500 return None
1501 else:
1502 # Recursively apply recognizers to the template argument
1503 # and add it to the arguments that will be displayed:
1504 displayed_args.append(self._recognize_subtype(targ))
1505
1506 # This assumes no class templates in the nested-name-specifier:
1507 template_name = type_obj.tag[0:type_obj.tag.find('<')]
1508 template_name = strip_inline_namespaces(template_name)
1509
1510 return template_name + '<' + ', '.join(displayed_args) + '>'
1511
1512 def _recognize_subtype(self, type_obj):
1513 """Convert a gdb.Type to a string by applying recognizers,
1514 or if that fails then simply converting to a string."""
1515
1516 if type_obj.code == gdb.TYPE_CODE_PTR:
1517 return self._recognize_subtype(type_obj.target()) + '*'
1518 if type_obj.code == gdb.TYPE_CODE_ARRAY:
1519 type_str = self._recognize_subtype(type_obj.target())
1520 if str(type_obj.strip_typedefs()).endswith('[]'):
1521 return type_str + '[]' # array of unknown bound
1522 return "%s[%d]" % (type_str, type_obj.range()[1] + 1)
1523 if type_obj.code == gdb.TYPE_CODE_REF:
1524 return self._recognize_subtype(type_obj.target()) + '&'
1525 if hasattr(gdb, 'TYPE_CODE_RVALUE_REF'):
1526 if type_obj.code == gdb.TYPE_CODE_RVALUE_REF:
1527 return self._recognize_subtype(type_obj.target()) + '&&'
1528
1529 type_str = gdb.types.apply_type_recognizers(
1530 gdb.types.get_type_recognizers(), type_obj)
1531 if type_str:
1532 return type_str
1533 return str(type_obj)
a29af167 1534
1535 def instantiate(self):
d4f6ff2a 1536 "Return a recognizer object for this type printer."
1537 return self._recognizer(self.name, self.defargs)
a29af167 1538
d4f6ff2a 1539def add_one_template_type_printer(obj, name, defargs):
1540 r"""
1541 Add a type printer for a class template with default template arguments.
1542
1543 Args:
1544 name (str): The template-name of the class template.
1545 defargs (dict int:string) The default template arguments.
1546
1547 Types in defargs can refer to the Nth template-argument using {N}
1548 (with zero-based indices).
1549
1550 e.g. 'unordered_map' has these defargs:
1551 { 2: 'std::hash<{0}>',
1552 3: 'std::equal_to<{0}>',
1553 4: 'std::allocator<std::pair<const {0}, {1}> >' }
1554
1555 """
1556 printer = TemplateTypePrinter('std::'+name, defargs)
a29af167 1557 gdb.types.register_type_printer(obj, printer)
d813c3cd 1558 if _versioned_namespace:
1559 # Add second type printer for same type in versioned namespace:
d4f6ff2a 1560 ns = 'std::' + _versioned_namespace
63d7b064 1561 # PR 86112 Cannot use dict comprehension here:
1562 defargs = dict((n, d.replace('std::', ns)) for (n,d) in defargs.items())
d4f6ff2a 1563 printer = TemplateTypePrinter(ns+name, defargs)
d813c3cd 1564 gdb.types.register_type_printer(obj, printer)
a29af167 1565
0ed3336a 1566class FilteringTypePrinter(object):
d4f6ff2a 1567 r"""
1568 A type printer that uses typedef names for common template specializations.
1569
1570 Args:
1571 match (str): The class template to recognize.
1572 name (str): The typedef-name that will be used instead.
1573
1574 Checks if a specialization of the class template 'match' is the same type
1575 as the typedef 'name', and prints it as 'name' instead.
1576
1577 e.g. if an instantiation of std::basic_istream<C, T> is the same type as
1578 std::istream then print it as std::istream.
1579 """
1580
0ed3336a 1581 def __init__(self, match, name):
1582 self.match = match
1583 self.name = name
1584 self.enabled = True
1585
1586 class _recognizer(object):
d4f6ff2a 1587 "The recognizer class for TemplateTypePrinter."
1588
0ed3336a 1589 def __init__(self, match, name):
1590 self.match = match
1591 self.name = name
1592 self.type_obj = None
1593
1594 def recognize(self, type_obj):
d4f6ff2a 1595 """
1596 If type_obj starts with self.match and is the same type as
1597 self.name then return self.name, otherwise None.
1598 """
0ed3336a 1599 if type_obj.tag is None:
1600 return None
1601
1602 if self.type_obj is None:
d4f6ff2a 1603 if not type_obj.tag.startswith(self.match):
0ed3336a 1604 # Filter didn't match.
1605 return None
1606 try:
1607 self.type_obj = gdb.lookup_type(self.name).strip_typedefs()
1608 except:
1609 pass
1610 if self.type_obj == type_obj:
d4f6ff2a 1611 return strip_inline_namespaces(self.name)
0ed3336a 1612 return None
1613
1614 def instantiate(self):
d4f6ff2a 1615 "Return a recognizer object for this type printer."
0ed3336a 1616 return self._recognizer(self.match, self.name)
1617
1618def add_one_type_printer(obj, match, name):
d4f6ff2a 1619 printer = FilteringTypePrinter('std::' + match, 'std::' + name)
0ed3336a 1620 gdb.types.register_type_printer(obj, printer)
d813c3cd 1621 if _versioned_namespace:
d4f6ff2a 1622 ns = 'std::' + _versioned_namespace
1623 printer = FilteringTypePrinter(ns + match, ns + name)
d813c3cd 1624 gdb.types.register_type_printer(obj, printer)
0ed3336a 1625
1626def register_type_printers(obj):
1627 global _use_type_printing
1628
1629 if not _use_type_printing:
1630 return
1631
d4f6ff2a 1632 # Add type printers for typedefs std::string, std::wstring etc.
1633 for ch in ('', 'w', 'u16', 'u32'):
1634 add_one_type_printer(obj, 'basic_string', ch + 'string')
6cfbd82f 1635 add_one_type_printer(obj, '__cxx11::basic_string', ch + 'string')
1636 # Typedefs for __cxx11::basic_string used to be in namespace __cxx11:
d4f6ff2a 1637 add_one_type_printer(obj, '__cxx11::basic_string',
1638 '__cxx11::' + ch + 'string')
1639 add_one_type_printer(obj, 'basic_string_view', ch + 'string_view')
1640
1641 # Add type printers for typedefs std::istream, std::wistream etc.
1642 for ch in ('', 'w'):
1643 for x in ('ios', 'streambuf', 'istream', 'ostream', 'iostream',
1644 'filebuf', 'ifstream', 'ofstream', 'fstream'):
1645 add_one_type_printer(obj, 'basic_' + x, ch + x)
1646 for x in ('stringbuf', 'istringstream', 'ostringstream',
1647 'stringstream'):
1648 add_one_type_printer(obj, 'basic_' + x, ch + x)
6cfbd82f 1649 # <sstream> types are in __cxx11 namespace, but typedefs aren't:
d4f6ff2a 1650 add_one_type_printer(obj, '__cxx11::basic_' + x, ch + x)
1651
1652 # Add type printers for typedefs regex, wregex, cmatch, wcmatch etc.
1653 for abi in ('', '__cxx11::'):
1654 for ch in ('', 'w'):
1655 add_one_type_printer(obj, abi + 'basic_regex', abi + ch + 'regex')
1656 for ch in ('c', 's', 'wc', 'ws'):
1657 add_one_type_printer(obj, abi + 'match_results', abi + ch + 'match')
1658 for x in ('sub_match', 'regex_iterator', 'regex_token_iterator'):
1659 add_one_type_printer(obj, abi + x, abi + ch + x)
0ed3336a 1660
1661 # Note that we can't have a printer for std::wstreampos, because
d4f6ff2a 1662 # it is the same type as std::streampos.
0ed3336a 1663 add_one_type_printer(obj, 'fpos', 'streampos')
d813c3cd 1664
d4f6ff2a 1665 # Add type printers for <chrono> typedefs.
0ed3336a 1666 for dur in ('nanoseconds', 'microseconds', 'milliseconds',
1667 'seconds', 'minutes', 'hours'):
1668 add_one_type_printer(obj, 'duration', dur)
1669
d4f6ff2a 1670 # Add type printers for <random> typedefs.
0ed3336a 1671 add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand0')
1672 add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand')
1673 add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937')
1674 add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937_64')
1675 add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux24_base')
1676 add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux48_base')
1677 add_one_type_printer(obj, 'discard_block_engine', 'ranlux24')
1678 add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
1679 add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')
1680
d4f6ff2a 1681 # Add type printers for experimental::basic_string_view typedefs.
1682 ns = 'experimental::fundamentals_v1::'
1683 for ch in ('', 'w', 'u16', 'u32'):
1684 add_one_type_printer(obj, ns + 'basic_string_view',
1685 ns + ch + 'string_view')
1686
1687 # Do not show defaulted template arguments in class templates.
1688 add_one_template_type_printer(obj, 'unique_ptr',
1689 { 1: 'std::default_delete<{0}>' })
1690 add_one_template_type_printer(obj, 'deque', { 1: 'std::allocator<{0}>'})
1691 add_one_template_type_printer(obj, 'forward_list', { 1: 'std::allocator<{0}>'})
1692 add_one_template_type_printer(obj, 'list', { 1: 'std::allocator<{0}>'})
1693 add_one_template_type_printer(obj, '__cxx11::list', { 1: 'std::allocator<{0}>'})
1694 add_one_template_type_printer(obj, 'vector', { 1: 'std::allocator<{0}>'})
1695 add_one_template_type_printer(obj, 'map',
1696 { 2: 'std::less<{0}>',
1697 3: 'std::allocator<std::pair<{0} const, {1}>>' })
1698 add_one_template_type_printer(obj, 'multimap',
1699 { 2: 'std::less<{0}>',
1700 3: 'std::allocator<std::pair<{0} const, {1}>>' })
1701 add_one_template_type_printer(obj, 'set',
1702 { 1: 'std::less<{0}>', 2: 'std::allocator<{0}>' })
1703 add_one_template_type_printer(obj, 'multiset',
1704 { 1: 'std::less<{0}>', 2: 'std::allocator<{0}>' })
1705 add_one_template_type_printer(obj, 'unordered_map',
1706 { 2: 'std::hash<{0}>',
1707 3: 'std::equal_to<{0}>',
1708 4: 'std::allocator<std::pair<{0} const, {1}>>'})
1709 add_one_template_type_printer(obj, 'unordered_multimap',
1710 { 2: 'std::hash<{0}>',
1711 3: 'std::equal_to<{0}>',
1712 4: 'std::allocator<std::pair<{0} const, {1}>>'})
1713 add_one_template_type_printer(obj, 'unordered_set',
1714 { 1: 'std::hash<{0}>',
1715 2: 'std::equal_to<{0}>',
1716 3: 'std::allocator<{0}>'})
1717 add_one_template_type_printer(obj, 'unordered_multiset',
1718 { 1: 'std::hash<{0}>',
1719 2: 'std::equal_to<{0}>',
1720 3: 'std::allocator<{0}>'})
a29af167 1721
510f22a9 1722def register_libstdcxx_printers (obj):
1723 "Register libstdc++ pretty-printers with objfile Obj."
1724
1725 global _use_gdb_pp
1726 global libstdcxx_printer
1727
1728 if _use_gdb_pp:
1729 gdb.printing.register_pretty_printer(obj, libstdcxx_printer)
1730 else:
1731 if obj is None:
1732 obj = gdb
1733 obj.pretty_printers.append(libstdcxx_printer)
b1986f6e 1734
0ed3336a 1735 register_type_printers(obj)
1736
b1986f6e 1737def build_libstdcxx_dictionary ():
510f22a9 1738 global libstdcxx_printer
1739
1740 libstdcxx_printer = Printer("libstdc++-v6")
1741
b1986f6e 1742 # libstdc++ objects requiring pretty-printing.
1743 # In order from:
1744 # http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01847.html
cd587d4d 1745 libstdcxx_printer.add_version('std::', 'basic_string', StdStringPrinter)
c730c800 1746 libstdcxx_printer.add_version('std::__cxx11::', 'basic_string', StdStringPrinter)
cd587d4d 1747 libstdcxx_printer.add_container('std::', 'bitset', StdBitsetPrinter)
1748 libstdcxx_printer.add_container('std::', 'deque', StdDequePrinter)
1749 libstdcxx_printer.add_container('std::', 'list', StdListPrinter)
0a9343a8 1750 libstdcxx_printer.add_container('std::__cxx11::', 'list', StdListPrinter)
cd587d4d 1751 libstdcxx_printer.add_container('std::', 'map', StdMapPrinter)
1752 libstdcxx_printer.add_container('std::', 'multimap', StdMapPrinter)
1753 libstdcxx_printer.add_container('std::', 'multiset', StdSetPrinter)
785c6c31 1754 libstdcxx_printer.add_version('std::', 'pair', StdPairPrinter)
cd587d4d 1755 libstdcxx_printer.add_version('std::', 'priority_queue',
1756 StdStackOrQueuePrinter)
1757 libstdcxx_printer.add_version('std::', 'queue', StdStackOrQueuePrinter)
1758 libstdcxx_printer.add_version('std::', 'tuple', StdTuplePrinter)
1759 libstdcxx_printer.add_container('std::', 'set', StdSetPrinter)
1760 libstdcxx_printer.add_version('std::', 'stack', StdStackOrQueuePrinter)
1761 libstdcxx_printer.add_version('std::', 'unique_ptr', UniquePointerPrinter)
1762 libstdcxx_printer.add_container('std::', 'vector', StdVectorPrinter)
b1986f6e 1763 # vector<bool>
1764
19791f4a 1765 # Printer registrations for classes compiled with -D_GLIBCXX_DEBUG.
510f22a9 1766 libstdcxx_printer.add('std::__debug::bitset', StdBitsetPrinter)
1767 libstdcxx_printer.add('std::__debug::deque', StdDequePrinter)
1768 libstdcxx_printer.add('std::__debug::list', StdListPrinter)
1769 libstdcxx_printer.add('std::__debug::map', StdMapPrinter)
1770 libstdcxx_printer.add('std::__debug::multimap', StdMapPrinter)
1771 libstdcxx_printer.add('std::__debug::multiset', StdSetPrinter)
1772 libstdcxx_printer.add('std::__debug::priority_queue',
1773 StdStackOrQueuePrinter)
1774 libstdcxx_printer.add('std::__debug::queue', StdStackOrQueuePrinter)
1775 libstdcxx_printer.add('std::__debug::set', StdSetPrinter)
1776 libstdcxx_printer.add('std::__debug::stack', StdStackOrQueuePrinter)
1777 libstdcxx_printer.add('std::__debug::unique_ptr', UniquePointerPrinter)
1778 libstdcxx_printer.add('std::__debug::vector', StdVectorPrinter)
19791f4a 1779
e11be3ea 1780 # These are the TR1 and C++11 printers.
b1986f6e 1781 # For array - the default GDB pretty-printer seems reasonable.
6c2e05ff 1782 libstdcxx_printer.add_version('std::', 'shared_ptr', SharedPointerPrinter)
1783 libstdcxx_printer.add_version('std::', 'weak_ptr', SharedPointerPrinter)
cd587d4d 1784 libstdcxx_printer.add_container('std::', 'unordered_map',
1785 Tr1UnorderedMapPrinter)
1786 libstdcxx_printer.add_container('std::', 'unordered_set',
1787 Tr1UnorderedSetPrinter)
1788 libstdcxx_printer.add_container('std::', 'unordered_multimap',
1789 Tr1UnorderedMapPrinter)
1790 libstdcxx_printer.add_container('std::', 'unordered_multiset',
1791 Tr1UnorderedSetPrinter)
1792 libstdcxx_printer.add_container('std::', 'forward_list',
1793 StdForwardListPrinter)
1794
c730c800 1795 libstdcxx_printer.add_version('std::tr1::', 'shared_ptr', SharedPointerPrinter)
1796 libstdcxx_printer.add_version('std::tr1::', 'weak_ptr', SharedPointerPrinter)
1797 libstdcxx_printer.add_version('std::tr1::', 'unordered_map',
cd587d4d 1798 Tr1UnorderedMapPrinter)
c730c800 1799 libstdcxx_printer.add_version('std::tr1::', 'unordered_set',
cd587d4d 1800 Tr1UnorderedSetPrinter)
c730c800 1801 libstdcxx_printer.add_version('std::tr1::', 'unordered_multimap',
cd587d4d 1802 Tr1UnorderedMapPrinter)
c730c800 1803 libstdcxx_printer.add_version('std::tr1::', 'unordered_multiset',
cd587d4d 1804 Tr1UnorderedSetPrinter)
b1986f6e 1805
e11be3ea 1806 # These are the C++11 printer registrations for -D_GLIBCXX_DEBUG cases.
cbd50187 1807 # The tr1 namespace containers do not have any debug equivalents,
1808 # so do not register printers for them.
510f22a9 1809 libstdcxx_printer.add('std::__debug::unordered_map',
1810 Tr1UnorderedMapPrinter)
1811 libstdcxx_printer.add('std::__debug::unordered_set',
1812 Tr1UnorderedSetPrinter)
1813 libstdcxx_printer.add('std::__debug::unordered_multimap',
1814 Tr1UnorderedMapPrinter)
1815 libstdcxx_printer.add('std::__debug::unordered_multiset',
1816 Tr1UnorderedSetPrinter)
3c80034b 1817 libstdcxx_printer.add('std::__debug::forward_list',
1818 StdForwardListPrinter)
19791f4a 1819
f29d6b5d 1820 # Library Fundamentals TS components
1821 libstdcxx_printer.add_version('std::experimental::fundamentals_v1::',
1822 'any', StdExpAnyPrinter)
1823 libstdcxx_printer.add_version('std::experimental::fundamentals_v1::',
1824 'optional', StdExpOptionalPrinter)
1825 libstdcxx_printer.add_version('std::experimental::fundamentals_v1::',
1826 'basic_string_view', StdExpStringViewPrinter)
5924b28e 1827 # Filesystem TS components
1828 libstdcxx_printer.add_version('std::experimental::filesystem::v1::',
1829 'path', StdExpPathPrinter)
d1eff9de 1830 libstdcxx_printer.add_version('std::experimental::filesystem::v1::__cxx11::',
5924b28e 1831 'path', StdExpPathPrinter)
3b90ed62 1832 libstdcxx_printer.add_version('std::filesystem::',
6bec006a 1833 'path', StdPathPrinter)
3b90ed62 1834 libstdcxx_printer.add_version('std::filesystem::__cxx11::',
6bec006a 1835 'path', StdPathPrinter)
b1986f6e 1836
e11be3ea 1837 # C++17 components
1838 libstdcxx_printer.add_version('std::',
1839 'any', StdExpAnyPrinter)
1840 libstdcxx_printer.add_version('std::',
1841 'optional', StdExpOptionalPrinter)
1842 libstdcxx_printer.add_version('std::',
1843 'basic_string_view', StdExpStringViewPrinter)
1844 libstdcxx_printer.add_version('std::',
1845 'variant', StdVariantPrinter)
67218f06 1846 libstdcxx_printer.add_version('std::',
1847 '_Node_handle', StdNodeHandlePrinter)
e11be3ea 1848
b1986f6e 1849 # Extensions.
cd587d4d 1850 libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter)
b1986f6e 1851
1852 if True:
1853 # These shouldn't be necessary, if GDB "print *i" worked.
1854 # But it often doesn't, so here they are.
cd587d4d 1855 libstdcxx_printer.add_container('std::', '_List_iterator',
1856 StdListIteratorPrinter)
1857 libstdcxx_printer.add_container('std::', '_List_const_iterator',
1858 StdListIteratorPrinter)
1859 libstdcxx_printer.add_version('std::', '_Rb_tree_iterator',
1860 StdRbtreeIteratorPrinter)
1861 libstdcxx_printer.add_version('std::', '_Rb_tree_const_iterator',
1862 StdRbtreeIteratorPrinter)
1863 libstdcxx_printer.add_container('std::', '_Deque_iterator',
1864 StdDequeIteratorPrinter)
1865 libstdcxx_printer.add_container('std::', '_Deque_const_iterator',
1866 StdDequeIteratorPrinter)
1867 libstdcxx_printer.add_version('__gnu_cxx::', '__normal_iterator',
1868 StdVectorIteratorPrinter)
1869 libstdcxx_printer.add_version('__gnu_cxx::', '_Slist_iterator',
1870 StdSlistIteratorPrinter)
8c1baff7 1871 libstdcxx_printer.add_container('std::', '_Fwd_list_iterator',
1872 StdFwdListIteratorPrinter)
1873 libstdcxx_printer.add_container('std::', '_Fwd_list_const_iterator',
1874 StdFwdListIteratorPrinter)
510f22a9 1875
1876 # Debug (compiled with -D_GLIBCXX_DEBUG) printer
db4f7f88 1877 # registrations.
510f22a9 1878 libstdcxx_printer.add('__gnu_debug::_Safe_iterator',
1879 StdDebugIteratorPrinter)
b1986f6e 1880
1881build_libstdcxx_dictionary ()