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 | llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override { |
24 | auto optional_idx = formatters::ExtractIndexFromString(item_name: name.GetCString()); |
25 | if (!optional_idx) { |
26 | return llvm::createStringError(Fmt: "Type has no child named '%s'", |
27 | Vals: name.AsCString()); |
28 | } |
29 | return *optional_idx; |
30 | } |
31 | |
32 | lldb::ChildCacheState Update() override; |
33 | llvm::Expected<uint32_t> CalculateNumChildren() override { |
34 | return m_elements.size(); |
35 | } |
36 | ValueObjectSP GetChildAtIndex(uint32_t idx) override; |
37 | |
38 | private: |
39 | // The lifetime of a ValueObject and all its derivative ValueObjects |
40 | // (children, clones, etc.) is managed by a ClusterManager. These |
41 | // objects are only destroyed when every shared pointer to any of them |
42 | // is destroyed, so we must not store a shared pointer to any ValueObject |
43 | // derived from our backend ValueObject (since we're in the same cluster). |
44 | std::vector<ValueObject*> m_elements; |
45 | ValueObject* m_base = nullptr; |
46 | }; |
47 | } |
48 | |
49 | lldb::ChildCacheState TupleFrontEnd::Update() { |
50 | m_elements.clear(); |
51 | m_base = nullptr; |
52 | |
53 | ValueObjectSP base_sp; |
54 | base_sp = m_backend.GetChildMemberWithName(name: "__base_"); |
55 | if (!base_sp) { |
56 | // Pre r304382 name of the base element. |
57 | base_sp = m_backend.GetChildMemberWithName(name: "base_"); |
58 | } |
59 | if (!base_sp) |
60 | return lldb::ChildCacheState::eRefetch; |
61 | m_base = base_sp.get(); |
62 | m_elements.assign(n: base_sp->GetCompilerType().GetNumDirectBaseClasses(), |
63 | val: nullptr); |
64 | return lldb::ChildCacheState::eRefetch; |
65 | } |
66 | |
67 | ValueObjectSP TupleFrontEnd::GetChildAtIndex(uint32_t idx) { |
68 | if (idx >= m_elements.size()) |
69 | return ValueObjectSP(); |
70 | if (!m_base) |
71 | return ValueObjectSP(); |
72 | if (m_elements[idx]) |
73 | return m_elements[idx]->GetSP(); |
74 | |
75 | CompilerType holder_type = |
76 | m_base->GetCompilerType().GetDirectBaseClassAtIndex(idx, bit_offset_ptr: nullptr); |
77 | if (!holder_type) |
78 | return ValueObjectSP(); |
79 | ValueObjectSP holder_sp = m_base->GetChildAtIndex(idx); |
80 | if (!holder_sp) |
81 | return ValueObjectSP(); |
82 | |
83 | ValueObjectSP elem_sp = holder_sp->GetChildAtIndex(idx: 0); |
84 | if (elem_sp) |
85 | m_elements[idx] = |
86 | elem_sp->Clone(new_name: ConstString(llvm::formatv(Fmt: "[{0}]", Vals&: idx).str())).get(); |
87 | |
88 | if (m_elements[idx]) |
89 | return m_elements[idx]->GetSP(); |
90 | return ValueObjectSP(); |
91 | } |
92 | |
93 | SyntheticChildrenFrontEnd * |
94 | formatters::LibcxxTupleFrontEndCreator(CXXSyntheticChildren *, |
95 | lldb::ValueObjectSP valobj_sp) { |
96 | if (valobj_sp) |
97 | return new TupleFrontEnd(*valobj_sp); |
98 | return nullptr; |
99 | } |
100 |