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