Skip to content

Commit b7722fb

Browse files
authored
[lldb] Fix std::unordered_* synthetic children when typedefs are used. (#123125)
There was a bug in both the GNU and libc++ library synthetic child providers when a typedef was used in the type of the variable. Previous code was looking at the top level typename to try and determine if std::unordered_ was a map or set and this failed when typedefs were being used. This patch fixes both C++ library synthetic child providers with updated tests.
1 parent 319c119 commit b7722fb

File tree

4 files changed

+28
-23
lines changed

4 files changed

+28
-23
lines changed

lldb/examples/synthetic/gnu_libstdcpp.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,11 @@ class StdUnorderedMapSynthProvider:
6161
def __init__(self, valobj, dict):
6262
self.valobj = valobj
6363
self.count = None
64-
self.kind = self.get_object_kind(valobj)
65-
66-
def get_object_kind(self, valobj):
67-
type_name = valobj.GetTypeName()
68-
return "set" if "set" in type_name else "map"
6964

7065
def extract_type(self):
7166
type = self.valobj.GetType()
72-
# type of std::pair<key, value> is the first template
73-
# argument type of the 4th template argument to std::map and
74-
# 3rd template argument for std::set. That's why
75-
# we need to know kind of the object
76-
template_arg_num = 4 if self.kind == "map" else 3
67+
# The last template argument is the allocator type.
68+
template_arg_num = type.GetNumberOfTemplateArguments() - 1
7769
allocator_type = type.GetTemplateArgumentType(template_arg_num)
7870
data_type = allocator_type.GetTemplateArgumentType(0)
7971
return data_type

lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ CompilerType lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
111111
// that wraps a std::pair. Peel away the internal wrapper type - whose
112112
// structure is of no value to users, to expose the std::pair. This
113113
// matches the structure returned by the std::map synthetic provider.
114-
if (isUnorderedMap(m_backend.GetTypeName())) {
114+
if (isUnorderedMap(
115+
m_backend.GetCompilerType().GetCanonicalType().GetTypeName())) {
115116
std::string name;
116117
CompilerType field_type =
117118
element_type.GetFieldAtIndex(0, name, nullptr, nullptr, nullptr);

lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/TestDataFormatterGenericUnordered.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def cleanup():
5454
self.look_for_content_and_continue(
5555
"map",
5656
[
57-
"%s::unordered_map" % ns,
57+
"UnorderedMap",
5858
children_are_key_value,
5959
"size=5 {",
6060
"hello",
@@ -68,7 +68,7 @@ def cleanup():
6868
self.look_for_content_and_continue(
6969
"mmap",
7070
[
71-
"%s::unordered_multimap" % ns,
71+
"UnorderedMultiMap",
7272
children_are_key_value,
7373
"size=6 {",
7474
"first = 3",
@@ -81,7 +81,7 @@ def cleanup():
8181
self.look_for_content_and_continue(
8282
"iset",
8383
[
84-
"%s::unordered_set" % ns,
84+
"IntsUnorderedSet",
8585
"size=5 {",
8686
"\[\d\] = 5",
8787
"\[\d\] = 3",
@@ -92,7 +92,7 @@ def cleanup():
9292
self.look_for_content_and_continue(
9393
"sset",
9494
[
95-
"%s::unordered_set" % ns,
95+
"StringsUnorderedSet",
9696
"size=5 {",
9797
'\[\d\] = "is"',
9898
'\[\d\] = "world"',
@@ -103,7 +103,7 @@ def cleanup():
103103
self.look_for_content_and_continue(
104104
"imset",
105105
[
106-
"%s::unordered_multiset" % ns,
106+
"IntsUnorderedMultiSet",
107107
"size=6 {",
108108
"(\[\d\] = 3(\\n|.)+){3}",
109109
"\[\d\] = 2",
@@ -114,7 +114,7 @@ def cleanup():
114114
self.look_for_content_and_continue(
115115
"smset",
116116
[
117-
"%s::unordered_multiset" % ns,
117+
"StringsUnorderedMultiSet",
118118
"size=5 {",
119119
'(\[\d\] = "is"(\\n|.)+){2}',
120120
'(\[\d\] = "world"(\\n|.)+){2}',

lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/main.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,19 @@ int main() {
1818
char buffer[sizeof(std::unordered_map<int, std::string>)] = {0};
1919
std::unordered_map<int, std::string> &corrupt_map = *(std::unordered_map<int, std::string> *)buffer;
2020

21-
std::unordered_map<int, std::string> map; // Set break point at this line.
21+
// Make a typedef to ensure functionality when typedefs are used.
22+
typedef std::unordered_map<int, std::string> UnorderedMap;
23+
UnorderedMap map; // Set break point at this line.
2224
map.emplace(1, "hello");
2325
map.emplace(2, "world");
2426
map.emplace(3, "this");
2527
map.emplace(4, "is");
2628
map.emplace(5, "me");
2729
thefoo_rw(); // Set break point at this line.
2830

29-
std::unordered_multimap<int, std::string> mmap;
31+
// Make a typedef to ensure functionality when typedefs are used.
32+
typedef std::unordered_multimap<int, std::string> UnorderedMultiMap;
33+
UnorderedMultiMap mmap;
3034
mmap.emplace(1, "hello");
3135
mmap.emplace(2, "hello");
3236
mmap.emplace(2, "world");
@@ -35,23 +39,29 @@ int main() {
3539
mmap.emplace(3, "this");
3640
thefoo_rw(); // Set break point at this line.
3741

38-
std::unordered_set<int> iset;
42+
// Make a typedef to ensure functionality when typedefs are used.
43+
typedef std::unordered_set<int> IntsUnorderedSet;
44+
IntsUnorderedSet iset;
3945
iset.emplace(1);
4046
iset.emplace(2);
4147
iset.emplace(3);
4248
iset.emplace(4);
4349
iset.emplace(5);
4450
thefoo_rw(); // Set break point at this line.
4551

46-
std::unordered_set<std::string> sset;
52+
// Make a typedef to ensure functionality when typedefs are used.
53+
typedef std::unordered_set<std::string> StringsUnorderedSet;
54+
StringsUnorderedSet sset;
4755
sset.emplace("hello");
4856
sset.emplace("world");
4957
sset.emplace("this");
5058
sset.emplace("is");
5159
sset.emplace("me");
5260
thefoo_rw(); // Set break point at this line.
5361

54-
std::unordered_multiset<int> imset;
62+
// Make a typedef to ensure functionality when typedefs are used.
63+
typedef std::unordered_multiset<int> IntsUnorderedMultiSet;
64+
IntsUnorderedMultiSet imset;
5565
imset.emplace(1);
5666
imset.emplace(2);
5767
imset.emplace(2);
@@ -60,7 +70,9 @@ int main() {
6070
imset.emplace(3);
6171
thefoo_rw(); // Set break point at this line.
6272

63-
std::unordered_multiset<std::string> smset;
73+
// Make a typedef to ensure functionality when typedefs are used.
74+
typedef std::unordered_multiset<std::string> StringsUnorderedMultiSet;
75+
StringsUnorderedMultiSet smset;
6476
smset.emplace("hello");
6577
smset.emplace("world");
6678
smset.emplace("world");

0 commit comments

Comments
 (0)