This diff adds a data formatter and tests for libstdcpp's unordered_map, unordered_set, unordered_multimap, unordered_multiset
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Hi Walter :) This is the Draft PR for the unordered_map/set data formatter. Currently it works well in case both key and values are of the same primitive data types (except string).
Unfortunately, the following problems are encountered:
- When key and value are of different types value is detected wrong (some garbage). I will leave the separate comment with the details
- Currently I print the unordered_map in the following form [key] = [value]. However, the right from would be: [index] = (first = key, second = value). I am struggling through finding the way to do so
- Whether key and/or value are of the string type, formatter cannot read the data. Is the string formatter issue.
Many thanks for your help in advance
lldb/examples/synthetic/gnu_libstdcpp.py | ||
---|---|---|
77 | I assume that the cause of the first issue (different key value type) is located here. self.next.GetType().GetByteSize() + self.data_size does not work in this case. Key is read, however value - not. It means that we cannot always add self.data_size. I tried to manually figure out on the unordered_map<char, int> case what can I add instead of self.data_size (which is 1 in this case), but got no success |
When you do your tests, don't care too much about std::string yet, as it has its own issues, but instead create a non-standard size type like
struct Foo { int a; int b; int c; }; ... std::unordered_map<int, Foo> u;
lldb/examples/synthetic/gnu_libstdcpp.py | ||
---|---|---|
16–24 | you can simplify this | |
18 | you are already passing stl_deref_flags when you declare this formatter in C++, so you shouldn't get a Reference type here | |
21 | GetTemplateArgumentType(0) will give you the key, and GetTemplateArgumentType(1) should give you the value type. The idea is that in this place you get both key_type and value_type, so that you don't need to figure them out later | |
44 | remove if not used | |
55 | this looks weird. you are already doing a while loop in get_child_at_index that is taking you to the node you want, but you do again another loop. You have to use current instead. My suggestion is to remove this function and make everything happen in get_child_at_index with one single loop | |
71 | why do you do this? that means that you are traversing backwards. Just move an 'index' number of times. The unordered map is unordered by definition | |
77 | do what i mentioned above regarding fetching the key and value types. I imagine that the internal allocator is using a pair<key, value>, which means that the memory layout will be: key value [with an offset of key size] | |
77 | here you are returning a child of type self.data_type, which is the key type. And we don't want that. We want to do the same thing that the map formatter does for getting the pair<key, value> and returning it: https://github.com/llvm-mirror/lldb/blob/master/examples/synthetic/gnu_libstdcpp.py#L366 that means that you don't need to individually find the key and the value, you only need to find the pair and return the pair Btw, if raw print an unordered_map, I get this: (std::unordered_map<int, double, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<const int, double> > >) that means that the fifth template argument contains the pair. I've confirmed that also libcxx works the same way |
Hi Walter,
Thank you for the hints. Everything works now, including the string case. There was a small difficulty with set case, but then I figured out that for set case I need to take not the 5th, but 4th template argument. I will be waiting for your comments. After this I will unify the tests across platforms. Thank you!
just some minor changes.
Could you unify these tests with libcxx?
lldb/examples/synthetic/gnu_libstdcpp.py | ||
---|---|---|
10 | add a few empty lines before this to avoid confusing that comment with this specific formatter. Besides that, rename this to StdUnorderedMapLikeSynthProvider and add a comment similar to """ This formatter can be applied to all unordered map-like structures (unordered_map, unordered_multimap, unordered_set, unordered_multiset) """ | |
25 | an exception is too much. Normally we just fail silently, as it obvious to the user when the formatter fails and investigation is needed. Just return "map" if "set" is not present in the type name. | |
29 | this comment
should be here | |
32 | if we used something that is not a map or set, this data type will be a dummy object that won't fail but won't do anything useful | |
46 | you see? we fail silently by default | |
83 | remove this comment, as this information is easily available to the user | |
86 | this one is fine | |
lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/unordered/main.cpp | ||
5 ↗ | (On Diff #387084) | also remove this, you barely save a few characters by not typing std::string |
7–13 ↗ | (On Diff #387084) | avoid using these defines, they just obscure the code when reading |
lldb/examples/synthetic/gnu_libstdcpp.py | ||
---|---|---|
110–115 |
add a few empty lines before this to avoid confusing that comment with this specific formatter. Besides that, rename this to StdUnorderedMapLikeSynthProvider and add a comment similar to