1 //===-- LibCxxInitializerList.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 
11 #include "lldb/Core/ValueObject.h"
12 #include "lldb/DataFormatters/FormattersHelpers.h"
13 #include "lldb/Utility/ConstString.h"
14 
15 using namespace lldb;
16 using namespace lldb_private;
17 using namespace lldb_private::formatters;
18 
19 namespace lldb_private {
20 namespace formatters {
21 class LibcxxInitializerListSyntheticFrontEnd
22     : public SyntheticChildrenFrontEnd {
23 public:
24   LibcxxInitializerListSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
25 
26   ~LibcxxInitializerListSyntheticFrontEnd() override;
27 
28   size_t CalculateNumChildren() override;
29 
30   lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
31 
32   bool Update() override;
33 
34   bool MightHaveChildren() override;
35 
36   size_t GetIndexOfChildWithName(ConstString name) override;
37 
38 private:
39   ValueObject *m_start = nullptr;
40   CompilerType m_element_type;
41   uint32_t m_element_size = 0;
42   size_t m_num_elements = 0;
43 };
44 } // namespace formatters
45 } // namespace lldb_private
46 
47 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::
48     LibcxxInitializerListSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
49     : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {
50   if (valobj_sp)
51     Update();
52 }
53 
54 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::
55     ~LibcxxInitializerListSyntheticFrontEnd() {
56   // this needs to stay around because it's a child object who will follow its
57   // parent's life cycle
58   // delete m_start;
59 }
60 
61 size_t lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::
62     CalculateNumChildren() {
63   static ConstString g_size_("__size_");
64   m_num_elements = 0;
65   ValueObjectSP size_sp(m_backend.GetChildMemberWithName(g_size_, true));
66   if (size_sp)
67     m_num_elements = size_sp->GetValueAsUnsigned(0);
68   return m_num_elements;
69 }
70 
71 lldb::ValueObjectSP lldb_private::formatters::
72     LibcxxInitializerListSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
73   if (!m_start)
74     return lldb::ValueObjectSP();
75 
76   uint64_t offset = idx * m_element_size;
77   offset = offset + m_start->GetValueAsUnsigned(0);
78   StreamString name;
79   name.Printf("[%" PRIu64 "]", (uint64_t)idx);
80   return CreateValueObjectFromAddress(name.GetString(), offset,
81                                       m_backend.GetExecutionContextRef(),
82                                       m_element_type);
83 }
84 
85 bool lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::
86     Update() {
87   static ConstString g_begin_("__begin_");
88 
89   m_start = nullptr;
90   m_num_elements = 0;
91   m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0);
92   if (!m_element_type.IsValid())
93     return false;
94 
95   if (llvm::Optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) {
96     m_element_size = *size;
97     // Store raw pointers or end up with a circular dependency.
98     m_start = m_backend.GetChildMemberWithName(g_begin_, true).get();
99   }
100 
101   return false;
102 }
103 
104 bool lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::
105     MightHaveChildren() {
106   return true;
107 }
108 
109 size_t lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::
110     GetIndexOfChildWithName(ConstString name) {
111   if (!m_start)
112     return UINT32_MAX;
113   return ExtractIndexFromString(name.GetCString());
114 }
115 
116 lldb_private::SyntheticChildrenFrontEnd *
117 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator(
118     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
119   return (valobj_sp ? new LibcxxInitializerListSyntheticFrontEnd(valobj_sp)
120                     : nullptr);
121 }
122