180814287SRaphael Isemann //===-- LibCxxMap.cpp -----------------------------------------------------===//
233e97e63SEnrico Granata //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
633e97e63SEnrico Granata //
733e97e63SEnrico Granata //===----------------------------------------------------------------------===//
833e97e63SEnrico Granata
933e97e63SEnrico Granata #include "LibCxx.h"
1033e97e63SEnrico Granata
118be30215SAlex Langford #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
1233e97e63SEnrico Granata #include "lldb/Core/ValueObject.h"
1333e97e63SEnrico Granata #include "lldb/Core/ValueObjectConstResult.h"
1433e97e63SEnrico Granata #include "lldb/DataFormatters/FormattersHelpers.h"
1533e97e63SEnrico Granata #include "lldb/Target/Target.h"
16666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h"
1701c3243fSZachary Turner #include "lldb/Utility/Endian.h"
1897206d57SZachary Turner #include "lldb/Utility/Status.h"
19bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
2033e97e63SEnrico Granata
2133e97e63SEnrico Granata using namespace lldb;
2233e97e63SEnrico Granata using namespace lldb_private;
2333e97e63SEnrico Granata using namespace lldb_private::formatters;
2433e97e63SEnrico Granata
25b9c1b51eSKate Stone class MapEntry {
2633e97e63SEnrico Granata public:
278d15f33bSEugene Zelenko MapEntry() = default;
MapEntry(ValueObjectSP entry_sp)2833e97e63SEnrico Granata explicit MapEntry(ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
MapEntry(ValueObject * entry)29b9c1b51eSKate Stone explicit MapEntry(ValueObject *entry)
30b9c1b51eSKate Stone : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
3133e97e63SEnrico Granata
left() const32b9c1b51eSKate Stone ValueObjectSP left() const {
3333e97e63SEnrico Granata static ConstString g_left("__left_");
3433e97e63SEnrico Granata if (!m_entry_sp)
3533e97e63SEnrico Granata return m_entry_sp;
36038aadd8SEnrico Granata return m_entry_sp->GetSyntheticChildAtOffset(
37038aadd8SEnrico Granata 0, m_entry_sp->GetCompilerType(), true);
3833e97e63SEnrico Granata }
3933e97e63SEnrico Granata
right() const40b9c1b51eSKate Stone ValueObjectSP right() const {
4133e97e63SEnrico Granata static ConstString g_right("__right_");
4233e97e63SEnrico Granata if (!m_entry_sp)
4333e97e63SEnrico Granata return m_entry_sp;
44038aadd8SEnrico Granata return m_entry_sp->GetSyntheticChildAtOffset(
45038aadd8SEnrico Granata m_entry_sp->GetProcessSP()->GetAddressByteSize(),
46038aadd8SEnrico Granata m_entry_sp->GetCompilerType(), true);
4733e97e63SEnrico Granata }
4833e97e63SEnrico Granata
parent() const49b9c1b51eSKate Stone ValueObjectSP parent() const {
5033e97e63SEnrico Granata static ConstString g_parent("__parent_");
5133e97e63SEnrico Granata if (!m_entry_sp)
5233e97e63SEnrico Granata return m_entry_sp;
53038aadd8SEnrico Granata return m_entry_sp->GetSyntheticChildAtOffset(
54038aadd8SEnrico Granata 2 * m_entry_sp->GetProcessSP()->GetAddressByteSize(),
55038aadd8SEnrico Granata m_entry_sp->GetCompilerType(), true);
5633e97e63SEnrico Granata }
5733e97e63SEnrico Granata
value() const58b9c1b51eSKate Stone uint64_t value() const {
5933e97e63SEnrico Granata if (!m_entry_sp)
6033e97e63SEnrico Granata return 0;
6133e97e63SEnrico Granata return m_entry_sp->GetValueAsUnsigned(0);
6233e97e63SEnrico Granata }
6333e97e63SEnrico Granata
error() const64b9c1b51eSKate Stone bool error() const {
6533e97e63SEnrico Granata if (!m_entry_sp)
6633e97e63SEnrico Granata return true;
6733e97e63SEnrico Granata return m_entry_sp->GetError().Fail();
6833e97e63SEnrico Granata }
6933e97e63SEnrico Granata
null() const70b9c1b51eSKate Stone bool null() const { return (value() == 0); }
7133e97e63SEnrico Granata
GetEntry() const72b9c1b51eSKate Stone ValueObjectSP GetEntry() const { return m_entry_sp; }
7333e97e63SEnrico Granata
SetEntry(ValueObjectSP entry)74b9c1b51eSKate Stone void SetEntry(ValueObjectSP entry) { m_entry_sp = entry; }
7533e97e63SEnrico Granata
operator ==(const MapEntry & rhs) const76b9c1b51eSKate Stone bool operator==(const MapEntry &rhs) const {
7733e97e63SEnrico Granata return (rhs.m_entry_sp.get() == m_entry_sp.get());
7833e97e63SEnrico Granata }
7933e97e63SEnrico Granata
8033e97e63SEnrico Granata private:
8133e97e63SEnrico Granata ValueObjectSP m_entry_sp;
8233e97e63SEnrico Granata };
8333e97e63SEnrico Granata
84b9c1b51eSKate Stone class MapIterator {
8533e97e63SEnrico Granata public:
868d15f33bSEugene Zelenko MapIterator() = default;
MapIterator(MapEntry entry,size_t depth=0)87b9c1b51eSKate Stone MapIterator(MapEntry entry, size_t depth = 0)
886dc2a6a8SDavid Blaikie : m_entry(std::move(entry)), m_max_depth(depth), m_error(false) {}
MapIterator(ValueObjectSP entry,size_t depth=0)89b9c1b51eSKate Stone MapIterator(ValueObjectSP entry, size_t depth = 0)
906dc2a6a8SDavid Blaikie : m_entry(std::move(entry)), m_max_depth(depth), m_error(false) {}
MapIterator(const MapIterator & rhs)91b9c1b51eSKate Stone MapIterator(const MapIterator &rhs)
92b9c1b51eSKate Stone : m_entry(rhs.m_entry), m_max_depth(rhs.m_max_depth), m_error(false) {}
MapIterator(ValueObject * entry,size_t depth=0)93b9c1b51eSKate Stone MapIterator(ValueObject *entry, size_t depth = 0)
94b9c1b51eSKate Stone : m_entry(entry), m_max_depth(depth), m_error(false) {}
9533e97e63SEnrico Granata
965312139fSEric Christopher MapIterator &operator=(const MapIterator &) = default;
975312139fSEric Christopher
value()98b9c1b51eSKate Stone ValueObjectSP value() { return m_entry.GetEntry(); }
9933e97e63SEnrico Granata
advance(size_t count)100b9c1b51eSKate Stone ValueObjectSP advance(size_t count) {
101bbd16815SEugene Zelenko ValueObjectSP fail;
10233e97e63SEnrico Granata if (m_error)
10333e97e63SEnrico Granata return fail;
10433e97e63SEnrico Granata size_t steps = 0;
105b9c1b51eSKate Stone while (count > 0) {
10633e97e63SEnrico Granata next();
10733e97e63SEnrico Granata count--, steps++;
108b9c1b51eSKate Stone if (m_error || m_entry.null() || (steps > m_max_depth))
10933e97e63SEnrico Granata return fail;
11033e97e63SEnrico Granata }
11133e97e63SEnrico Granata return m_entry.GetEntry();
11233e97e63SEnrico Granata }
1138d15f33bSEugene Zelenko
11433e97e63SEnrico Granata protected:
next()115b9c1b51eSKate Stone void next() {
11633e97e63SEnrico Granata if (m_entry.null())
11733e97e63SEnrico Granata return;
11833e97e63SEnrico Granata MapEntry right(m_entry.right());
119b9c1b51eSKate Stone if (!right.null()) {
12033e97e63SEnrico Granata m_entry = tree_min(std::move(right));
12133e97e63SEnrico Granata return;
12233e97e63SEnrico Granata }
12333e97e63SEnrico Granata size_t steps = 0;
124b9c1b51eSKate Stone while (!is_left_child(m_entry)) {
125b9c1b51eSKate Stone if (m_entry.error()) {
12633e97e63SEnrico Granata m_error = true;
12733e97e63SEnrico Granata return;
12833e97e63SEnrico Granata }
12933e97e63SEnrico Granata m_entry.SetEntry(m_entry.parent());
13033e97e63SEnrico Granata steps++;
131b9c1b51eSKate Stone if (steps > m_max_depth) {
13233e97e63SEnrico Granata m_entry = MapEntry();
13333e97e63SEnrico Granata return;
13433e97e63SEnrico Granata }
13533e97e63SEnrico Granata }
13633e97e63SEnrico Granata m_entry = MapEntry(m_entry.parent());
13733e97e63SEnrico Granata }
13833e97e63SEnrico Granata
13933e97e63SEnrico Granata private:
tree_min(MapEntry x)1406dc2a6a8SDavid Blaikie MapEntry tree_min(MapEntry x) {
14133e97e63SEnrico Granata if (x.null())
14233e97e63SEnrico Granata return MapEntry();
14333e97e63SEnrico Granata MapEntry left(x.left());
14433e97e63SEnrico Granata size_t steps = 0;
145b9c1b51eSKate Stone while (!left.null()) {
146b9c1b51eSKate Stone if (left.error()) {
14733e97e63SEnrico Granata m_error = true;
14833e97e63SEnrico Granata return MapEntry();
14933e97e63SEnrico Granata }
15033e97e63SEnrico Granata x = left;
15133e97e63SEnrico Granata left.SetEntry(x.left());
15233e97e63SEnrico Granata steps++;
15333e97e63SEnrico Granata if (steps > m_max_depth)
15433e97e63SEnrico Granata return MapEntry();
15533e97e63SEnrico Granata }
15633e97e63SEnrico Granata return x;
15733e97e63SEnrico Granata }
15833e97e63SEnrico Granata
is_left_child(const MapEntry & x)159b9c1b51eSKate Stone bool is_left_child(const MapEntry &x) {
16033e97e63SEnrico Granata if (x.null())
16133e97e63SEnrico Granata return false;
16233e97e63SEnrico Granata MapEntry rhs(x.parent());
16333e97e63SEnrico Granata rhs.SetEntry(rhs.left());
16433e97e63SEnrico Granata return x.value() == rhs.value();
16533e97e63SEnrico Granata }
16633e97e63SEnrico Granata
16733e97e63SEnrico Granata MapEntry m_entry;
168*459cfa5eSSlava Gurevich size_t m_max_depth = 0;
169*459cfa5eSSlava Gurevich bool m_error = false;
17033e97e63SEnrico Granata };
17133e97e63SEnrico Granata
172a0b75d7eSEnrico Granata namespace lldb_private {
173a0b75d7eSEnrico Granata namespace formatters {
174b9c1b51eSKate Stone class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
175a0b75d7eSEnrico Granata public:
176a0b75d7eSEnrico Granata LibcxxStdMapSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
177a0b75d7eSEnrico Granata
178a0b75d7eSEnrico Granata ~LibcxxStdMapSyntheticFrontEnd() override = default;
179a0b75d7eSEnrico Granata
180b9c1b51eSKate Stone size_t CalculateNumChildren() override;
181a0b75d7eSEnrico Granata
182b9c1b51eSKate Stone lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
183a0b75d7eSEnrico Granata
184b9c1b51eSKate Stone bool Update() override;
185a0b75d7eSEnrico Granata
186b9c1b51eSKate Stone bool MightHaveChildren() override;
187a0b75d7eSEnrico Granata
1880e4c4821SAdrian Prantl size_t GetIndexOfChildWithName(ConstString name) override;
189a0b75d7eSEnrico Granata
190a0b75d7eSEnrico Granata private:
191b9c1b51eSKate Stone bool GetDataType();
192a0b75d7eSEnrico Granata
193b9c1b51eSKate Stone void GetValueOffset(const lldb::ValueObjectSP &node);
194a0b75d7eSEnrico Granata
19528c878aeSShafik Yaghmour ValueObject *m_tree = nullptr;
19628c878aeSShafik Yaghmour ValueObject *m_root_node = nullptr;
197a0b75d7eSEnrico Granata CompilerType m_element_type;
19828c878aeSShafik Yaghmour uint32_t m_skip_size = UINT32_MAX;
19928c878aeSShafik Yaghmour size_t m_count = UINT32_MAX;
200a0b75d7eSEnrico Granata std::map<size_t, MapIterator> m_iterators;
201a0b75d7eSEnrico Granata };
202a0b75d7eSEnrico Granata } // namespace formatters
203a0b75d7eSEnrico Granata } // namespace lldb_private
204a0b75d7eSEnrico Granata
205b9c1b51eSKate Stone lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::
LibcxxStdMapSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)206b9c1b51eSKate Stone LibcxxStdMapSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
20728c878aeSShafik Yaghmour : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type(), m_iterators() {
20833e97e63SEnrico Granata if (valobj_sp)
20933e97e63SEnrico Granata Update();
21033e97e63SEnrico Granata }
21133e97e63SEnrico Granata
212b9c1b51eSKate Stone size_t lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::
CalculateNumChildren()213b9c1b51eSKate Stone CalculateNumChildren() {
21480a11e08SShafik Yaghmour static ConstString g_pair3_("__pair3_");
21580a11e08SShafik Yaghmour static ConstString g_first_("__first_");
21680a11e08SShafik Yaghmour static ConstString g_value_("__value_");
2174c2bf568SEnrico Granata
21833e97e63SEnrico Granata if (m_count != UINT32_MAX)
21933e97e63SEnrico Granata return m_count;
220bbd16815SEugene Zelenko if (m_tree == nullptr)
22133e97e63SEnrico Granata return 0;
22280a11e08SShafik Yaghmour ValueObjectSP m_item(m_tree->GetChildMemberWithName(g_pair3_, true));
22333e97e63SEnrico Granata if (!m_item)
22433e97e63SEnrico Granata return 0;
2256cc3354dSLang Hames
2266cc3354dSLang Hames switch (m_item->GetCompilerType().GetNumDirectBaseClasses()) {
2276cc3354dSLang Hames case 1:
2286cc3354dSLang Hames // Assume a pre llvm r300140 __compressed_pair implementation:
22980a11e08SShafik Yaghmour m_item = m_item->GetChildMemberWithName(g_first_, true);
2306cc3354dSLang Hames break;
2316cc3354dSLang Hames case 2: {
2326cc3354dSLang Hames // Assume a post llvm r300140 __compressed_pair implementation:
2336cc3354dSLang Hames ValueObjectSP first_elem_parent = m_item->GetChildAtIndex(0, true);
23480a11e08SShafik Yaghmour m_item = first_elem_parent->GetChildMemberWithName(g_value_, true);
2356cc3354dSLang Hames break;
2366cc3354dSLang Hames }
2376cc3354dSLang Hames default:
2386cc3354dSLang Hames return false;
2396cc3354dSLang Hames }
2406cc3354dSLang Hames
24133e97e63SEnrico Granata if (!m_item)
24233e97e63SEnrico Granata return 0;
24333e97e63SEnrico Granata m_count = m_item->GetValueAsUnsigned(0);
24433e97e63SEnrico Granata return m_count;
24533e97e63SEnrico Granata }
24633e97e63SEnrico Granata
GetDataType()247b9c1b51eSKate Stone bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() {
24880a11e08SShafik Yaghmour static ConstString g_value_("__value_");
249be3be28bSEnrico Granata static ConstString g_tree_("__tree_");
250be3be28bSEnrico Granata static ConstString g_pair3("__pair3_");
2514c2bf568SEnrico Granata
25233e97e63SEnrico Granata if (m_element_type.GetOpaqueQualType() && m_element_type.GetTypeSystem())
25333e97e63SEnrico Granata return true;
25433e97e63SEnrico Granata m_element_type.Clear();
25533e97e63SEnrico Granata ValueObjectSP deref;
25697206d57SZachary Turner Status error;
25733e97e63SEnrico Granata deref = m_root_node->Dereference(error);
25833e97e63SEnrico Granata if (!deref || error.Fail())
25933e97e63SEnrico Granata return false;
26080a11e08SShafik Yaghmour deref = deref->GetChildMemberWithName(g_value_, true);
261be3be28bSEnrico Granata if (deref) {
26233e97e63SEnrico Granata m_element_type = deref->GetCompilerType();
26333e97e63SEnrico Granata return true;
26433e97e63SEnrico Granata }
265be3be28bSEnrico Granata deref = m_backend.GetChildAtNamePath({g_tree_, g_pair3});
266be3be28bSEnrico Granata if (!deref)
267be3be28bSEnrico Granata return false;
268769b21eaSPavel Labath m_element_type = deref->GetCompilerType()
269769b21eaSPavel Labath .GetTypeTemplateArgument(1)
270769b21eaSPavel Labath .GetTypeTemplateArgument(1);
271038aadd8SEnrico Granata if (m_element_type) {
272038aadd8SEnrico Granata std::string name;
273038aadd8SEnrico Granata uint64_t bit_offset_ptr;
274038aadd8SEnrico Granata uint32_t bitfield_bit_size_ptr;
275038aadd8SEnrico Granata bool is_bitfield_ptr;
276038aadd8SEnrico Granata m_element_type = m_element_type.GetFieldAtIndex(
277038aadd8SEnrico Granata 0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
278be3be28bSEnrico Granata m_element_type = m_element_type.GetTypedefedType();
279be3be28bSEnrico Granata return m_element_type.IsValid();
280038aadd8SEnrico Granata } else {
281769b21eaSPavel Labath m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0);
282038aadd8SEnrico Granata return m_element_type.IsValid();
283038aadd8SEnrico Granata }
284be3be28bSEnrico Granata }
28533e97e63SEnrico Granata
GetValueOffset(const lldb::ValueObjectSP & node)286b9c1b51eSKate Stone void lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset(
287b9c1b51eSKate Stone const lldb::ValueObjectSP &node) {
28833e97e63SEnrico Granata if (m_skip_size != UINT32_MAX)
28933e97e63SEnrico Granata return;
29033e97e63SEnrico Granata if (!node)
29133e97e63SEnrico Granata return;
29233e97e63SEnrico Granata CompilerType node_type(node->GetCompilerType());
29333e97e63SEnrico Granata uint64_t bit_offset;
294be3be28bSEnrico Granata if (node_type.GetIndexOfFieldWithName("__value_", nullptr, &bit_offset) !=
295be3be28bSEnrico Granata UINT32_MAX) {
29633e97e63SEnrico Granata m_skip_size = bit_offset / 8u;
297038aadd8SEnrico Granata } else {
2986e3b0cc2SRaphael Isemann TypeSystemClang *ast_ctx =
2996e3b0cc2SRaphael Isemann llvm::dyn_cast_or_null<TypeSystemClang>(node_type.GetTypeSystem());
300be3be28bSEnrico Granata if (!ast_ctx)
301be3be28bSEnrico Granata return;
302038aadd8SEnrico Granata CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(
303038aadd8SEnrico Granata ConstString(),
304038aadd8SEnrico Granata {{"ptr0", ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
305be3be28bSEnrico Granata {"ptr1", ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
306be3be28bSEnrico Granata {"ptr2", ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
307be3be28bSEnrico Granata {"cw", ast_ctx->GetBasicType(lldb::eBasicTypeBool)},
308038aadd8SEnrico Granata {"payload", (m_element_type.GetCompleteType(), m_element_type)}});
309be3be28bSEnrico Granata std::string child_name;
310be3be28bSEnrico Granata uint32_t child_byte_size;
311be3be28bSEnrico Granata int32_t child_byte_offset = 0;
312be3be28bSEnrico Granata uint32_t child_bitfield_bit_size;
313be3be28bSEnrico Granata uint32_t child_bitfield_bit_offset;
314be3be28bSEnrico Granata bool child_is_base_class;
315be3be28bSEnrico Granata bool child_is_deref_of_parent;
316be3be28bSEnrico Granata uint64_t language_flags;
317038aadd8SEnrico Granata if (tree_node_type
318038aadd8SEnrico Granata .GetChildCompilerTypeAtIndex(
319038aadd8SEnrico Granata nullptr, 4, true, true, true, child_name, child_byte_size,
320038aadd8SEnrico Granata child_byte_offset, child_bitfield_bit_size,
321038aadd8SEnrico Granata child_bitfield_bit_offset, child_is_base_class,
322038aadd8SEnrico Granata child_is_deref_of_parent, nullptr, language_flags)
323038aadd8SEnrico Granata .IsValid())
324be3be28bSEnrico Granata m_skip_size = (uint32_t)child_byte_offset;
325be3be28bSEnrico Granata }
326be3be28bSEnrico Granata }
32733e97e63SEnrico Granata
32833e97e63SEnrico Granata lldb::ValueObjectSP
GetChildAtIndex(size_t idx)329b9c1b51eSKate Stone lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex(
330b9c1b51eSKate Stone size_t idx) {
33180a11e08SShafik Yaghmour static ConstString g_cc("__cc");
33280a11e08SShafik Yaghmour static ConstString g_nc("__nc");
33380a11e08SShafik Yaghmour static ConstString g_value_("__value_");
33433e97e63SEnrico Granata
33533e97e63SEnrico Granata if (idx >= CalculateNumChildren())
33633e97e63SEnrico Granata return lldb::ValueObjectSP();
337bbd16815SEugene Zelenko if (m_tree == nullptr || m_root_node == nullptr)
33833e97e63SEnrico Granata return lldb::ValueObjectSP();
33933e97e63SEnrico Granata
34033e97e63SEnrico Granata MapIterator iterator(m_root_node, CalculateNumChildren());
341a0b75d7eSEnrico Granata
342a0b75d7eSEnrico Granata const bool need_to_skip = (idx > 0);
343a0b75d7eSEnrico Granata size_t actual_advancde = idx;
344b9c1b51eSKate Stone if (need_to_skip) {
345a0b75d7eSEnrico Granata auto cached_iterator = m_iterators.find(idx - 1);
346b9c1b51eSKate Stone if (cached_iterator != m_iterators.end()) {
347a0b75d7eSEnrico Granata iterator = cached_iterator->second;
348a0b75d7eSEnrico Granata actual_advancde = 1;
349a0b75d7eSEnrico Granata }
350a0b75d7eSEnrico Granata }
351a0b75d7eSEnrico Granata
352a0b75d7eSEnrico Granata ValueObjectSP iterated_sp(iterator.advance(actual_advancde));
353b9c1b51eSKate Stone if (!iterated_sp) {
35433e97e63SEnrico Granata // this tree is garbage - stop
355b9c1b51eSKate Stone m_tree =
356b9c1b51eSKate Stone nullptr; // this will stop all future searches until an Update() happens
35733e97e63SEnrico Granata return iterated_sp;
35833e97e63SEnrico Granata }
359b9c1b51eSKate Stone if (GetDataType()) {
360b9c1b51eSKate Stone if (!need_to_skip) {
36197206d57SZachary Turner Status error;
36233e97e63SEnrico Granata iterated_sp = iterated_sp->Dereference(error);
363b9c1b51eSKate Stone if (!iterated_sp || error.Fail()) {
364bbd16815SEugene Zelenko m_tree = nullptr;
36533e97e63SEnrico Granata return lldb::ValueObjectSP();
36633e97e63SEnrico Granata }
36733e97e63SEnrico Granata GetValueOffset(iterated_sp);
36880a11e08SShafik Yaghmour auto child_sp = iterated_sp->GetChildMemberWithName(g_value_, true);
369be3be28bSEnrico Granata if (child_sp)
370be3be28bSEnrico Granata iterated_sp = child_sp;
371be3be28bSEnrico Granata else
372be3be28bSEnrico Granata iterated_sp = iterated_sp->GetSyntheticChildAtOffset(
373be3be28bSEnrico Granata m_skip_size, m_element_type, true);
374b9c1b51eSKate Stone if (!iterated_sp) {
375bbd16815SEugene Zelenko m_tree = nullptr;
37633e97e63SEnrico Granata return lldb::ValueObjectSP();
37733e97e63SEnrico Granata }
378b9c1b51eSKate Stone } else {
37905097246SAdrian Prantl // because of the way our debug info is made, we need to read item 0
38005097246SAdrian Prantl // first so that we can cache information used to generate other elements
38133e97e63SEnrico Granata if (m_skip_size == UINT32_MAX)
38233e97e63SEnrico Granata GetChildAtIndex(0);
383b9c1b51eSKate Stone if (m_skip_size == UINT32_MAX) {
384bbd16815SEugene Zelenko m_tree = nullptr;
38533e97e63SEnrico Granata return lldb::ValueObjectSP();
38633e97e63SEnrico Granata }
387b9c1b51eSKate Stone iterated_sp = iterated_sp->GetSyntheticChildAtOffset(
388b9c1b51eSKate Stone m_skip_size, m_element_type, true);
389b9c1b51eSKate Stone if (!iterated_sp) {
390bbd16815SEugene Zelenko m_tree = nullptr;
39133e97e63SEnrico Granata return lldb::ValueObjectSP();
39233e97e63SEnrico Granata }
39333e97e63SEnrico Granata }
394b9c1b51eSKate Stone } else {
395bbd16815SEugene Zelenko m_tree = nullptr;
39633e97e63SEnrico Granata return lldb::ValueObjectSP();
39733e97e63SEnrico Granata }
39833e97e63SEnrico Granata // at this point we have a valid
399b9c1b51eSKate Stone // we need to copy current_sp into a new object otherwise we will end up with
400b9c1b51eSKate Stone // all items named __value_
40133e97e63SEnrico Granata DataExtractor data;
40297206d57SZachary Turner Status error;
40333e97e63SEnrico Granata iterated_sp->GetData(data, error);
404b9c1b51eSKate Stone if (error.Fail()) {
405bbd16815SEugene Zelenko m_tree = nullptr;
40633e97e63SEnrico Granata return lldb::ValueObjectSP();
40733e97e63SEnrico Granata }
40833e97e63SEnrico Granata StreamString name;
40933e97e63SEnrico Granata name.Printf("[%" PRIu64 "]", (uint64_t)idx);
410b9c1b51eSKate Stone auto potential_child_sp = CreateValueObjectFromData(
411c156427dSZachary Turner name.GetString(), data, m_backend.GetExecutionContextRef(),
412c156427dSZachary Turner m_element_type);
413b9c1b51eSKate Stone if (potential_child_sp) {
414b9c1b51eSKate Stone switch (potential_child_sp->GetNumChildren()) {
415b9c1b51eSKate Stone case 1: {
41633e97e63SEnrico Granata auto child0_sp = potential_child_sp->GetChildAtIndex(0, true);
41780a11e08SShafik Yaghmour if (child0_sp && child0_sp->GetName() == g_cc)
4184fbb55b7STamas Berghammer potential_child_sp = child0_sp->Clone(ConstString(name.GetString()));
41933e97e63SEnrico Granata break;
42033e97e63SEnrico Granata }
421b9c1b51eSKate Stone case 2: {
42233e97e63SEnrico Granata auto child0_sp = potential_child_sp->GetChildAtIndex(0, true);
42333e97e63SEnrico Granata auto child1_sp = potential_child_sp->GetChildAtIndex(1, true);
42480a11e08SShafik Yaghmour if (child0_sp && child0_sp->GetName() == g_cc && child1_sp &&
42580a11e08SShafik Yaghmour child1_sp->GetName() == g_nc)
4264fbb55b7STamas Berghammer potential_child_sp = child0_sp->Clone(ConstString(name.GetString()));
42733e97e63SEnrico Granata break;
42833e97e63SEnrico Granata }
42933e97e63SEnrico Granata }
43033e97e63SEnrico Granata }
431a0b75d7eSEnrico Granata m_iterators[idx] = iterator;
432106aae51SEnrico Granata return potential_child_sp;
43333e97e63SEnrico Granata }
43433e97e63SEnrico Granata
Update()435b9c1b51eSKate Stone bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::Update() {
43680a11e08SShafik Yaghmour static ConstString g_tree_("__tree_");
43780a11e08SShafik Yaghmour static ConstString g_begin_node_("__begin_node_");
43833e97e63SEnrico Granata m_count = UINT32_MAX;
439bbd16815SEugene Zelenko m_tree = m_root_node = nullptr;
440a0b75d7eSEnrico Granata m_iterators.clear();
44180a11e08SShafik Yaghmour m_tree = m_backend.GetChildMemberWithName(g_tree_, true).get();
44233e97e63SEnrico Granata if (!m_tree)
44333e97e63SEnrico Granata return false;
44480a11e08SShafik Yaghmour m_root_node = m_tree->GetChildMemberWithName(g_begin_node_, true).get();
44533e97e63SEnrico Granata return false;
44633e97e63SEnrico Granata }
44733e97e63SEnrico Granata
448b9c1b51eSKate Stone bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::
MightHaveChildren()449b9c1b51eSKate Stone MightHaveChildren() {
45033e97e63SEnrico Granata return true;
45133e97e63SEnrico Granata }
45233e97e63SEnrico Granata
453b9c1b51eSKate Stone size_t lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::
GetIndexOfChildWithName(ConstString name)4540e4c4821SAdrian Prantl GetIndexOfChildWithName(ConstString name) {
45533e97e63SEnrico Granata return ExtractIndexFromString(name.GetCString());
45633e97e63SEnrico Granata }
45733e97e63SEnrico Granata
45833e97e63SEnrico Granata SyntheticChildrenFrontEnd *
LibcxxStdMapSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)459b9c1b51eSKate Stone lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator(
460b9c1b51eSKate Stone CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
461bbd16815SEugene Zelenko return (valobj_sp ? new LibcxxStdMapSyntheticFrontEnd(valobj_sp) : nullptr);
46233e97e63SEnrico Granata }
463