From bb9da7a0edc60991e14b7e8c738e5d8ae3661512 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Thu, 8 Oct 2020 22:15:18 +0200 Subject: [PATCH] BTreeMap: fix gdb introspection of BTreeMap with ZST keys or values --- src/etc/gdb_providers.py | 63 ++++++++++---------- src/test/debuginfo/pretty-std-collections.rs | 16 +++-- 2 files changed, 43 insertions(+), 36 deletions(-) diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index bae51e6f9ee93..b2d343fd7af6a 100644 --- a/src/etc/gdb_providers.py +++ b/src/etc/gdb_providers.py @@ -207,30 +207,46 @@ def children(self): yield "borrow", self.borrow -# Yield each key (and optionally value) from a BoxedNode. -def children_of_node(boxed_node, height, want_values): +# Yields children (in a provider's sense of the word) for a tree headed by a BoxedNode. +# In particular, yields each key/value pair in the node and in any child nodes. +def children_of_node(boxed_node, height): def cast_to_internal(node): - internal_type_name = str(node.type.target()).replace("LeafNode", "InternalNode", 1) + internal_type_name = node.type.target().name.replace("LeafNode", "InternalNode", 1) internal_type = lookup_type(internal_type_name) return node.cast(internal_type.pointer()) node_ptr = unwrap_unique_or_non_null(boxed_node["ptr"]) - node_ptr = cast_to_internal(node_ptr) if height > 0 else node_ptr - leaf = node_ptr["data"] if height > 0 else node_ptr.dereference() + leaf = node_ptr.dereference() keys = leaf["keys"] - values = leaf["vals"] + vals = leaf["vals"] + edges = cast_to_internal(node_ptr)["edges"] if height > 0 else None length = int(leaf["len"]) for i in xrange(0, length + 1): if height > 0: - child_ptr = node_ptr["edges"][i]["value"]["value"] - for child in children_of_node(child_ptr, height - 1, want_values): + boxed_child_node = edges[i]["value"]["value"] + for child in children_of_node(boxed_child_node, height - 1): yield child if i < length: - if want_values: - yield keys[i]["value"]["value"], values[i]["value"]["value"] - else: - yield keys[i]["value"]["value"] + # Avoid "Cannot perform pointer math on incomplete type" on zero-sized arrays. + key = keys[i]["value"]["value"] if keys.type.sizeof > 0 else None + val = vals[i]["value"]["value"] if vals.type.sizeof > 0 else None + yield key, val + + +# Yields children for a BTreeMap. +def children_of_map(map): + if map["length"] > 0: + root = map["root"] + if root.type.name.startswith("core::option::Option<"): + root = root.cast(gdb.lookup_type(root.type.name[21:-1])) + boxed_root_node = root["node"] + height = root["height"] + for i, (key, val) in enumerate(children_of_node(boxed_root_node, height)): + if key is not None: + yield "key{}".format(i), key + if val is not None: + yield "val{}".format(i), val class StdBTreeSetProvider: @@ -242,15 +258,8 @@ def to_string(self): def children(self): inner_map = self.valobj["map"] - if inner_map["length"] > 0: - root = inner_map["root"] - if "core::option::Option<" in root.type.name: - type_name = str(root.type.name).replace("core::option::Option<", "", 1)[:-1] - root = root.cast(gdb.lookup_type(type_name)) - - node_ptr = root["node"] - for i, child in enumerate(children_of_node(node_ptr, root["height"], False)): - yield "[{}]".format(i), child + for child in children_of_map(inner_map): + yield child @staticmethod def display_hint(): @@ -265,16 +274,8 @@ def to_string(self): return "BTreeMap(size={})".format(self.valobj["length"]) def children(self): - if self.valobj["length"] > 0: - root = self.valobj["root"] - if "core::option::Option<" in root.type.name: - type_name = str(root.type.name).replace("core::option::Option<", "", 1)[:-1] - root = root.cast(gdb.lookup_type(type_name)) - - node_ptr = root["node"] - for i, child in enumerate(children_of_node(node_ptr, root["height"], True)): - yield "key{}".format(i), child[0] - yield "val{}".format(i), child[1] + for child in children_of_map(self.valobj): + yield child @staticmethod def display_hint(): diff --git a/src/test/debuginfo/pretty-std-collections.rs b/src/test/debuginfo/pretty-std-collections.rs index a4fbff5725c97..c6d2090759ff2 100644 --- a/src/test/debuginfo/pretty-std-collections.rs +++ b/src/test/debuginfo/pretty-std-collections.rs @@ -34,17 +34,20 @@ // gdb-check:$6 = BTreeMap(size=15) = {[0] = pretty_std_collections::MyLeafNode (0), [...]} // (abbreviated because it's boring but we need enough elements to include internal nodes) +// gdb-command: print zst_btree_map +// gdb-check:$7 = BTreeMap(size=1) + // gdb-command: print vec_deque -// gdb-check:$7 = VecDeque(size=3) = {5, 3, 7} +// gdb-check:$8 = VecDeque(size=3) = {5, 3, 7} // gdb-command: print vec_deque2 -// gdb-check:$8 = VecDeque(size=7) = {2, 3, 4, 5, 6, 7, 8} +// gdb-check:$9 = VecDeque(size=7) = {2, 3, 4, 5, 6, 7, 8} // gdb-command: print hash_map -// gdb-check:$9 = HashMap(size=4) = {[1] = 10, [2] = 20, [3] = 30, [4] = 40} +// gdb-check:$10 = HashMap(size=4) = {[1] = 10, [2] = 20, [3] = 30, [4] = 40} // gdb-command: print hash_set -// gdb-check:$10 = HashSet(size=4) = {1, 2, 3, 4} +// gdb-check:$11 = HashSet(size=4) = {1, 2, 3, 4} // === LLDB TESTS ================================================================================== @@ -69,9 +72,9 @@ #![allow(unused_variables)] use std::collections::BTreeMap; use std::collections::BTreeSet; -use std::collections::VecDeque; use std::collections::HashMap; use std::collections::HashSet; +use std::collections::VecDeque; use std::hash::{BuildHasherDefault, Hasher}; struct MyLeafNode(i32); // helps to ensure we don't blindly replace substring "LeafNode" @@ -111,6 +114,9 @@ fn main() { nasty_btree_map.insert(i, MyLeafNode(i)); } + let mut zst_btree_map: BTreeMap<(), ()> = BTreeMap::new(); + zst_btree_map.insert((), ()); + // VecDeque let mut vec_deque = VecDeque::new(); vec_deque.push_back(5);