Skip to content

Commit cb72aec

Browse files
authored
[lldb][DataFormatter] Move std::unordered_map::iterator formatter into LibCxxUnorderedMap.cpp (#97752)
Similar to how we moved the `std::map::iterator` formatter in #97687, do the same for `std::unordered_map::iterator`. Again the `unordered_map` and `unordered_map::iterator` formatters try to do very similar things: retrieve data out of the map. The iterator formatter does this in a fragile way (similar to how `std::map` does it, see #97579). Thus we will be refactoring the `std::unordered_map::iterator` in upcoming patches. Having it in `LibCxxUnorderedMap` will allow us to re-use some of the logic (and we won't have to repeat some of the clarification comments).
1 parent 1e6dfc6 commit cb72aec

File tree

3 files changed

+200
-199
lines changed

3 files changed

+200
-199
lines changed

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

Lines changed: 0 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -202,155 +202,6 @@ bool lldb_private::formatters::LibcxxUniquePointerSummaryProvider(
202202
return true;
203203
}
204204

205-
lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
206-
LibCxxUnorderedMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
207-
: SyntheticChildrenFrontEnd(*valobj_sp) {
208-
if (valobj_sp)
209-
Update();
210-
}
211-
212-
lldb::ChildCacheState lldb_private::formatters::
213-
LibCxxUnorderedMapIteratorSyntheticFrontEnd::Update() {
214-
m_pair_sp.reset();
215-
m_iter_ptr = nullptr;
216-
217-
ValueObjectSP valobj_sp = m_backend.GetSP();
218-
if (!valobj_sp)
219-
return lldb::ChildCacheState::eRefetch;
220-
221-
TargetSP target_sp(valobj_sp->GetTargetSP());
222-
223-
if (!target_sp)
224-
return lldb::ChildCacheState::eRefetch;
225-
226-
if (!valobj_sp)
227-
return lldb::ChildCacheState::eRefetch;
228-
229-
auto exprPathOptions = ValueObject::GetValueForExpressionPathOptions()
230-
.DontCheckDotVsArrowSyntax()
231-
.SetSyntheticChildrenTraversal(
232-
ValueObject::GetValueForExpressionPathOptions::
233-
SyntheticChildrenTraversal::None);
234-
235-
// This must be a ValueObject* because it is a child of the ValueObject we
236-
// are producing children for it if were a ValueObjectSP, we would end up
237-
// with a loop (iterator -> synthetic -> child -> parent == iterator) and
238-
// that would in turn leak memory by never allowing the ValueObjects to die
239-
// and free their memory.
240-
m_iter_ptr =
241-
valobj_sp
242-
->GetValueForExpressionPath(".__i_.__node_", nullptr, nullptr,
243-
exprPathOptions, nullptr)
244-
.get();
245-
246-
if (m_iter_ptr) {
247-
auto iter_child(valobj_sp->GetChildMemberWithName("__i_"));
248-
if (!iter_child) {
249-
m_iter_ptr = nullptr;
250-
return lldb::ChildCacheState::eRefetch;
251-
}
252-
253-
CompilerType node_type(iter_child->GetCompilerType()
254-
.GetTypeTemplateArgument(0)
255-
.GetPointeeType());
256-
257-
CompilerType pair_type(node_type.GetTypeTemplateArgument(0));
258-
259-
std::string name;
260-
uint64_t bit_offset_ptr;
261-
uint32_t bitfield_bit_size_ptr;
262-
bool is_bitfield_ptr;
263-
264-
pair_type = pair_type.GetFieldAtIndex(
265-
0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
266-
if (!pair_type) {
267-
m_iter_ptr = nullptr;
268-
return lldb::ChildCacheState::eRefetch;
269-
}
270-
271-
uint64_t addr = m_iter_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
272-
m_iter_ptr = nullptr;
273-
274-
if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
275-
return lldb::ChildCacheState::eRefetch;
276-
277-
auto ts = pair_type.GetTypeSystem();
278-
auto ast_ctx = ts.dyn_cast_or_null<TypeSystemClang>();
279-
if (!ast_ctx)
280-
return lldb::ChildCacheState::eRefetch;
281-
282-
// Mimick layout of std::__hash_iterator::__node_ and read it in
283-
// from process memory.
284-
//
285-
// The following shows the contiguous block of memory:
286-
//
287-
// +-----------------------------+ class __hash_node_base
288-
// __node_ | __next_pointer __next_; |
289-
// +-----------------------------+ class __hash_node
290-
// | size_t __hash_; |
291-
// | __node_value_type __value_; | <<< our key/value pair
292-
// +-----------------------------+
293-
//
294-
CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(
295-
llvm::StringRef(),
296-
{{"__next_",
297-
ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
298-
{"__hash_", ast_ctx->GetBasicType(lldb::eBasicTypeUnsignedLongLong)},
299-
{"__value_", pair_type}});
300-
std::optional<uint64_t> size = tree_node_type.GetByteSize(nullptr);
301-
if (!size)
302-
return lldb::ChildCacheState::eRefetch;
303-
WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
304-
ProcessSP process_sp(target_sp->GetProcessSP());
305-
Status error;
306-
process_sp->ReadMemory(addr, buffer_sp->GetBytes(),
307-
buffer_sp->GetByteSize(), error);
308-
if (error.Fail())
309-
return lldb::ChildCacheState::eRefetch;
310-
DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(),
311-
process_sp->GetAddressByteSize());
312-
auto pair_sp = CreateValueObjectFromData(
313-
"pair", extractor, valobj_sp->GetExecutionContextRef(), tree_node_type);
314-
if (pair_sp)
315-
m_pair_sp = pair_sp->GetChildAtIndex(2);
316-
}
317-
318-
return lldb::ChildCacheState::eRefetch;
319-
}
320-
321-
llvm::Expected<uint32_t> lldb_private::formatters::
322-
LibCxxUnorderedMapIteratorSyntheticFrontEnd::CalculateNumChildren() {
323-
return 2;
324-
}
325-
326-
lldb::ValueObjectSP lldb_private::formatters::
327-
LibCxxUnorderedMapIteratorSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
328-
if (m_pair_sp)
329-
return m_pair_sp->GetChildAtIndex(idx);
330-
return lldb::ValueObjectSP();
331-
}
332-
333-
bool lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
334-
MightHaveChildren() {
335-
return true;
336-
}
337-
338-
size_t lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
339-
GetIndexOfChildWithName(ConstString name) {
340-
if (name == "first")
341-
return 0;
342-
if (name == "second")
343-
return 1;
344-
return UINT32_MAX;
345-
}
346-
347-
SyntheticChildrenFrontEnd *
348-
lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEndCreator(
349-
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
350-
return (valobj_sp ? new LibCxxUnorderedMapIteratorSyntheticFrontEnd(valobj_sp)
351-
: nullptr);
352-
}
353-
354205
/*
355206
(lldb) fr var ibeg --raw --ptr-depth 1 -T
356207
(std::__1::__wrap_iter<int *>) ibeg = {

lldb/source/Plugins/Language/CPlusPlus/LibCxx.h

Lines changed: 4 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -87,56 +87,6 @@ bool LibcxxContainerSummaryProvider(ValueObject &valobj, Stream &stream,
8787
bool LibcxxSpanSummaryProvider(ValueObject &valobj, Stream &stream,
8888
const TypeSummaryOptions &options);
8989

90-
/// Formats libcxx's std::unordered_map iterators
91-
///
92-
/// In raw form a std::unordered_map::iterator is represented as follows:
93-
///
94-
/// (lldb) var it --raw --ptr-depth 1
95-
/// (std::__1::__hash_map_iterator<
96-
/// std::__1::__hash_iterator<
97-
/// std::__1::__hash_node<
98-
/// std::__1::__hash_value_type<
99-
/// std::__1::basic_string<char, std::__1::char_traits<char>,
100-
/// std::__1::allocator<char> >, std::__1::basic_string<char,
101-
/// std::__1::char_traits<char>, std::__1::allocator<char> > >,
102-
/// void *> *> >)
103-
/// it = {
104-
/// __i_ = {
105-
/// __node_ = 0x0000600001700040 {
106-
/// __next_ = 0x0000600001704000
107-
/// }
108-
/// }
109-
/// }
110-
class LibCxxUnorderedMapIteratorSyntheticFrontEnd
111-
: public SyntheticChildrenFrontEnd {
112-
public:
113-
LibCxxUnorderedMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
114-
115-
~LibCxxUnorderedMapIteratorSyntheticFrontEnd() override = default;
116-
117-
llvm::Expected<uint32_t> CalculateNumChildren() override;
118-
119-
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
120-
121-
lldb::ChildCacheState Update() override;
122-
123-
bool MightHaveChildren() override;
124-
125-
size_t GetIndexOfChildWithName(ConstString name) override;
126-
127-
private:
128-
ValueObject *m_iter_ptr = nullptr; ///< Held, not owned. Child of iterator
129-
///< ValueObject supplied at construction.
130-
131-
lldb::ValueObjectSP m_pair_sp; ///< ValueObject for the key/value pair
132-
///< that the iterator currently points
133-
///< to.
134-
};
135-
136-
SyntheticChildrenFrontEnd *
137-
LibCxxUnorderedMapIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,
138-
lldb::ValueObjectSP);
139-
14090
SyntheticChildrenFrontEnd *
14191
LibCxxVectorIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,
14292
lldb::ValueObjectSP);
@@ -230,6 +180,10 @@ SyntheticChildrenFrontEnd *
230180
LibcxxStdUnorderedMapSyntheticFrontEndCreator(CXXSyntheticChildren *,
231181
lldb::ValueObjectSP);
232182

183+
SyntheticChildrenFrontEnd *
184+
LibCxxUnorderedMapIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,
185+
lldb::ValueObjectSP);
186+
233187
SyntheticChildrenFrontEnd *
234188
LibcxxInitializerListSyntheticFrontEndCreator(CXXSyntheticChildren *,
235189
lldb::ValueObjectSP);

0 commit comments

Comments
 (0)