Skip to content

Conversation

@AngryLoki
Copy link
Contributor

@AngryLoki AngryLoki commented Dec 23, 2024

GDB/MI requires unique names for each child, otherwise fails with "Duplicate variable object name".
Also wrapped containers printers were flattened for cleaner visualization in IDEs and CLI.

Fixes #62340

This is the final result from vscode perspective:

Before After
image image

@AngryLoki AngryLoki requested a review from a team as a code owner December 23, 2024 09:17
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Dec 23, 2024
@llvmbot
Copy link
Member

llvmbot commented Dec 23, 2024

@llvm/pr-subscribers-libcxx

Author: Sv. Lockal (AngryLoki)

Changes

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

This is the final result from vscode perspective:

Before After
<img width="400" alt="image" src="https://github.com/user-attachments/assets/963ddc08-1375-406d-b2de-d4920598637d" /> <img width="400" alt="image" src="https://github.com/user-attachments/assets/be93fd53-d23c-4321-a579-7de04bba4b5c" />

Full diff: https://github.com/llvm/llvm-project/pull/120951.diff

1 Files Affected:

  • (modified) libcxx/utils/gdb/libcxx/printers.py (+24-17)
diff --git a/libcxx/utils/gdb/libcxx/printers.py b/libcxx/utils/gdb/libcxx/printers.py
index 8e74b93e7b121f..77736f4722d067 100644
--- a/libcxx/utils/gdb/libcxx/printers.py
+++ b/libcxx/utils/gdb/libcxx/printers.py
@@ -446,10 +446,13 @@ def _list_it(self):
         num_emitted = 0
         current_addr = self.start_ptr
         start_index = self.first_block_start_index
+        i = 0
         while num_emitted < self.size:
             end_index = min(start_index + self.size - num_emitted, self.block_size)
             for _, elem in self._bucket_it(current_addr, start_index, end_index):
-                yield "", elem
+                key_name = "[%d]" % i
+                i += 1
+                yield key_name, elem
             num_emitted += end_index - start_index
             current_addr = gdb.Value(addr_as_long(current_addr) + _pointer_size).cast(
                 self.node_type
@@ -494,8 +497,8 @@ def to_string(self):
 
     def _list_iter(self):
         current_node = self.first_node
-        for _ in range(self.size):
-            yield "", current_node.cast(self.nodetype).dereference()["__value_"]
+        for i in range(self.size):
+            yield "[%d]" % i, current_node.cast(self.nodetype).dereference()["__value_"]
             current_node = current_node.dereference()["__next_"]
 
     def __iter__(self):
@@ -512,15 +515,14 @@ class StdQueueOrStackPrinter(object):
     """Print a std::queue or std::stack."""
 
     def __init__(self, val):
-        self.val = val
-        self.underlying = val["c"]
+        self.typename = _remove_generics(_prettify_typename(val.type))
+        self.visualizer = gdb.default_visualizer(val['c'])
 
     def to_string(self):
-        typename = _remove_generics(_prettify_typename(self.val.type))
-        return "%s wrapping" % typename
+        return "%s wrapping: %s" % (self.typename, self.visualizer.to_string())
 
     def children(self):
-        return iter([("", self.underlying)])
+        return self.visualizer.children()
 
     def display_hint(self):
         return "array"
@@ -530,19 +532,18 @@ class StdPriorityQueuePrinter(object):
     """Print a std::priority_queue."""
 
     def __init__(self, val):
-        self.val = val
-        self.underlying = val["c"]
+        self.typename = _remove_generics(_prettify_typename(val.type))
+        self.visualizer = gdb.default_visualizer(val['c'])
 
     def to_string(self):
         # TODO(tamur): It would be nice to print the top element. The technical
         # difficulty is that, the implementation refers to the underlying
         # container, which is a generic class. libstdcxx pretty printers do not
         # print the top element.
-        typename = _remove_generics(_prettify_typename(self.val.type))
-        return "%s wrapping" % typename
+        return "%s wrapping: %s" % (self.typename, self.visualizer.to_string())
 
     def children(self):
-        return iter([("", self.underlying)])
+        return self.visualizer.children()
 
     def display_hint(self):
         return "array"
@@ -622,13 +623,16 @@ def _traverse(self):
         """Traverses the binary search tree in order."""
         current = self.util.root
         skip_left_child = False
+        i = 0
         while True:
             if not skip_left_child and self.util.left_child(current):
                 current = self.util.left_child(current)
                 continue
             skip_left_child = False
             for key_value in self._get_key_value(current):
-                yield "", key_value
+                key_name = "[%d]" % i
+                i += 1
+                yield key_name, key_value
             right_child = self.util.right_child(current)
             if right_child:
                 current = right_child
@@ -784,10 +788,13 @@ def __init__(self, val):
 
     def _list_it(self, sentinel_ptr):
         next_ptr = sentinel_ptr["__next_"]
+        i = 0
         while str(next_ptr.cast(_void_pointer_type)) != "0x0":
             next_val = next_ptr.cast(self.cast_type).dereference()
             for key_value in self._get_key_value(next_val):
-                yield "", key_value
+                key_name = "[%d]" % i
+                i += 1
+                yield key_name, key_value
             next_ptr = next_val["__next_"]
 
     def to_string(self):
@@ -851,8 +858,8 @@ def children(self):
         return self if self.addr else iter(())
 
     def __iter__(self):
-        for key_value in self._get_key_value():
-            yield "", key_value
+        for i, key_value in enumerate(self._get_key_value()):
+            yield "[%d]" % i, key_value
 
 
 class StdUnorderedSetIteratorPrinter(AbstractHashMapIteratorPrinter):

@github-actions
Copy link

github-actions bot commented Dec 23, 2024

✅ With the latest revision this PR passed the Python code formatter.

@AngryLoki AngryLoki force-pushed the mi-printers branch 2 times, most recently from 39792aa to 125138b Compare December 23, 2024 14:44
@github-actions
Copy link

github-actions bot commented Dec 23, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

GDB/MI requires unique names for each child, otherwise fails with "Duplicate variable object name".
Also wrapped containers printers were flattened for cleaner visualization in IDEs and CLI.

Fixes llvm#62340
@ldionne ldionne merged commit 473510a into llvm:main Jan 9, 2025
62 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[libc++] Pretty printing not working for some containers in GDB's MI mode and IDEs

3 participants