/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
11 | | #include "lldb/Core/ValueObject.h" |
12 | | #include "lldb/DataFormatters/FormattersHelpers.h" |
13 | | #include "lldb/DataFormatters/TypeSynthetic.h" |
14 | | #include "lldb/Utility/ConstString.h" |
15 | | |
16 | | #include <memory> |
17 | | #include <vector> |
18 | | |
19 | | using namespace lldb; |
20 | | using namespace lldb_private; |
21 | | using namespace lldb_private::formatters; |
22 | | |
23 | | namespace { |
24 | | |
25 | | class LibStdcppUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd { |
26 | | public: |
27 | | explicit LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); |
28 | | |
29 | | size_t CalculateNumChildren() override; |
30 | | |
31 | | lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; |
32 | | |
33 | | bool Update() override; |
34 | | |
35 | | bool MightHaveChildren() override; |
36 | | |
37 | | size_t GetIndexOfChildWithName(ConstString name) override; |
38 | | |
39 | | bool GetSummary(Stream &stream, const TypeSummaryOptions &options); |
40 | | |
41 | | private: |
42 | | // The lifetime of a ValueObject and all its derivative ValueObjects |
43 | | // (children, clones, etc.) is managed by a ClusterManager. These |
44 | | // objects are only destroyed when every shared pointer to any of them |
45 | | // is destroyed, so we must not store a shared pointer to any ValueObject |
46 | | // derived from our backend ValueObject (since we're in the same cluster). |
47 | | ValueObject* m_ptr_obj = nullptr; |
48 | | ValueObject* m_obj_obj = nullptr; |
49 | | ValueObject* m_del_obj = nullptr; |
50 | | |
51 | | ValueObjectSP GetTuple(); |
52 | | }; |
53 | | |
54 | | } // end of anonymous namespace |
55 | | |
56 | | LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd( |
57 | | lldb::ValueObjectSP valobj_sp) |
58 | 2 | : SyntheticChildrenFrontEnd(*valobj_sp) { |
59 | 2 | Update(); |
60 | 2 | } |
61 | | |
62 | 3 | ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetTuple() { |
63 | 3 | ValueObjectSP valobj_backend_sp = m_backend.GetSP(); |
64 | | |
65 | 3 | if (!valobj_backend_sp) |
66 | 0 | return nullptr; |
67 | | |
68 | 3 | ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue(); |
69 | 3 | if (!valobj_sp) |
70 | 0 | return nullptr; |
71 | | |
72 | 3 | ValueObjectSP obj_child_sp = valobj_sp->GetChildMemberWithName("_M_t"); |
73 | 3 | if (!obj_child_sp) |
74 | 3 | return nullptr; |
75 | | |
76 | 0 | ValueObjectSP obj_subchild_sp = obj_child_sp->GetChildMemberWithName("_M_t"); |
77 | | |
78 | | // if there is a _M_t subchild, the tuple is found in the obj_subchild_sp |
79 | | // (for libstdc++ 6.0.23). |
80 | 0 | if (obj_subchild_sp) { |
81 | 0 | return obj_subchild_sp; |
82 | 0 | } |
83 | | |
84 | 0 | return obj_child_sp; |
85 | 0 | } |
86 | | |
87 | 3 | bool LibStdcppUniquePtrSyntheticFrontEnd::Update() { |
88 | 3 | ValueObjectSP tuple_sp = GetTuple(); |
89 | | |
90 | 3 | if (!tuple_sp) |
91 | 3 | return false; |
92 | | |
93 | 0 | std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend( |
94 | 0 | LibStdcppTupleSyntheticFrontEndCreator(nullptr, tuple_sp)); |
95 | |
|
96 | 0 | ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0); |
97 | 0 | if (ptr_obj) |
98 | 0 | 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 | 0 | if (tuple_sp->GetByteSize() > ptr_obj->GetByteSize()) { |
107 | 0 | ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1); |
108 | 0 | if (del_obj) |
109 | 0 | m_del_obj = del_obj->Clone(ConstString("deleter")).get(); |
110 | 0 | } |
111 | 0 | m_obj_obj = nullptr; |
112 | |
|
113 | 0 | return false; |
114 | 3 | } |
115 | | |
116 | 1 | bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; } |
117 | | |
118 | | lldb::ValueObjectSP |
119 | 1 | LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) { |
120 | 1 | if (idx == 0 && m_ptr_obj) |
121 | 0 | return m_ptr_obj->GetSP(); |
122 | 1 | if (idx == 1 && m_del_obj0 ) |
123 | 0 | return m_del_obj->GetSP(); |
124 | 1 | if (idx == 2) { |
125 | 0 | if (m_ptr_obj && !m_obj_obj) { |
126 | 0 | Status error; |
127 | 0 | ValueObjectSP obj_obj = m_ptr_obj->Dereference(error); |
128 | 0 | if (error.Success()) { |
129 | 0 | m_obj_obj = obj_obj->Clone(ConstString("object")).get(); |
130 | 0 | } |
131 | 0 | } |
132 | 0 | if (m_obj_obj) |
133 | 0 | return m_obj_obj->GetSP(); |
134 | 0 | } |
135 | 1 | return lldb::ValueObjectSP(); |
136 | 1 | } |
137 | | |
138 | 1 | size_t LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() { |
139 | 1 | if (m_del_obj) |
140 | 0 | return 2; |
141 | 1 | return 1; |
142 | 1 | } |
143 | | |
144 | | size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName( |
145 | 0 | ConstString name) { |
146 | 0 | if (name == "ptr" || name == "pointer") |
147 | 0 | return 0; |
148 | 0 | if (name == "del" || name == "deleter") |
149 | 0 | return 1; |
150 | 0 | if (name == "obj" || name == "object" || name == "$$dereference$$") |
151 | 0 | return 2; |
152 | 0 | return UINT32_MAX; |
153 | 0 | } |
154 | | |
155 | | bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary( |
156 | 1 | Stream &stream, const TypeSummaryOptions &options) { |
157 | 1 | if (!m_ptr_obj) |
158 | 1 | return false; |
159 | | |
160 | 0 | bool success; |
161 | 0 | uint64_t ptr_value = m_ptr_obj->GetValueAsUnsigned(0, &success); |
162 | 0 | if (!success) |
163 | 0 | return false; |
164 | 0 | if (ptr_value == 0) |
165 | 0 | stream.Printf("nullptr"); |
166 | 0 | else |
167 | 0 | stream.Printf("0x%" PRIx64, ptr_value); |
168 | 0 | return true; |
169 | 0 | } |
170 | | |
171 | | SyntheticChildrenFrontEnd * |
172 | | lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator( |
173 | 1 | CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { |
174 | 1 | return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp) |
175 | 1 | : nullptr0 ); |
176 | 1 | } |
177 | | |
178 | | bool lldb_private::formatters::LibStdcppUniquePointerSummaryProvider( |
179 | 1 | ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { |
180 | 1 | LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP()); |
181 | 1 | return formatter.GetSummary(stream, options); |
182 | 1 | } |