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#include "llvm/Support/ErrorExtras.h"
16
17#include <memory>
18#include <vector>
19
20using namespace lldb;
21using namespace lldb_private;
22using namespace lldb_private::formatters;
23
24namespace {
25
26class LibStdcppUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
27public:
28 explicit LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
29
30 llvm::Expected<uint32_t> CalculateNumChildren() override;
31
32 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
33
34 lldb::ChildCacheState Update() override;
35
36 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
37
38 bool GetSummary(Stream &stream, const TypeSummaryOptions &options);
39
40private:
41 // The lifetime of a ValueObject and all its derivative ValueObjects
42 // (children, clones, etc.) is managed by a ClusterManager. These
43 // objects are only destroyed when every shared pointer to any of them
44 // is destroyed, so we must not store a shared pointer to any ValueObject
45 // derived from our backend ValueObject (since we're in the same cluster).
46 ValueObject *m_ptr_obj = nullptr;
47 ValueObject* m_del_obj = nullptr;
48
49 ValueObjectSP GetTuple();
50};
51
52} // end of anonymous namespace
53
54LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd(
55 lldb::ValueObjectSP valobj_sp)
56 : SyntheticChildrenFrontEnd(*valobj_sp) {
57 Update();
58}
59
60ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetTuple() {
61 ValueObjectSP valobj_backend_sp = m_backend.GetSP();
62
63 if (!valobj_backend_sp)
64 return nullptr;
65
66 ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue();
67 if (!valobj_sp)
68 return nullptr;
69
70 ValueObjectSP obj_child_sp = valobj_sp->GetChildMemberWithName("_M_t");
71 if (!obj_child_sp)
72 return nullptr;
73
74 ValueObjectSP obj_subchild_sp = obj_child_sp->GetChildMemberWithName("_M_t");
75
76 // if there is a _M_t subchild, the tuple is found in the obj_subchild_sp
77 // (for libstdc++ 6.0.23).
78 if (obj_subchild_sp) {
79 return obj_subchild_sp;
80 }
81
82 return obj_child_sp;
83}
84
85lldb::ChildCacheState LibStdcppUniquePtrSyntheticFrontEnd::Update() {
86 ValueObjectSP tuple_sp = GetTuple();
87
88 if (!tuple_sp)
90
91 std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend(
93
94 ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0);
95 if (!ptr_obj)
97
98 m_ptr_obj = ptr_obj->Clone(ConstString("pointer")).get();
99
100 // Add a 'deleter' child if there was a non-empty deleter type specified.
101 //
102 // The object might have size=1 in the TypeSystem but occupies no dedicated
103 // storage due to no_unique_address, so infer the actual size from the total
104 // size of the unique_ptr class. If sizeof(unique_ptr) == sizeof(void*) then
105 // the deleter is empty and should be hidden.
106 if (llvm::expectedToOptional(tuple_sp->GetByteSize()).value_or(0) >
107 llvm::expectedToOptional(ptr_obj->GetByteSize()).value_or(0)) {
108 ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1);
109 if (del_obj)
110 m_del_obj = del_obj->Clone(ConstString("deleter")).get();
111 }
112
114}
115
117LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
118 if (idx == 0 && m_ptr_obj)
119 return m_ptr_obj->GetSP();
120 if (idx == 1 && m_del_obj)
121 return m_del_obj->GetSP();
122 if (idx == 2) {
123 if (m_ptr_obj) {
124 Status status;
125 auto value_sp = m_ptr_obj->Dereference(status);
126 if (status.Success()) {
127 return value_sp;
128 }
129 }
130 }
131 return lldb::ValueObjectSP();
132}
133
134llvm::Expected<uint32_t>
135LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() {
136 if (m_del_obj)
137 return 2;
138 return 1;
139}
140
141llvm::Expected<size_t>
142LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) {
143 if (name == "ptr" || name == "pointer")
144 return 0;
145 if (name == "del" || name == "deleter")
146 return 1;
147 if (name == "obj" || name == "object" || name == "$$dereference$$")
148 return 2;
149 return llvm::createStringErrorV("type has no child named '{0}'", name);
150}
151
152bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary(
153 Stream &stream, const TypeSummaryOptions &options) {
154 if (!m_ptr_obj)
155 return false;
156
157 DumpCxxSmartPtrPointerSummary(stream, *m_ptr_obj, options);
158
159 return true;
160}
161
162SyntheticChildrenFrontEnd *
164 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
165 return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp)
166 : nullptr);
167}
168
170 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
171 LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP());
172 return formatter.GetSummary(stream, options);
173}
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 ...
bool Success() const
Test for success condition.
Definition Status.cpp:303
A stream class that can stream formatted output to a file.
Definition Stream.h:28
lldb::ValueObjectSP GetSP()
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