Skip to content

Commit 39792aa

Browse files
committed
[libc++] Fix mi-mode in GDB pretty printers
GDB/MI requires unique names for each child, otherwise fails with "Duplicate variable object name". Additionally wrapped containers printers were flattened for cleaner visualization in IDEs and CLI. Fixes #62340
1 parent 4b35dd5 commit 39792aa

File tree

1 file changed

+24
-17
lines changed

1 file changed

+24
-17
lines changed

libcxx/utils/gdb/libcxx/printers.py

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -446,10 +446,13 @@ def _list_it(self):
446446
num_emitted = 0
447447
current_addr = self.start_ptr
448448
start_index = self.first_block_start_index
449+
i = 0
449450
while num_emitted < self.size:
450451
end_index = min(start_index + self.size - num_emitted, self.block_size)
451452
for _, elem in self._bucket_it(current_addr, start_index, end_index):
452-
yield "", elem
453+
key_name = "[%d]" % i
454+
i += 1
455+
yield key_name, elem
453456
num_emitted += end_index - start_index
454457
current_addr = gdb.Value(addr_as_long(current_addr) + _pointer_size).cast(
455458
self.node_type
@@ -494,8 +497,8 @@ def to_string(self):
494497

495498
def _list_iter(self):
496499
current_node = self.first_node
497-
for _ in range(self.size):
498-
yield "", current_node.cast(self.nodetype).dereference()["__value_"]
500+
for i in range(self.size):
501+
yield "[%d]" % i, current_node.cast(self.nodetype).dereference()["__value_"]
499502
current_node = current_node.dereference()["__next_"]
500503

501504
def __iter__(self):
@@ -512,15 +515,14 @@ class StdQueueOrStackPrinter(object):
512515
"""Print a std::queue or std::stack."""
513516

514517
def __init__(self, val):
515-
self.val = val
516-
self.underlying = val["c"]
518+
self.typename = _remove_generics(_prettify_typename(val.type))
519+
self.visualizer = gdb.default_visualizer(val["c"])
517520

518521
def to_string(self):
519-
typename = _remove_generics(_prettify_typename(self.val.type))
520-
return "%s wrapping" % typename
522+
return "%s wrapping: %s" % (self.typename, self.visualizer.to_string())
521523

522524
def children(self):
523-
return iter([("", self.underlying)])
525+
return self.visualizer.children()
524526

525527
def display_hint(self):
526528
return "array"
@@ -530,19 +532,18 @@ class StdPriorityQueuePrinter(object):
530532
"""Print a std::priority_queue."""
531533

532534
def __init__(self, val):
533-
self.val = val
534-
self.underlying = val["c"]
535+
self.typename = _remove_generics(_prettify_typename(val.type))
536+
self.visualizer = gdb.default_visualizer(val["c"])
535537

536538
def to_string(self):
537539
# TODO(tamur): It would be nice to print the top element. The technical
538540
# difficulty is that, the implementation refers to the underlying
539541
# container, which is a generic class. libstdcxx pretty printers do not
540542
# print the top element.
541-
typename = _remove_generics(_prettify_typename(self.val.type))
542-
return "%s wrapping" % typename
543+
return "%s wrapping: %s" % (self.typename, self.visualizer.to_string())
543544

544545
def children(self):
545-
return iter([("", self.underlying)])
546+
return self.visualizer.children()
546547

547548
def display_hint(self):
548549
return "array"
@@ -622,13 +623,16 @@ def _traverse(self):
622623
"""Traverses the binary search tree in order."""
623624
current = self.util.root
624625
skip_left_child = False
626+
i = 0
625627
while True:
626628
if not skip_left_child and self.util.left_child(current):
627629
current = self.util.left_child(current)
628630
continue
629631
skip_left_child = False
630632
for key_value in self._get_key_value(current):
631-
yield "", key_value
633+
key_name = "[%d]" % i
634+
i += 1
635+
yield key_name, key_value
632636
right_child = self.util.right_child(current)
633637
if right_child:
634638
current = right_child
@@ -784,10 +788,13 @@ def __init__(self, val):
784788

785789
def _list_it(self, sentinel_ptr):
786790
next_ptr = sentinel_ptr["__next_"]
791+
i = 0
787792
while str(next_ptr.cast(_void_pointer_type)) != "0x0":
788793
next_val = next_ptr.cast(self.cast_type).dereference()
789794
for key_value in self._get_key_value(next_val):
790-
yield "", key_value
795+
key_name = "[%d]" % i
796+
i += 1
797+
yield key_name, key_value
791798
next_ptr = next_val["__next_"]
792799

793800
def to_string(self):
@@ -851,8 +858,8 @@ def children(self):
851858
return self if self.addr else iter(())
852859

853860
def __iter__(self):
854-
for key_value in self._get_key_value():
855-
yield "", key_value
861+
for i, key_value in enumerate(self._get_key_value()):
862+
yield "[%d]" % i, key_value
856863

857864

858865
class StdUnorderedSetIteratorPrinter(AbstractHashMapIteratorPrinter):

0 commit comments

Comments
 (0)