1 | //===-- LibCxxTuple.cpp ---------------------------------------------------===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "LibCxx.h" |
10 | #include "lldb/DataFormatters/FormattersHelpers.h" |
11 | |
12 | using namespace lldb; |
13 | using namespace lldb_private; |
14 | |
15 | namespace { |
16 | |
17 | class TupleFrontEnd: public SyntheticChildrenFrontEnd { |
18 | public: |
19 | TupleFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) { |
20 | Update(); |
21 | } |
22 | |
23 | size_t GetIndexOfChildWithName(ConstString name) override { |
24 | return formatters::ExtractIndexFromString(item_name: name.GetCString()); |
25 | } |
26 | |
27 | bool MightHaveChildren() override { return true; } |
28 | lldb::ChildCacheState Update() override; |
29 | llvm::Expected<uint32_t> CalculateNumChildren() override { |
30 | return m_elements.size(); |
31 | } |
32 | ValueObjectSP GetChildAtIndex(uint32_t idx) override; |
33 | |
34 | private: |
35 | // The lifetime of a ValueObject and all its derivative ValueObjects |
36 | // (children, clones, etc.) is managed by a ClusterManager. These |
37 | // objects are only destroyed when every shared pointer to any of them |
38 | // is destroyed, so we must not store a shared pointer to any ValueObject |
39 | // derived from our backend ValueObject (since we're in the same cluster). |
40 | std::vector<ValueObject*> m_elements; |
41 | ValueObject* m_base = nullptr; |
42 | }; |
43 | } |
44 | |
45 | lldb::ChildCacheState TupleFrontEnd::Update() { |
46 | m_elements.clear(); |
47 | m_base = nullptr; |
48 | |
49 | ValueObjectSP base_sp; |
50 | base_sp = m_backend.GetChildMemberWithName(name: "__base_"); |
51 | if (!base_sp) { |
52 | // Pre r304382 name of the base element. |
53 | base_sp = m_backend.GetChildMemberWithName(name: "base_"); |
54 | } |
55 | if (!base_sp) |
56 | return lldb::ChildCacheState::eRefetch; |
57 | m_base = base_sp.get(); |
58 | m_elements.assign(n: base_sp->GetCompilerType().GetNumDirectBaseClasses(), |
59 | val: nullptr); |
60 | return lldb::ChildCacheState::eRefetch; |
61 | } |
62 | |
63 | ValueObjectSP TupleFrontEnd::GetChildAtIndex(uint32_t idx) { |
64 | if (idx >= m_elements.size()) |
65 | return ValueObjectSP(); |
66 | if (!m_base) |
67 | return ValueObjectSP(); |
68 | if (m_elements[idx]) |
69 | return m_elements[idx]->GetSP(); |
70 | |
71 | CompilerType holder_type = |
72 | m_base->GetCompilerType().GetDirectBaseClassAtIndex(idx, bit_offset_ptr: nullptr); |
73 | if (!holder_type) |
74 | return ValueObjectSP(); |
75 | ValueObjectSP holder_sp = m_base->GetChildAtIndex(idx); |
76 | if (!holder_sp) |
77 | return ValueObjectSP(); |
78 | |
79 | ValueObjectSP elem_sp = holder_sp->GetChildAtIndex(idx: 0); |
80 | if (elem_sp) |
81 | m_elements[idx] = |
82 | elem_sp->Clone(new_name: ConstString(llvm::formatv(Fmt: "[{0}]", Vals&: idx).str())).get(); |
83 | |
84 | if (m_elements[idx]) |
85 | return m_elements[idx]->GetSP(); |
86 | return ValueObjectSP(); |
87 | } |
88 | |
89 | SyntheticChildrenFrontEnd * |
90 | formatters::LibcxxTupleFrontEndCreator(CXXSyntheticChildren *, |
91 | lldb::ValueObjectSP valobj_sp) { |
92 | if (valobj_sp) |
93 | return new TupleFrontEnd(*valobj_sp); |
94 | return nullptr; |
95 | } |
96 |