LLDB mainline
LibStdcppUniquePointer.cpp
Go to the documentation of this file.
1//===-- LibStdcppUniquePointer.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 "LibStdcpp.h"
10
15
16#include <memory>
17#include <vector>
18
19using namespace lldb;
20using namespace lldb_private;
21using namespace lldb_private::formatters;
22
23namespace {
24
25class LibStdcppUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
26public:
27 explicit LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
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 bool GetSummary(Stream &stream, const TypeSummaryOptions &options);
38
39private:
40 // The lifetime of a ValueObject and all its derivative ValueObjects
41 // (children, clones, etc.) is managed by a ClusterManager. These
42 // objects are only destroyed when every shared pointer to any of them
43 // is destroyed, so we must not store a shared pointer to any ValueObject
44 // derived from our backend ValueObject (since we're in the same cluster).
45 ValueObject *m_ptr_obj = nullptr;
46 ValueObject* m_del_obj = nullptr;
47
48 ValueObjectSP GetTuple();
49};
50
51} // end of anonymous namespace
52
53LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd(
54 lldb::ValueObjectSP valobj_sp)
55 : SyntheticChildrenFrontEnd(*valobj_sp) {
56 Update();
57}
58
59ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetTuple() {
60 ValueObjectSP valobj_backend_sp = m_backend.GetSP();
61
62 if (!valobj_backend_sp)
63 return nullptr;
64
65 ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue();
66 if (!valobj_sp)
67 return nullptr;
68
69 ValueObjectSP obj_child_sp = valobj_sp->GetChildMemberWithName("_M_t");
70 if (!obj_child_sp)
71 return nullptr;
72
73 ValueObjectSP obj_subchild_sp = obj_child_sp->GetChildMemberWithName("_M_t");
74
75 // if there is a _M_t subchild, the tuple is found in the obj_subchild_sp
76 // (for libstdc++ 6.0.23).
77 if (obj_subchild_sp) {
78 return obj_subchild_sp;
79 }
80
81 return obj_child_sp;
82}
83
84lldb::ChildCacheState LibStdcppUniquePtrSyntheticFrontEnd::Update() {
85 ValueObjectSP tuple_sp = GetTuple();
86
87 if (!tuple_sp)
89
90 std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend(
92
93 ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0);
94 if (ptr_obj)
95 m_ptr_obj = ptr_obj->Clone(ConstString("pointer")).get();
96
97 // Add a 'deleter' child if there was a non-empty deleter type specified.
98 //
99 // The object might have size=1 in the TypeSystem but occupies no dedicated
100 // storage due to no_unique_address, so infer the actual size from the total
101 // size of the unique_ptr class. If sizeof(unique_ptr) == sizeof(void*) then
102 // the deleter is empty and should be hidden.
103 if (llvm::expectedToOptional(tuple_sp->GetByteSize()).value_or(0) >
104 llvm::expectedToOptional(ptr_obj->GetByteSize()).value_or(0)) {
105 ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1);
106 if (del_obj)
107 m_del_obj = del_obj->Clone(ConstString("deleter")).get();
108 }
109
111}
112
114LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
115 if (idx == 0 && m_ptr_obj)
116 return m_ptr_obj->GetSP();
117 if (idx == 1 && m_del_obj)
118 return m_del_obj->GetSP();
119 if (idx == 2) {
120 if (m_ptr_obj) {
121 Status status;
122 auto value_sp = m_ptr_obj->Dereference(status);
123 if (status.Success()) {
124 return value_sp;
125 }
126 }
127 }
128 return lldb::ValueObjectSP();
129}
130
131llvm::Expected<uint32_t>
132LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() {
133 if (m_del_obj)
134 return 2;
135 return 1;
136}
137
138llvm::Expected<size_t>
139LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) {
140 if (name == "ptr" || name == "pointer")
141 return 0;
142 if (name == "del" || name == "deleter")
143 return 1;
144 if (name == "obj" || name == "object" || name == "$$dereference$$")
145 return 2;
146 return llvm::createStringError("Type has no child named '%s'",
147 name.AsCString());
148}
149
150bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary(
151 Stream &stream, const TypeSummaryOptions &options) {
152 if (!m_ptr_obj)
153 return false;
154
155 DumpCxxSmartPtrPointerSummary(stream, *m_ptr_obj, options);
156
157 return true;
158}
159
160SyntheticChildrenFrontEnd *
163 return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp)
164 : nullptr);
165}
166
168 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
169 LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP());
170 return formatter.GetSummary(stream, options);
171}
static std::optional< size_t > CalculateNumChildren(CompilerType container_elem_type, uint64_t num_elements, CompilerType element_type)
Calculates the number of elements stored in a container (with element type 'container_elem_type') as ...
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
bool Success() const
Test for success condition.
Definition Status.cpp:304
A stream class that can stream formatted output to a file.
Definition Stream.h:28
lldb::ValueObjectSP GetSP()
virtual lldb::ValueObjectSP Clone(ConstString new_name)
Creates a copy of the ValueObject with a new name and setting the current ValueObject as its parent.
virtual lldb::ValueObjectSP Dereference(Status &error)
SyntheticChildrenFrontEnd * LibStdcppUniquePtrSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
SyntheticChildrenFrontEnd * LibStdcppTupleSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
bool LibStdcppUniquePointerSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
void DumpCxxSmartPtrPointerSummary(Stream &stream, ValueObject &ptr, const TypeSummaryOptions &options)
Prints the summary for the pointer value of a C++ std::unique_ptr/stdshared_ptr/stdweak_ptr.
A class that represents a running process on the host machine.
ChildCacheState
Specifies if children need to be re-computed after a call to SyntheticChildrenFrontEnd::Update.
@ eRefetch
Children need to be recomputed dynamically.
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP