File: | tools/lldb/include/lldb/Utility/SharingPtr.h |
Warning: | line 148, column 37 Returning null reference |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- LibStdcppUniquePointer.cpp ------------------------------*- C++ -*-===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | ||||
10 | #include "LibStdcpp.h" | |||
11 | ||||
12 | #include "lldb/Core/ValueObject.h" | |||
13 | #include "lldb/DataFormatters/FormattersHelpers.h" | |||
14 | #include "lldb/DataFormatters/TypeSynthetic.h" | |||
15 | #include "lldb/Utility/ConstString.h" | |||
16 | ||||
17 | #include <memory> | |||
18 | #include <vector> | |||
19 | ||||
20 | using namespace lldb; | |||
21 | using namespace lldb_private; | |||
22 | using namespace lldb_private::formatters; | |||
23 | ||||
24 | namespace { | |||
25 | ||||
26 | class LibStdcppUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd { | |||
27 | public: | |||
28 | explicit LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); | |||
29 | ||||
30 | size_t CalculateNumChildren() override; | |||
31 | ||||
32 | lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; | |||
33 | ||||
34 | bool Update() override; | |||
35 | ||||
36 | bool MightHaveChildren() override; | |||
37 | ||||
38 | size_t GetIndexOfChildWithName(const ConstString &name) override; | |||
39 | ||||
40 | bool GetSummary(Stream &stream, const TypeSummaryOptions &options); | |||
41 | ||||
42 | private: | |||
43 | ValueObjectSP m_ptr_obj; | |||
44 | ValueObjectSP m_obj_obj; | |||
45 | ValueObjectSP m_del_obj; | |||
46 | ||||
47 | ValueObjectSP GetTuple(); | |||
48 | }; | |||
49 | ||||
50 | } // end of anonymous namespace | |||
51 | ||||
52 | LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd( | |||
53 | lldb::ValueObjectSP valobj_sp) | |||
54 | : SyntheticChildrenFrontEnd(*valobj_sp) { | |||
55 | Update(); | |||
56 | } | |||
57 | ||||
58 | ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetTuple() { | |||
59 | ValueObjectSP valobj_backend_sp = m_backend.GetSP(); | |||
60 | ||||
61 | if (!valobj_backend_sp) | |||
62 | return nullptr; | |||
63 | ||||
64 | ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue(); | |||
65 | if (!valobj_sp) | |||
66 | return nullptr; | |||
67 | ||||
68 | ValueObjectSP obj_child_sp = | |||
69 | valobj_sp->GetChildMemberWithName(ConstString("_M_t"), true); | |||
70 | if (!obj_child_sp) | |||
71 | return nullptr; | |||
72 | ||||
73 | ValueObjectSP obj_subchild_sp = | |||
74 | obj_child_sp->GetChildMemberWithName(ConstString("_M_t"), true); | |||
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 | ||||
85 | bool LibStdcppUniquePtrSyntheticFrontEnd::Update() { | |||
86 | ValueObjectSP tuple_sp = GetTuple(); | |||
87 | ||||
88 | if (!tuple_sp) | |||
89 | return false; | |||
90 | ||||
91 | std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend( | |||
92 | LibStdcppTupleSyntheticFrontEndCreator(nullptr, tuple_sp)); | |||
93 | ||||
94 | ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0); | |||
95 | if (ptr_obj) | |||
96 | m_ptr_obj = ptr_obj->Clone(ConstString("pointer")); | |||
97 | ||||
98 | ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1); | |||
99 | if (del_obj) | |||
100 | m_del_obj = del_obj->Clone(ConstString("deleter")); | |||
101 | ||||
102 | if (m_ptr_obj) { | |||
103 | Status error; | |||
104 | ValueObjectSP obj_obj = m_ptr_obj->Dereference(error); | |||
105 | if (error.Success()) { | |||
106 | m_obj_obj = obj_obj->Clone(ConstString("object")); | |||
107 | } | |||
108 | } | |||
109 | ||||
110 | return false; | |||
111 | } | |||
112 | ||||
113 | bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; } | |||
114 | ||||
115 | lldb::ValueObjectSP | |||
116 | LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) { | |||
117 | if (idx == 0) | |||
118 | return m_ptr_obj; | |||
119 | if (idx == 1) | |||
120 | return m_del_obj; | |||
121 | if (idx == 2) | |||
122 | return m_obj_obj; | |||
123 | return lldb::ValueObjectSP(); | |||
124 | } | |||
125 | ||||
126 | size_t LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() { | |||
127 | if (m_del_obj) | |||
128 | return 2; | |||
129 | return 1; | |||
130 | } | |||
131 | ||||
132 | size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName( | |||
133 | const ConstString &name) { | |||
134 | if (name == ConstString("ptr") || name == ConstString("pointer")) | |||
135 | return 0; | |||
136 | if (name == ConstString("del") || name == ConstString("deleter")) | |||
137 | return 1; | |||
138 | if (name == ConstString("obj") || name == ConstString("object") || | |||
139 | name == ConstString("$$dereference$$")) | |||
140 | return 2; | |||
141 | return UINT32_MAX(4294967295U); | |||
142 | } | |||
143 | ||||
144 | bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary( | |||
145 | Stream &stream, const TypeSummaryOptions &options) { | |||
146 | if (!m_ptr_obj) | |||
147 | return false; | |||
148 | ||||
149 | bool success; | |||
150 | uint64_t ptr_value = m_ptr_obj->GetValueAsUnsigned(0, &success); | |||
151 | if (!success) | |||
152 | return false; | |||
153 | if (ptr_value == 0) | |||
154 | stream.Printf("nullptr"); | |||
155 | else | |||
156 | stream.Printf("0x%" PRIx64"l" "x", ptr_value); | |||
157 | return true; | |||
158 | } | |||
159 | ||||
160 | SyntheticChildrenFrontEnd * | |||
161 | lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator( | |||
162 | CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { | |||
163 | return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp) | |||
164 | : nullptr); | |||
165 | } | |||
166 | ||||
167 | bool lldb_private::formatters::LibStdcppUniquePointerSummaryProvider( | |||
168 | ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { | |||
169 | LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP()); | |||
| ||||
170 | return formatter.GetSummary(stream, options); | |||
171 | } |
1 | //===-- ValueObject.h -------------------------------------------*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef liblldb_ValueObject_h_ |
11 | #define liblldb_ValueObject_h_ |
12 | |
13 | #include "lldb/Core/Value.h" |
14 | #include "lldb/Symbol/CompilerType.h" |
15 | #include "lldb/Symbol/Type.h" // for TypeImpl |
16 | #include "lldb/Target/ExecutionContext.h" |
17 | #include "lldb/Target/Process.h" |
18 | #include "lldb/Utility/ConstString.h" |
19 | #include "lldb/Utility/DataExtractor.h" |
20 | #include "lldb/Utility/SharedCluster.h" |
21 | #include "lldb/Utility/Status.h" |
22 | #include "lldb/Utility/UserID.h" |
23 | #include "lldb/lldb-defines.h" // for LLDB_INVALID... |
24 | #include "lldb/lldb-enumerations.h" // for DynamicValue... |
25 | #include "lldb/lldb-forward.h" // for ValueObjectSP |
26 | #include "lldb/lldb-private-enumerations.h" // for AddressType |
27 | #include "lldb/lldb-types.h" // for addr_t, offs... |
28 | |
29 | #include "llvm/ADT/ArrayRef.h" |
30 | #include "llvm/ADT/Optional.h" |
31 | #include "llvm/ADT/SmallVector.h" |
32 | #include "llvm/ADT/StringRef.h" // for StringRef |
33 | |
34 | #include <functional> |
35 | #include <initializer_list> |
36 | #include <map> |
37 | #include <mutex> // for recursive_mutex |
38 | #include <string> // for string |
39 | #include <utility> // for pair |
40 | |
41 | #include <stddef.h> // for size_t |
42 | #include <stdint.h> // for uint32_t |
43 | namespace lldb_private { |
44 | class Declaration; |
45 | } |
46 | namespace lldb_private { |
47 | class DumpValueObjectOptions; |
48 | } |
49 | namespace lldb_private { |
50 | class EvaluateExpressionOptions; |
51 | } |
52 | namespace lldb_private { |
53 | class ExecutionContextScope; |
54 | } |
55 | namespace lldb_private { |
56 | class Log; |
57 | } |
58 | namespace lldb_private { |
59 | class Scalar; |
60 | } |
61 | namespace lldb_private { |
62 | class Stream; |
63 | } |
64 | namespace lldb_private { |
65 | class SymbolContextScope; |
66 | } |
67 | namespace lldb_private { |
68 | class TypeFormatImpl; |
69 | } |
70 | namespace lldb_private { |
71 | class TypeSummaryImpl; |
72 | } |
73 | namespace lldb_private { |
74 | class TypeSummaryOptions; |
75 | } |
76 | namespace lldb_private { |
77 | |
78 | /// ValueObject: |
79 | /// |
80 | /// This abstract class provides an interface to a particular value, be it a |
81 | /// register, a local or global variable, |
82 | /// that is evaluated in some particular scope. The ValueObject also has the |
83 | /// capability of being the "child" of |
84 | /// some other variable object, and in turn of having children. |
85 | /// If a ValueObject is a root variable object - having no parent - then it must |
86 | /// be constructed with respect to some |
87 | /// particular ExecutionContextScope. If it is a child, it inherits the |
88 | /// ExecutionContextScope from its parent. |
89 | /// The ValueObject will update itself if necessary before fetching its value, |
90 | /// summary, object description, etc. |
91 | /// But it will always update itself in the ExecutionContextScope with which it |
92 | /// was originally created. |
93 | |
94 | /// A brief note on life cycle management for ValueObjects. This is a little |
95 | /// tricky because a ValueObject can contain |
96 | /// various other ValueObjects - the Dynamic Value, its children, the |
97 | /// dereference value, etc. Any one of these can be |
98 | /// handed out as a shared pointer, but for that contained value object to be |
99 | /// valid, the root object and potentially other |
100 | /// of the value objects need to stay around. |
101 | /// We solve this problem by handing out shared pointers to the Value Object and |
102 | /// any of its dependents using a shared |
103 | /// ClusterManager. This treats each shared pointer handed out for the entire |
104 | /// cluster as a reference to the whole |
105 | /// cluster. The whole cluster will stay around until the last reference is |
106 | /// released. |
107 | /// |
108 | /// The ValueObject mostly handle this automatically, if a value object is made |
109 | /// with a Parent ValueObject, then it adds |
110 | /// itself to the ClusterManager of the parent. |
111 | |
112 | /// It does mean that external to the ValueObjects we should only ever make |
113 | /// available ValueObjectSP's, never ValueObjects |
114 | /// or pointers to them. So all the "Root level" ValueObject derived |
115 | /// constructors should be private, and |
116 | /// should implement a Create function that new's up object and returns a Shared |
117 | /// Pointer that it gets from the GetSP() method. |
118 | /// |
119 | /// However, if you are making an derived ValueObject that will be contained in |
120 | /// a parent value object, you should just |
121 | /// hold onto a pointer to it internally, and by virtue of passing the parent |
122 | /// ValueObject into its constructor, it will |
123 | /// be added to the ClusterManager for the parent. Then if you ever hand out a |
124 | /// Shared Pointer to the contained ValueObject, |
125 | /// just do so by calling GetSP() on the contained object. |
126 | |
127 | class ValueObject : public UserID { |
128 | public: |
129 | enum GetExpressionPathFormat { |
130 | eGetExpressionPathFormatDereferencePointers = 1, |
131 | eGetExpressionPathFormatHonorPointers |
132 | }; |
133 | |
134 | enum ValueObjectRepresentationStyle { |
135 | eValueObjectRepresentationStyleValue = 1, |
136 | eValueObjectRepresentationStyleSummary, |
137 | eValueObjectRepresentationStyleLanguageSpecific, |
138 | eValueObjectRepresentationStyleLocation, |
139 | eValueObjectRepresentationStyleChildrenCount, |
140 | eValueObjectRepresentationStyleType, |
141 | eValueObjectRepresentationStyleName, |
142 | eValueObjectRepresentationStyleExpressionPath |
143 | }; |
144 | |
145 | enum ExpressionPathScanEndReason { |
146 | eExpressionPathScanEndReasonEndOfString = 1, // out of data to parse |
147 | eExpressionPathScanEndReasonNoSuchChild, // child element not found |
148 | eExpressionPathScanEndReasonNoSuchSyntheticChild, // (synthetic) child |
149 | // element not found |
150 | eExpressionPathScanEndReasonEmptyRangeNotAllowed, // [] only allowed for |
151 | // arrays |
152 | eExpressionPathScanEndReasonDotInsteadOfArrow, // . used when -> should be |
153 | // used |
154 | eExpressionPathScanEndReasonArrowInsteadOfDot, // -> used when . should be |
155 | // used |
156 | eExpressionPathScanEndReasonFragileIVarNotAllowed, // ObjC ivar expansion |
157 | // not allowed |
158 | eExpressionPathScanEndReasonRangeOperatorNotAllowed, // [] not allowed by |
159 | // options |
160 | eExpressionPathScanEndReasonRangeOperatorInvalid, // [] not valid on objects |
161 | // other than scalars, |
162 | // pointers or arrays |
163 | eExpressionPathScanEndReasonArrayRangeOperatorMet, // [] is good for arrays, |
164 | // but I cannot parse it |
165 | eExpressionPathScanEndReasonBitfieldRangeOperatorMet, // [] is good for |
166 | // bitfields, but I |
167 | // cannot parse after |
168 | // it |
169 | eExpressionPathScanEndReasonUnexpectedSymbol, // something is malformed in |
170 | // the expression |
171 | eExpressionPathScanEndReasonTakingAddressFailed, // impossible to apply & |
172 | // operator |
173 | eExpressionPathScanEndReasonDereferencingFailed, // impossible to apply * |
174 | // operator |
175 | eExpressionPathScanEndReasonRangeOperatorExpanded, // [] was expanded into a |
176 | // VOList |
177 | eExpressionPathScanEndReasonSyntheticValueMissing, // getting the synthetic |
178 | // children failed |
179 | eExpressionPathScanEndReasonUnknown = 0xFFFF |
180 | }; |
181 | |
182 | enum ExpressionPathEndResultType { |
183 | eExpressionPathEndResultTypePlain = 1, // anything but... |
184 | eExpressionPathEndResultTypeBitfield, // a bitfield |
185 | eExpressionPathEndResultTypeBoundedRange, // a range [low-high] |
186 | eExpressionPathEndResultTypeUnboundedRange, // a range [] |
187 | eExpressionPathEndResultTypeValueObjectList, // several items in a VOList |
188 | eExpressionPathEndResultTypeInvalid = 0xFFFF |
189 | }; |
190 | |
191 | enum ExpressionPathAftermath { |
192 | eExpressionPathAftermathNothing = 1, // just return it |
193 | eExpressionPathAftermathDereference, // dereference the target |
194 | eExpressionPathAftermathTakeAddress // take target's address |
195 | }; |
196 | |
197 | enum ClearUserVisibleDataItems { |
198 | eClearUserVisibleDataItemsNothing = 1u << 0, |
199 | eClearUserVisibleDataItemsValue = 1u << 1, |
200 | eClearUserVisibleDataItemsSummary = 1u << 2, |
201 | eClearUserVisibleDataItemsLocation = 1u << 3, |
202 | eClearUserVisibleDataItemsDescription = 1u << 4, |
203 | eClearUserVisibleDataItemsSyntheticChildren = 1u << 5, |
204 | eClearUserVisibleDataItemsValidator = 1u << 6, |
205 | eClearUserVisibleDataItemsAllStrings = |
206 | eClearUserVisibleDataItemsValue | eClearUserVisibleDataItemsSummary | |
207 | eClearUserVisibleDataItemsLocation | |
208 | eClearUserVisibleDataItemsDescription, |
209 | eClearUserVisibleDataItemsAll = 0xFFFF |
210 | }; |
211 | |
212 | struct GetValueForExpressionPathOptions { |
213 | enum class SyntheticChildrenTraversal { |
214 | None, |
215 | ToSynthetic, |
216 | FromSynthetic, |
217 | Both |
218 | }; |
219 | |
220 | bool m_check_dot_vs_arrow_syntax; |
221 | bool m_no_fragile_ivar; |
222 | bool m_allow_bitfields_syntax; |
223 | SyntheticChildrenTraversal m_synthetic_children_traversal; |
224 | |
225 | GetValueForExpressionPathOptions( |
226 | bool dot = false, bool no_ivar = false, bool bitfield = true, |
227 | SyntheticChildrenTraversal synth_traverse = |
228 | SyntheticChildrenTraversal::ToSynthetic) |
229 | : m_check_dot_vs_arrow_syntax(dot), m_no_fragile_ivar(no_ivar), |
230 | m_allow_bitfields_syntax(bitfield), |
231 | m_synthetic_children_traversal(synth_traverse) {} |
232 | |
233 | GetValueForExpressionPathOptions &DoCheckDotVsArrowSyntax() { |
234 | m_check_dot_vs_arrow_syntax = true; |
235 | return *this; |
236 | } |
237 | |
238 | GetValueForExpressionPathOptions &DontCheckDotVsArrowSyntax() { |
239 | m_check_dot_vs_arrow_syntax = false; |
240 | return *this; |
241 | } |
242 | |
243 | GetValueForExpressionPathOptions &DoAllowFragileIVar() { |
244 | m_no_fragile_ivar = false; |
245 | return *this; |
246 | } |
247 | |
248 | GetValueForExpressionPathOptions &DontAllowFragileIVar() { |
249 | m_no_fragile_ivar = true; |
250 | return *this; |
251 | } |
252 | |
253 | GetValueForExpressionPathOptions &DoAllowBitfieldSyntax() { |
254 | m_allow_bitfields_syntax = true; |
255 | return *this; |
256 | } |
257 | |
258 | GetValueForExpressionPathOptions &DontAllowBitfieldSyntax() { |
259 | m_allow_bitfields_syntax = false; |
260 | return *this; |
261 | } |
262 | |
263 | GetValueForExpressionPathOptions & |
264 | SetSyntheticChildrenTraversal(SyntheticChildrenTraversal traverse) { |
265 | m_synthetic_children_traversal = traverse; |
266 | return *this; |
267 | } |
268 | |
269 | static const GetValueForExpressionPathOptions DefaultOptions() { |
270 | static GetValueForExpressionPathOptions g_default_options; |
271 | |
272 | return g_default_options; |
273 | } |
274 | }; |
275 | |
276 | class EvaluationPoint { |
277 | public: |
278 | EvaluationPoint(); |
279 | |
280 | EvaluationPoint(ExecutionContextScope *exe_scope, |
281 | bool use_selected = false); |
282 | |
283 | EvaluationPoint(const EvaluationPoint &rhs); |
284 | |
285 | ~EvaluationPoint(); |
286 | |
287 | const ExecutionContextRef &GetExecutionContextRef() const { |
288 | return m_exe_ctx_ref; |
289 | } |
290 | |
291 | // Set the EvaluationPoint to the values in exe_scope, Return true if the |
292 | // Evaluation Point changed. Since the ExecutionContextScope is always |
293 | // going to be valid currently, the Updated Context will also always be |
294 | // valid. |
295 | |
296 | // bool |
297 | // SetContext (ExecutionContextScope *exe_scope); |
298 | |
299 | void SetIsConstant() { |
300 | SetUpdated(); |
301 | m_mod_id.SetInvalid(); |
302 | } |
303 | |
304 | bool IsConstant() const { return !m_mod_id.IsValid(); } |
305 | |
306 | ProcessModID GetModID() const { return m_mod_id; } |
307 | |
308 | void SetUpdateID(ProcessModID new_id) { m_mod_id = new_id; } |
309 | |
310 | void SetNeedsUpdate() { m_needs_update = true; } |
311 | |
312 | void SetUpdated(); |
313 | |
314 | bool NeedsUpdating(bool accept_invalid_exe_ctx) { |
315 | SyncWithProcessState(accept_invalid_exe_ctx); |
316 | return m_needs_update; |
317 | } |
318 | |
319 | bool IsValid() { |
320 | const bool accept_invalid_exe_ctx = false; |
321 | if (!m_mod_id.IsValid()) |
322 | return false; |
323 | else if (SyncWithProcessState(accept_invalid_exe_ctx)) { |
324 | if (!m_mod_id.IsValid()) |
325 | return false; |
326 | } |
327 | return true; |
328 | } |
329 | |
330 | void SetInvalid() { |
331 | // Use the stop id to mark us as invalid, leave the thread id and the |
332 | // stack id around for logging and history purposes. |
333 | m_mod_id.SetInvalid(); |
334 | |
335 | // Can't update an invalid state. |
336 | m_needs_update = false; |
337 | } |
338 | |
339 | private: |
340 | bool SyncWithProcessState(bool accept_invalid_exe_ctx); |
341 | |
342 | ProcessModID m_mod_id; // This is the stop id when this ValueObject was last |
343 | // evaluated. |
344 | ExecutionContextRef m_exe_ctx_ref; |
345 | bool m_needs_update; |
346 | }; |
347 | |
348 | virtual ~ValueObject(); |
349 | |
350 | const EvaluationPoint &GetUpdatePoint() const { return m_update_point; } |
351 | |
352 | EvaluationPoint &GetUpdatePoint() { return m_update_point; } |
353 | |
354 | const ExecutionContextRef &GetExecutionContextRef() const { |
355 | return m_update_point.GetExecutionContextRef(); |
356 | } |
357 | |
358 | lldb::TargetSP GetTargetSP() const { |
359 | return m_update_point.GetExecutionContextRef().GetTargetSP(); |
360 | } |
361 | |
362 | lldb::ProcessSP GetProcessSP() const { |
363 | return m_update_point.GetExecutionContextRef().GetProcessSP(); |
364 | } |
365 | |
366 | lldb::ThreadSP GetThreadSP() const { |
367 | return m_update_point.GetExecutionContextRef().GetThreadSP(); |
368 | } |
369 | |
370 | lldb::StackFrameSP GetFrameSP() const { |
371 | return m_update_point.GetExecutionContextRef().GetFrameSP(); |
372 | } |
373 | |
374 | void SetNeedsUpdate(); |
375 | |
376 | CompilerType GetCompilerType(); |
377 | |
378 | // this vends a TypeImpl that is useful at the SB API layer |
379 | virtual TypeImpl GetTypeImpl(); |
380 | |
381 | virtual bool CanProvideValue(); |
382 | |
383 | //------------------------------------------------------------------ |
384 | // Subclasses must implement the functions below. |
385 | //------------------------------------------------------------------ |
386 | virtual uint64_t GetByteSize() = 0; |
387 | |
388 | virtual lldb::ValueType GetValueType() const = 0; |
389 | |
390 | //------------------------------------------------------------------ |
391 | // Subclasses can implement the functions below. |
392 | //------------------------------------------------------------------ |
393 | virtual ConstString GetTypeName(); |
394 | |
395 | virtual ConstString GetDisplayTypeName(); |
396 | |
397 | virtual ConstString GetQualifiedTypeName(); |
398 | |
399 | virtual lldb::LanguageType GetObjectRuntimeLanguage(); |
400 | |
401 | virtual uint32_t |
402 | GetTypeInfo(CompilerType *pointee_or_element_compiler_type = nullptr); |
403 | |
404 | virtual bool IsPointerType(); |
405 | |
406 | virtual bool IsArrayType(); |
407 | |
408 | virtual bool IsScalarType(); |
409 | |
410 | virtual bool IsPointerOrReferenceType(); |
411 | |
412 | virtual bool IsPossibleDynamicType(); |
413 | |
414 | bool IsNilReference(); |
415 | |
416 | bool IsUninitializedReference(); |
417 | |
418 | virtual bool IsBaseClass() { return false; } |
419 | |
420 | bool IsBaseClass(uint32_t &depth); |
421 | |
422 | virtual bool IsDereferenceOfParent() { return false; } |
423 | |
424 | bool IsIntegerType(bool &is_signed); |
425 | |
426 | virtual bool GetBaseClassPath(Stream &s); |
427 | |
428 | virtual void GetExpressionPath( |
429 | Stream &s, bool qualify_cxx_base_classes, |
430 | GetExpressionPathFormat = eGetExpressionPathFormatDereferencePointers); |
431 | |
432 | lldb::ValueObjectSP GetValueForExpressionPath( |
433 | llvm::StringRef expression, |
434 | ExpressionPathScanEndReason *reason_to_stop = nullptr, |
435 | ExpressionPathEndResultType *final_value_type = nullptr, |
436 | const GetValueForExpressionPathOptions &options = |
437 | GetValueForExpressionPathOptions::DefaultOptions(), |
438 | ExpressionPathAftermath *final_task_on_target = nullptr); |
439 | |
440 | virtual bool IsInScope() { return true; } |
441 | |
442 | virtual lldb::offset_t GetByteOffset() { return 0; } |
443 | |
444 | virtual uint32_t GetBitfieldBitSize() { return 0; } |
445 | |
446 | virtual uint32_t GetBitfieldBitOffset() { return 0; } |
447 | |
448 | bool IsBitfield() { |
449 | return (GetBitfieldBitSize() != 0) || (GetBitfieldBitOffset() != 0); |
450 | } |
451 | |
452 | virtual bool IsArrayItemForPointer() { return m_is_array_item_for_pointer; } |
453 | |
454 | virtual const char *GetValueAsCString(); |
455 | |
456 | virtual bool GetValueAsCString(const lldb_private::TypeFormatImpl &format, |
457 | std::string &destination); |
458 | |
459 | bool GetValueAsCString(lldb::Format format, std::string &destination); |
460 | |
461 | virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, |
462 | bool *success = nullptr); |
463 | |
464 | virtual int64_t GetValueAsSigned(int64_t fail_value, bool *success = nullptr); |
465 | |
466 | virtual bool SetValueFromCString(const char *value_str, Status &error); |
467 | |
468 | // Return the module associated with this value object in case the value is |
469 | // from an executable file and might have its data in sections of the file. |
470 | // This can be used for variables. |
471 | virtual lldb::ModuleSP GetModule(); |
472 | |
473 | ValueObject *GetRoot(); |
474 | |
475 | // Given a ValueObject, loop over itself and its parent, and its parent's |
476 | // parent, .. until either the given callback returns false, or you end up at |
477 | // a null pointer |
478 | ValueObject *FollowParentChain(std::function<bool(ValueObject *)>); |
479 | |
480 | virtual bool GetDeclaration(Declaration &decl); |
481 | |
482 | //------------------------------------------------------------------ |
483 | // The functions below should NOT be modified by subclasses |
484 | //------------------------------------------------------------------ |
485 | const Status &GetError(); |
486 | |
487 | const ConstString &GetName() const; |
488 | |
489 | virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx, bool can_create); |
490 | |
491 | // this will always create the children if necessary |
492 | lldb::ValueObjectSP GetChildAtIndexPath(llvm::ArrayRef<size_t> idxs, |
493 | size_t *index_of_error = nullptr); |
494 | |
495 | lldb::ValueObjectSP |
496 | GetChildAtIndexPath(llvm::ArrayRef<std::pair<size_t, bool>> idxs, |
497 | size_t *index_of_error = nullptr); |
498 | |
499 | // this will always create the children if necessary |
500 | lldb::ValueObjectSP GetChildAtNamePath(llvm::ArrayRef<ConstString> names, |
501 | ConstString *name_of_error = nullptr); |
502 | |
503 | lldb::ValueObjectSP |
504 | GetChildAtNamePath(llvm::ArrayRef<std::pair<ConstString, bool>> names, |
505 | ConstString *name_of_error = nullptr); |
506 | |
507 | virtual lldb::ValueObjectSP GetChildMemberWithName(const ConstString &name, |
508 | bool can_create); |
509 | |
510 | virtual size_t GetIndexOfChildWithName(const ConstString &name); |
511 | |
512 | size_t GetNumChildren(uint32_t max = UINT32_MAX(4294967295U)); |
513 | |
514 | const Value &GetValue() const; |
515 | |
516 | Value &GetValue(); |
517 | |
518 | virtual bool ResolveValue(Scalar &scalar); |
519 | |
520 | // return 'false' whenever you set the error, otherwise callers may assume |
521 | // true means everything is OK - this will break breakpoint conditions among |
522 | // potentially a few others |
523 | virtual bool IsLogicalTrue(Status &error); |
524 | |
525 | virtual const char *GetLocationAsCString(); |
526 | |
527 | const char * |
528 | GetSummaryAsCString(lldb::LanguageType lang = lldb::eLanguageTypeUnknown); |
529 | |
530 | bool |
531 | GetSummaryAsCString(TypeSummaryImpl *summary_ptr, std::string &destination, |
532 | lldb::LanguageType lang = lldb::eLanguageTypeUnknown); |
533 | |
534 | bool GetSummaryAsCString(std::string &destination, |
535 | const TypeSummaryOptions &options); |
536 | |
537 | bool GetSummaryAsCString(TypeSummaryImpl *summary_ptr, |
538 | std::string &destination, |
539 | const TypeSummaryOptions &options); |
540 | |
541 | std::pair<TypeValidatorResult, std::string> GetValidationStatus(); |
542 | |
543 | const char *GetObjectDescription(); |
544 | |
545 | bool HasSpecialPrintableRepresentation( |
546 | ValueObjectRepresentationStyle val_obj_display, |
547 | lldb::Format custom_format); |
548 | |
549 | enum class PrintableRepresentationSpecialCases : bool { |
550 | eDisable = false, |
551 | eAllow = true |
552 | }; |
553 | |
554 | bool |
555 | DumpPrintableRepresentation(Stream &s, |
556 | ValueObjectRepresentationStyle val_obj_display = |
557 | eValueObjectRepresentationStyleSummary, |
558 | lldb::Format custom_format = lldb::eFormatInvalid, |
559 | PrintableRepresentationSpecialCases special = |
560 | PrintableRepresentationSpecialCases::eAllow, |
561 | bool do_dump_error = true); |
562 | bool GetValueIsValid() const; |
563 | |
564 | // If you call this on a newly created ValueObject, it will always return |
565 | // false. |
566 | bool GetValueDidChange(); |
567 | |
568 | bool UpdateValueIfNeeded(bool update_format = true); |
569 | |
570 | bool UpdateFormatsIfNeeded(); |
571 | |
572 | lldb::ValueObjectSP GetSP() { return m_manager->GetSharedPointer(this); } |
573 | |
574 | // Change the name of the current ValueObject. Should *not* be used from a |
575 | // synthetic child provider as it would change the name of the non synthetic |
576 | // child as well. |
577 | void SetName(const ConstString &name); |
578 | |
579 | virtual lldb::addr_t GetAddressOf(bool scalar_is_load_address = true, |
580 | AddressType *address_type = nullptr); |
581 | |
582 | lldb::addr_t GetPointerValue(AddressType *address_type = nullptr); |
583 | |
584 | lldb::ValueObjectSP GetSyntheticChild(const ConstString &key) const; |
585 | |
586 | lldb::ValueObjectSP GetSyntheticArrayMember(size_t index, bool can_create); |
587 | |
588 | lldb::ValueObjectSP GetSyntheticBitFieldChild(uint32_t from, uint32_t to, |
589 | bool can_create); |
590 | |
591 | lldb::ValueObjectSP GetSyntheticExpressionPathChild(const char *expression, |
592 | bool can_create); |
593 | |
594 | virtual lldb::ValueObjectSP |
595 | GetSyntheticChildAtOffset(uint32_t offset, const CompilerType &type, |
596 | bool can_create, |
597 | ConstString name_const_str = ConstString()); |
598 | |
599 | virtual lldb::ValueObjectSP |
600 | GetSyntheticBase(uint32_t offset, const CompilerType &type, bool can_create, |
601 | ConstString name_const_str = ConstString()); |
602 | |
603 | virtual lldb::ValueObjectSP GetDynamicValue(lldb::DynamicValueType valueType); |
604 | |
605 | lldb::DynamicValueType GetDynamicValueType(); |
606 | |
607 | virtual lldb::ValueObjectSP GetStaticValue(); |
608 | |
609 | virtual lldb::ValueObjectSP GetNonSyntheticValue(); |
610 | |
611 | lldb::ValueObjectSP GetSyntheticValue(bool use_synthetic = true); |
612 | |
613 | virtual bool HasSyntheticValue(); |
614 | |
615 | virtual bool IsSynthetic() { return false; } |
616 | |
617 | lldb::ValueObjectSP |
618 | GetQualifiedRepresentationIfAvailable(lldb::DynamicValueType dynValue, |
619 | bool synthValue); |
620 | |
621 | virtual lldb::ValueObjectSP CreateConstantValue(const ConstString &name); |
622 | |
623 | virtual lldb::ValueObjectSP Dereference(Status &error); |
624 | |
625 | // Creates a copy of the ValueObject with a new name and setting the current |
626 | // ValueObject as its parent. It should be used when we want to change the |
627 | // name of a ValueObject without modifying the actual ValueObject itself |
628 | // (e.g. sythetic child provider). |
629 | virtual lldb::ValueObjectSP Clone(const ConstString &new_name); |
630 | |
631 | virtual lldb::ValueObjectSP AddressOf(Status &error); |
632 | |
633 | virtual lldb::addr_t GetLiveAddress() { return LLDB_INVALID_ADDRESS(18446744073709551615UL); } |
634 | |
635 | virtual void SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS(18446744073709551615UL), |
636 | AddressType address_type = eAddressTypeLoad) {} |
637 | |
638 | // Find the address of the C++ vtable pointer |
639 | virtual lldb::addr_t GetCPPVTableAddress(AddressType &address_type); |
640 | |
641 | virtual lldb::ValueObjectSP Cast(const CompilerType &compiler_type); |
642 | |
643 | virtual lldb::ValueObjectSP CastPointerType(const char *name, |
644 | CompilerType &ast_type); |
645 | |
646 | virtual lldb::ValueObjectSP CastPointerType(const char *name, |
647 | lldb::TypeSP &type_sp); |
648 | |
649 | // The backing bits of this value object were updated, clear any descriptive |
650 | // string, so we know we have to refetch them |
651 | virtual void ValueUpdated() { |
652 | ClearUserVisibleData(eClearUserVisibleDataItemsValue | |
653 | eClearUserVisibleDataItemsSummary | |
654 | eClearUserVisibleDataItemsDescription); |
655 | } |
656 | |
657 | virtual bool IsDynamic() { return false; } |
658 | |
659 | virtual bool DoesProvideSyntheticValue() { return false; } |
660 | |
661 | virtual bool IsSyntheticChildrenGenerated(); |
662 | |
663 | virtual void SetSyntheticChildrenGenerated(bool b); |
664 | |
665 | virtual SymbolContextScope *GetSymbolContextScope(); |
666 | |
667 | void Dump(Stream &s); |
668 | |
669 | void Dump(Stream &s, const DumpValueObjectOptions &options); |
670 | |
671 | static lldb::ValueObjectSP |
672 | CreateValueObjectFromExpression(llvm::StringRef name, |
673 | llvm::StringRef expression, |
674 | const ExecutionContext &exe_ctx); |
675 | |
676 | static lldb::ValueObjectSP |
677 | CreateValueObjectFromExpression(llvm::StringRef name, |
678 | llvm::StringRef expression, |
679 | const ExecutionContext &exe_ctx, |
680 | const EvaluateExpressionOptions &options); |
681 | |
682 | static lldb::ValueObjectSP |
683 | CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address, |
684 | const ExecutionContext &exe_ctx, |
685 | CompilerType type); |
686 | |
687 | static lldb::ValueObjectSP |
688 | CreateValueObjectFromData(llvm::StringRef name, const DataExtractor &data, |
689 | const ExecutionContext &exe_ctx, CompilerType type); |
690 | |
691 | void LogValueObject(Log *log); |
692 | |
693 | void LogValueObject(Log *log, const DumpValueObjectOptions &options); |
694 | |
695 | lldb::ValueObjectSP Persist(); |
696 | |
697 | // returns true if this is a char* or a char[] if it is a char* and |
698 | // check_pointer is true, it also checks that the pointer is valid |
699 | bool IsCStringContainer(bool check_pointer = false); |
700 | |
701 | std::pair<size_t, bool> |
702 | ReadPointedString(lldb::DataBufferSP &buffer_sp, Status &error, |
703 | uint32_t max_length = 0, bool honor_array = true, |
704 | lldb::Format item_format = lldb::eFormatCharArray); |
705 | |
706 | virtual size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0, |
707 | uint32_t item_count = 1); |
708 | |
709 | virtual uint64_t GetData(DataExtractor &data, Status &error); |
710 | |
711 | virtual bool SetData(DataExtractor &data, Status &error); |
712 | |
713 | virtual bool GetIsConstant() const { return m_update_point.IsConstant(); } |
714 | |
715 | bool NeedsUpdating() { |
716 | const bool accept_invalid_exe_ctx = |
717 | (CanUpdateWithInvalidExecutionContext() == eLazyBoolYes); |
718 | return m_update_point.NeedsUpdating(accept_invalid_exe_ctx); |
719 | } |
720 | |
721 | void SetIsConstant() { m_update_point.SetIsConstant(); } |
722 | |
723 | lldb::Format GetFormat() const; |
724 | |
725 | virtual void SetFormat(lldb::Format format) { |
726 | if (format != m_format) |
727 | ClearUserVisibleData(eClearUserVisibleDataItemsValue); |
728 | m_format = format; |
729 | } |
730 | |
731 | virtual lldb::LanguageType GetPreferredDisplayLanguage(); |
732 | |
733 | void SetPreferredDisplayLanguage(lldb::LanguageType); |
734 | |
735 | lldb::TypeSummaryImplSP GetSummaryFormat() { |
736 | UpdateFormatsIfNeeded(); |
737 | return m_type_summary_sp; |
738 | } |
739 | |
740 | void SetSummaryFormat(lldb::TypeSummaryImplSP format) { |
741 | m_type_summary_sp = format; |
742 | ClearUserVisibleData(eClearUserVisibleDataItemsSummary); |
743 | } |
744 | |
745 | lldb::TypeValidatorImplSP GetValidator() { |
746 | UpdateFormatsIfNeeded(); |
747 | return m_type_validator_sp; |
748 | } |
749 | |
750 | void SetValidator(lldb::TypeValidatorImplSP format) { |
751 | m_type_validator_sp = format; |
752 | ClearUserVisibleData(eClearUserVisibleDataItemsValidator); |
753 | } |
754 | |
755 | void SetValueFormat(lldb::TypeFormatImplSP format) { |
756 | m_type_format_sp = format; |
757 | ClearUserVisibleData(eClearUserVisibleDataItemsValue); |
758 | } |
759 | |
760 | lldb::TypeFormatImplSP GetValueFormat() { |
761 | UpdateFormatsIfNeeded(); |
762 | return m_type_format_sp; |
763 | } |
764 | |
765 | void SetSyntheticChildren(const lldb::SyntheticChildrenSP &synth_sp) { |
766 | if (synth_sp.get() == m_synthetic_children_sp.get()) |
767 | return; |
768 | ClearUserVisibleData(eClearUserVisibleDataItemsSyntheticChildren); |
769 | m_synthetic_children_sp = synth_sp; |
770 | } |
771 | |
772 | lldb::SyntheticChildrenSP GetSyntheticChildren() { |
773 | UpdateFormatsIfNeeded(); |
774 | return m_synthetic_children_sp; |
775 | } |
776 | |
777 | // Use GetParent for display purposes, but if you want to tell the parent to |
778 | // update itself then use m_parent. The ValueObjectDynamicValue's parent is |
779 | // not the correct parent for displaying, they are really siblings, so for |
780 | // display it needs to route through to its grandparent. |
781 | virtual ValueObject *GetParent() { return m_parent; } |
782 | |
783 | virtual const ValueObject *GetParent() const { return m_parent; } |
784 | |
785 | ValueObject *GetNonBaseClassParent(); |
786 | |
787 | void SetAddressTypeOfChildren(AddressType at) { |
788 | m_address_type_of_ptr_or_ref_children = at; |
789 | } |
790 | |
791 | AddressType GetAddressTypeOfChildren(); |
792 | |
793 | void SetHasCompleteType() { m_did_calculate_complete_objc_class_type = true; } |
794 | |
795 | //------------------------------------------------------------------ |
796 | /// Find out if a ValueObject might have children. |
797 | /// |
798 | /// This call is much more efficient than CalculateNumChildren() as |
799 | /// it doesn't need to complete the underlying type. This is designed |
800 | /// to be used in a UI environment in order to detect if the |
801 | /// disclosure triangle should be displayed or not. |
802 | /// |
803 | /// This function returns true for class, union, structure, |
804 | /// pointers, references, arrays and more. Again, it does so without |
805 | /// doing any expensive type completion. |
806 | /// |
807 | /// @return |
808 | /// Returns \b true if the ValueObject might have children, or \b |
809 | /// false otherwise. |
810 | //------------------------------------------------------------------ |
811 | virtual bool MightHaveChildren(); |
812 | |
813 | virtual lldb::VariableSP GetVariable() { return nullptr; } |
814 | |
815 | virtual bool IsRuntimeSupportValue(); |
816 | |
817 | virtual uint64_t GetLanguageFlags(); |
818 | |
819 | virtual void SetLanguageFlags(uint64_t flags); |
820 | |
821 | protected: |
822 | typedef ClusterManager<ValueObject> ValueObjectManager; |
823 | |
824 | class ChildrenManager { |
825 | public: |
826 | ChildrenManager() : m_mutex(), m_children(), m_children_count(0) {} |
827 | |
828 | bool HasChildAtIndex(size_t idx) { |
829 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
830 | return (m_children.find(idx) != m_children.end()); |
831 | } |
832 | |
833 | ValueObject *GetChildAtIndex(size_t idx) { |
834 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
835 | const auto iter = m_children.find(idx); |
836 | return ((iter == m_children.end()) ? nullptr : iter->second); |
837 | } |
838 | |
839 | void SetChildAtIndex(size_t idx, ValueObject *valobj) { |
840 | // we do not need to be mutex-protected to make a pair |
841 | ChildrenPair pair(idx, valobj); |
842 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
843 | m_children.insert(pair); |
844 | } |
845 | |
846 | void SetChildrenCount(size_t count) { Clear(count); } |
847 | |
848 | size_t GetChildrenCount() { return m_children_count; } |
849 | |
850 | void Clear(size_t new_count = 0) { |
851 | std::lock_guard<std::recursive_mutex> guard(m_mutex); |
852 | m_children_count = new_count; |
853 | m_children.clear(); |
854 | } |
855 | |
856 | private: |
857 | typedef std::map<size_t, ValueObject *> ChildrenMap; |
858 | typedef ChildrenMap::iterator ChildrenIterator; |
859 | typedef ChildrenMap::value_type ChildrenPair; |
860 | std::recursive_mutex m_mutex; |
861 | ChildrenMap m_children; |
862 | size_t m_children_count; |
863 | }; |
864 | |
865 | //------------------------------------------------------------------ |
866 | // Classes that inherit from ValueObject can see and modify these |
867 | //------------------------------------------------------------------ |
868 | ValueObject |
869 | *m_parent; // The parent value object, or nullptr if this has no parent |
870 | ValueObject *m_root; // The root of the hierarchy for this ValueObject (or |
871 | // nullptr if never calculated) |
872 | EvaluationPoint m_update_point; // Stores both the stop id and the full |
873 | // context at which this value was last |
874 | // updated. When we are asked to update the value object, we check whether |
875 | // the context & stop id are the same before updating. |
876 | ConstString m_name; // The name of this object |
877 | DataExtractor |
878 | m_data; // A data extractor that can be used to extract the value. |
879 | Value m_value; |
880 | Status |
881 | m_error; // An error object that can describe any errors that occur when |
882 | // updating values. |
883 | std::string m_value_str; // Cached value string that will get cleared if/when |
884 | // the value is updated. |
885 | std::string m_old_value_str; // Cached old value string from the last time the |
886 | // value was gotten |
887 | std::string m_location_str; // Cached location string that will get cleared |
888 | // if/when the value is updated. |
889 | std::string m_summary_str; // Cached summary string that will get cleared |
890 | // if/when the value is updated. |
891 | std::string m_object_desc_str; // Cached result of the "object printer". This |
892 | // differs from the summary |
893 | // in that the summary is consed up by us, the object_desc_string is builtin. |
894 | |
895 | llvm::Optional<std::pair<TypeValidatorResult, std::string>> |
896 | m_validation_result; |
897 | |
898 | CompilerType m_override_type; // If the type of the value object should be |
899 | // overridden, the type to impose. |
900 | |
901 | ValueObjectManager *m_manager; // This object is managed by the root object |
902 | // (any ValueObject that gets created |
903 | // without a parent.) The manager gets passed through all the generations of |
904 | // dependent objects, and will keep the whole cluster of objects alive as |
905 | // long as a shared pointer to any of them has been handed out. Shared |
906 | // pointers to value objects must always be made with the GetSP method. |
907 | |
908 | ChildrenManager m_children; |
909 | std::map<ConstString, ValueObject *> m_synthetic_children; |
910 | |
911 | ValueObject *m_dynamic_value; |
912 | ValueObject *m_synthetic_value; |
913 | ValueObject *m_deref_valobj; |
914 | |
915 | lldb::ValueObjectSP m_addr_of_valobj_sp; // We have to hold onto a shared |
916 | // pointer to this one because it is |
917 | // created |
918 | // as an independent ValueObjectConstResult, which isn't managed by us. |
919 | |
920 | lldb::Format m_format; |
921 | lldb::Format m_last_format; |
922 | uint32_t m_last_format_mgr_revision; |
923 | lldb::TypeSummaryImplSP m_type_summary_sp; |
924 | lldb::TypeFormatImplSP m_type_format_sp; |
925 | lldb::SyntheticChildrenSP m_synthetic_children_sp; |
926 | lldb::TypeValidatorImplSP m_type_validator_sp; |
927 | ProcessModID m_user_id_of_forced_summary; |
928 | AddressType m_address_type_of_ptr_or_ref_children; |
929 | |
930 | llvm::SmallVector<uint8_t, 16> m_value_checksum; |
931 | |
932 | lldb::LanguageType m_preferred_display_language; |
933 | |
934 | uint64_t m_language_flags; |
935 | |
936 | bool m_value_is_valid : 1, m_value_did_change : 1, m_children_count_valid : 1, |
937 | m_old_value_valid : 1, m_is_deref_of_parent : 1, |
938 | m_is_array_item_for_pointer : 1, m_is_bitfield_for_scalar : 1, |
939 | m_is_child_at_offset : 1, m_is_getting_summary : 1, |
940 | m_did_calculate_complete_objc_class_type : 1, |
941 | m_is_synthetic_children_generated : 1; |
942 | |
943 | friend class ValueObjectChild; |
944 | friend class ClangExpressionDeclMap; // For GetValue |
945 | friend class ExpressionVariable; // For SetName |
946 | friend class Target; // For SetName |
947 | friend class ValueObjectConstResultImpl; |
948 | friend class ValueObjectSynthetic; // For ClearUserVisibleData |
949 | |
950 | //------------------------------------------------------------------ |
951 | // Constructors and Destructors |
952 | //------------------------------------------------------------------ |
953 | |
954 | // Use the no-argument constructor to make a constant variable object (with |
955 | // no ExecutionContextScope.) |
956 | |
957 | ValueObject(); |
958 | |
959 | // Use this constructor to create a "root variable object". The ValueObject |
960 | // will be locked to this context through-out its lifespan. |
961 | |
962 | ValueObject(ExecutionContextScope *exe_scope, |
963 | AddressType child_ptr_or_ref_addr_type = eAddressTypeLoad); |
964 | |
965 | // Use this constructor to create a ValueObject owned by another ValueObject. |
966 | // It will inherit the ExecutionContext of its parent. |
967 | |
968 | ValueObject(ValueObject &parent); |
969 | |
970 | ValueObjectManager *GetManager() { return m_manager; } |
971 | |
972 | virtual bool UpdateValue() = 0; |
973 | |
974 | virtual LazyBool CanUpdateWithInvalidExecutionContext() { |
975 | return eLazyBoolCalculate; |
976 | } |
977 | |
978 | virtual void CalculateDynamicValue(lldb::DynamicValueType use_dynamic); |
979 | |
980 | virtual lldb::DynamicValueType GetDynamicValueTypeImpl() { |
981 | return lldb::eNoDynamicValues; |
982 | } |
983 | |
984 | virtual bool HasDynamicValueTypeInfo() { return false; } |
985 | |
986 | virtual void CalculateSyntheticValue(bool use_synthetic = true); |
987 | |
988 | // Should only be called by ValueObject::GetChildAtIndex() Returns a |
989 | // ValueObject managed by this ValueObject's manager. |
990 | virtual ValueObject *CreateChildAtIndex(size_t idx, |
991 | bool synthetic_array_member, |
992 | int32_t synthetic_index); |
993 | |
994 | // Should only be called by ValueObject::GetNumChildren() |
995 | virtual size_t CalculateNumChildren(uint32_t max = UINT32_MAX(4294967295U)) = 0; |
996 | |
997 | void SetNumChildren(size_t num_children); |
998 | |
999 | void SetValueDidChange(bool value_changed); |
1000 | |
1001 | void SetValueIsValid(bool valid); |
1002 | |
1003 | void ClearUserVisibleData( |
1004 | uint32_t items = ValueObject::eClearUserVisibleDataItemsAllStrings); |
1005 | |
1006 | void AddSyntheticChild(const ConstString &key, ValueObject *valobj); |
1007 | |
1008 | DataExtractor &GetDataExtractor(); |
1009 | |
1010 | void ClearDynamicTypeInformation(); |
1011 | |
1012 | //------------------------------------------------------------------ |
1013 | // Subclasses must implement the functions below. |
1014 | //------------------------------------------------------------------ |
1015 | |
1016 | virtual CompilerType GetCompilerTypeImpl() = 0; |
1017 | |
1018 | const char *GetLocationAsCStringImpl(const Value &value, |
1019 | const DataExtractor &data); |
1020 | |
1021 | bool IsChecksumEmpty(); |
1022 | |
1023 | void SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType); |
1024 | |
1025 | private: |
1026 | virtual CompilerType MaybeCalculateCompleteType(); |
1027 | |
1028 | lldb::ValueObjectSP GetValueForExpressionPath_Impl( |
1029 | llvm::StringRef expression_cstr, |
1030 | ExpressionPathScanEndReason *reason_to_stop, |
1031 | ExpressionPathEndResultType *final_value_type, |
1032 | const GetValueForExpressionPathOptions &options, |
1033 | ExpressionPathAftermath *final_task_on_target); |
1034 | |
1035 | DISALLOW_COPY_AND_ASSIGN(ValueObject)ValueObject(const ValueObject &) = delete; const ValueObject &operator=(const ValueObject &) = delete; |
1036 | }; |
1037 | |
1038 | //------------------------------------------------------------------------------ |
1039 | // A value object manager class that is seeded with the static variable value |
1040 | // and it vends the user facing value object. If the type is dynamic it can |
1041 | // vend the dynamic type. If this user type also has a synthetic type |
1042 | // associated with it, it will vend the synthetic type. The class watches the |
1043 | // process' stop |
1044 | // ID and will update the user type when needed. |
1045 | //------------------------------------------------------------------------------ |
1046 | class ValueObjectManager { |
1047 | // The root value object is the static typed variable object. |
1048 | lldb::ValueObjectSP m_root_valobj_sp; |
1049 | // The user value object is the value object the user wants to see. |
1050 | lldb::ValueObjectSP m_user_valobj_sp; |
1051 | lldb::DynamicValueType m_use_dynamic; |
1052 | uint32_t m_stop_id; // The stop ID that m_user_valobj_sp is valid for. |
1053 | bool m_use_synthetic; |
1054 | |
1055 | public: |
1056 | ValueObjectManager() {} |
1057 | |
1058 | ValueObjectManager(lldb::ValueObjectSP in_valobj_sp, |
1059 | lldb::DynamicValueType use_dynamic, bool use_synthetic); |
1060 | |
1061 | bool IsValid() const; |
1062 | |
1063 | lldb::ValueObjectSP GetRootSP() const { return m_root_valobj_sp; } |
1064 | |
1065 | // Gets the correct value object from the root object for a given process |
1066 | // stop ID. If dynamic values are enabled, or if synthetic children are |
1067 | // enabled, the value object that the user wants to see might change while |
1068 | // debugging. |
1069 | lldb::ValueObjectSP GetSP(); |
1070 | |
1071 | void SetUseDynamic(lldb::DynamicValueType use_dynamic); |
1072 | void SetUseSynthetic(bool use_synthetic); |
1073 | lldb::DynamicValueType GetUseDynamic() const { return m_use_dynamic; } |
1074 | bool GetUseSynthetic() const { return m_use_synthetic; } |
1075 | lldb::TargetSP GetTargetSP() const; |
1076 | lldb::ProcessSP GetProcessSP() const; |
1077 | lldb::ThreadSP GetThreadSP() const; |
1078 | lldb::StackFrameSP GetFrameSP() const; |
1079 | }; |
1080 | |
1081 | } // namespace lldb_private |
1082 | |
1083 | #endif // liblldb_ValueObject_h_ |
1 | //===------------------SharedCluster.h --------------------------*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef utility_SharedCluster_h_ |
11 | #define utility_SharedCluster_h_ |
12 | |
13 | #include "lldb/Utility/LLDBAssert.h" |
14 | #include "lldb/Utility/SharingPtr.h" |
15 | |
16 | #include "llvm/ADT/SmallPtrSet.h" |
17 | |
18 | #include <mutex> |
19 | |
20 | namespace lldb_private { |
21 | |
22 | namespace imp { |
23 | template <typename T> |
24 | class shared_ptr_refcount : public lldb_private::imp::shared_count { |
25 | public: |
26 | template <class Y> |
27 | shared_ptr_refcount(Y *in) : shared_count(0), manager(in) {} |
28 | |
29 | shared_ptr_refcount() : shared_count(0) {} |
30 | |
31 | ~shared_ptr_refcount() override {} |
32 | |
33 | void on_zero_shared() override { manager->DecrementRefCount(); } |
34 | |
35 | private: |
36 | T *manager; |
37 | }; |
38 | |
39 | } // namespace imp |
40 | |
41 | template <class T> class ClusterManager { |
42 | public: |
43 | ClusterManager() : m_objects(), m_external_ref(0), m_mutex() {} |
44 | |
45 | ~ClusterManager() { |
46 | for (typename llvm::SmallPtrSet<T *, 16>::iterator pos = m_objects.begin(), |
47 | end = m_objects.end(); |
48 | pos != end; ++pos) { |
49 | T *object = *pos; |
50 | delete object; |
51 | } |
52 | |
53 | // Decrement refcount should have been called on this ClusterManager, and |
54 | // it should have locked the mutex, now we will unlock it before we destroy |
55 | // it... |
56 | m_mutex.unlock(); |
57 | } |
58 | |
59 | void ManageObject(T *new_object) { |
60 | std::lock_guard<std::mutex> guard(m_mutex); |
61 | m_objects.insert(new_object); |
62 | } |
63 | |
64 | typename lldb_private::SharingPtr<T> GetSharedPointer(T *desired_object) { |
65 | { |
66 | std::lock_guard<std::mutex> guard(m_mutex); |
67 | m_external_ref++; |
68 | if (0 == m_objects.count(desired_object)) { |
69 | lldbassert(false && "object not found in shared cluster when expected")lldb_private::lldb_assert(static_cast<bool>(false && "object not found in shared cluster when expected"), "false && \"object not found in shared cluster when expected\"" , __FUNCTION__, "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/include/lldb/Utility/SharedCluster.h" , 69); |
70 | desired_object = nullptr; |
71 | } |
72 | } |
73 | return typename lldb_private::SharingPtr<T>( |
74 | desired_object, new imp::shared_ptr_refcount<ClusterManager>(this)); |
75 | } |
76 | |
77 | private: |
78 | void DecrementRefCount() { |
79 | m_mutex.lock(); |
80 | m_external_ref--; |
81 | if (m_external_ref == 0) |
82 | delete this; |
83 | else |
84 | m_mutex.unlock(); |
85 | } |
86 | |
87 | friend class imp::shared_ptr_refcount<ClusterManager>; |
88 | |
89 | llvm::SmallPtrSet<T *, 16> m_objects; |
90 | int m_external_ref; |
91 | std::mutex m_mutex; |
92 | }; |
93 | |
94 | } // namespace lldb_private |
95 | |
96 | #endif // utility_SharedCluster_h_ |
1 | //===---------------------SharingPtr.h --------------------------*- C++ -*-===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | ||||
10 | #ifndef utility_SharingPtr_h_ | |||
11 | #define utility_SharingPtr_h_ | |||
12 | ||||
13 | // C Includes | |||
14 | // C++ Includes | |||
15 | #include <memory> | |||
16 | ||||
17 | // Microsoft Visual C++ currently does not enable std::atomic to work in CLR | |||
18 | // mode - as such we need to "hack around it" for MSVC++ builds only using | |||
19 | // Windows specific intrinsics instead of the C++11 atomic support | |||
20 | #ifdef _MSC_VER | |||
21 | #include <intrin.h> | |||
22 | #else | |||
23 | #include <atomic> | |||
24 | #endif | |||
25 | ||||
26 | #include <stddef.h> | |||
27 | ||||
28 | // Other libraries and framework includes | |||
29 | // Project includes | |||
30 | ||||
31 | //#define ENABLE_SP_LOGGING 1 // DON'T CHECK THIS LINE IN UNLESS COMMENTED OUT | |||
32 | #if defined(ENABLE_SP_LOGGING) | |||
33 | ||||
34 | extern "C" void track_sp(void *sp_this, void *ptr, long count); | |||
35 | ||||
36 | #endif | |||
37 | ||||
38 | namespace lldb_private { | |||
39 | ||||
40 | namespace imp { | |||
41 | ||||
42 | class shared_count { | |||
43 | shared_count(const shared_count &); | |||
44 | shared_count &operator=(const shared_count &); | |||
45 | ||||
46 | public: | |||
47 | explicit shared_count(long refs = 0) : shared_owners_(refs) {} | |||
48 | ||||
49 | void add_shared(); | |||
50 | void release_shared(); | |||
51 | long use_count() const { return shared_owners_ + 1; } | |||
52 | ||||
53 | protected: | |||
54 | #ifdef _MSC_VER | |||
55 | long shared_owners_; | |||
56 | #else | |||
57 | std::atomic<long> shared_owners_; | |||
58 | #endif | |||
59 | virtual ~shared_count(); | |||
60 | ||||
61 | private: | |||
62 | virtual void on_zero_shared() = 0; | |||
63 | }; | |||
64 | ||||
65 | template <class T> class shared_ptr_pointer : public shared_count { | |||
66 | T data_; | |||
67 | ||||
68 | public: | |||
69 | shared_ptr_pointer(T p) : data_(p) {} | |||
70 | ||||
71 | private: | |||
72 | void on_zero_shared() override; | |||
73 | ||||
74 | // Outlaw copy constructor and assignment operator to keep effective C++ | |||
75 | // warnings down to a minimum | |||
76 | shared_ptr_pointer(const shared_ptr_pointer &); | |||
77 | shared_ptr_pointer &operator=(const shared_ptr_pointer &); | |||
78 | }; | |||
79 | ||||
80 | template <class T> void shared_ptr_pointer<T>::on_zero_shared() { | |||
81 | delete data_; | |||
82 | } | |||
83 | ||||
84 | template <class T> class shared_ptr_emplace : public shared_count { | |||
85 | T data_; | |||
86 | ||||
87 | public: | |||
88 | shared_ptr_emplace() : data_() {} | |||
89 | ||||
90 | template <class A0> shared_ptr_emplace(A0 &a0) : data_(a0) {} | |||
91 | ||||
92 | template <class A0, class A1> | |||
93 | shared_ptr_emplace(A0 &a0, A1 &a1) : data_(a0, a1) {} | |||
94 | ||||
95 | template <class A0, class A1, class A2> | |||
96 | shared_ptr_emplace(A0 &a0, A1 &a1, A2 &a2) : data_(a0, a1, a2) {} | |||
97 | ||||
98 | template <class A0, class A1, class A2, class A3> | |||
99 | shared_ptr_emplace(A0 &a0, A1 &a1, A2 &a2, A3 &a3) : data_(a0, a1, a2, a3) {} | |||
100 | ||||
101 | template <class A0, class A1, class A2, class A3, class A4> | |||
102 | shared_ptr_emplace(A0 &a0, A1 &a1, A2 &a2, A3 &a3, A4 &a4) | |||
103 | : data_(a0, a1, a2, a3, a4) {} | |||
104 | ||||
105 | private: | |||
106 | void on_zero_shared() override; | |||
107 | ||||
108 | public: | |||
109 | T *get() { return &data_; } | |||
110 | }; | |||
111 | ||||
112 | template <class T> void shared_ptr_emplace<T>::on_zero_shared() {} | |||
113 | ||||
114 | } // namespace imp | |||
115 | ||||
116 | template <class T> class SharingPtr { | |||
117 | public: | |||
118 | typedef T element_type; | |||
119 | ||||
120 | private: | |||
121 | element_type *ptr_; | |||
122 | imp::shared_count *cntrl_; | |||
123 | ||||
124 | struct nat { | |||
125 | int for_bool_; | |||
126 | }; | |||
127 | ||||
128 | public: | |||
129 | SharingPtr(); | |||
130 | SharingPtr(std::nullptr_t); | |||
131 | template <class Y> explicit SharingPtr(Y *p); | |||
132 | template <class Y> explicit SharingPtr(Y *p, imp::shared_count *ctrl_block); | |||
133 | template <class Y> SharingPtr(const SharingPtr<Y> &r, element_type *p); | |||
134 | SharingPtr(const SharingPtr &r); | |||
135 | template <class Y> SharingPtr(const SharingPtr<Y> &r); | |||
136 | ||||
137 | ~SharingPtr(); | |||
138 | ||||
139 | SharingPtr &operator=(const SharingPtr &r); | |||
140 | template <class Y> SharingPtr &operator=(const SharingPtr<Y> &r); | |||
141 | ||||
142 | void swap(SharingPtr &r); | |||
143 | void reset(); | |||
144 | template <class Y> void reset(Y *p); | |||
145 | void reset(std::nullptr_t); | |||
146 | ||||
147 | element_type *get() const { return ptr_; } | |||
148 | element_type &operator*() const { return *ptr_; } | |||
| ||||
149 | element_type *operator->() const { return ptr_; } | |||
150 | long use_count() const { return cntrl_ ? cntrl_->use_count() : 0; } | |||
151 | bool unique() const { return use_count() == 1; } | |||
152 | bool empty() const { return cntrl_ == nullptr; } | |||
153 | operator nat *() const { return (nat *)get(); } | |||
154 | ||||
155 | static SharingPtr<T> make_shared(); | |||
156 | ||||
157 | template <class A0> static SharingPtr<T> make_shared(A0 &); | |||
158 | ||||
159 | template <class A0, class A1> static SharingPtr<T> make_shared(A0 &, A1 &); | |||
160 | ||||
161 | template <class A0, class A1, class A2> | |||
162 | static SharingPtr<T> make_shared(A0 &, A1 &, A2 &); | |||
163 | ||||
164 | template <class A0, class A1, class A2, class A3> | |||
165 | static SharingPtr<T> make_shared(A0 &, A1 &, A2 &, A3 &); | |||
166 | ||||
167 | template <class A0, class A1, class A2, class A3, class A4> | |||
168 | static SharingPtr<T> make_shared(A0 &, A1 &, A2 &, A3 &, A4 &); | |||
169 | ||||
170 | private: | |||
171 | template <class U> friend class SharingPtr; | |||
172 | }; | |||
173 | ||||
174 | template <class T> | |||
175 | inline SharingPtr<T>::SharingPtr() : ptr_(nullptr), cntrl_(nullptr) {} | |||
176 | ||||
177 | template <class T> | |||
178 | inline SharingPtr<T>::SharingPtr(std::nullptr_t) | |||
179 | : ptr_(nullptr), cntrl_(nullptr) {} | |||
180 | ||||
181 | template <class T> | |||
182 | template <class Y> | |||
183 | SharingPtr<T>::SharingPtr(Y *p) : ptr_(p), cntrl_(nullptr) { | |||
184 | std::unique_ptr<Y> hold(p); | |||
185 | typedef imp::shared_ptr_pointer<Y *> _CntrlBlk; | |||
186 | cntrl_ = new _CntrlBlk(p); | |||
187 | hold.release(); | |||
188 | } | |||
189 | ||||
190 | template <class T> | |||
191 | template <class Y> | |||
192 | SharingPtr<T>::SharingPtr(Y *p, imp::shared_count *cntrl_block) | |||
193 | : ptr_(p), cntrl_(cntrl_block) {} | |||
194 | ||||
195 | template <class T> | |||
196 | template <class Y> | |||
197 | inline SharingPtr<T>::SharingPtr(const SharingPtr<Y> &r, element_type *p) | |||
198 | : ptr_(p), cntrl_(r.cntrl_) { | |||
199 | if (cntrl_) | |||
200 | cntrl_->add_shared(); | |||
201 | } | |||
202 | ||||
203 | template <class T> | |||
204 | inline SharingPtr<T>::SharingPtr(const SharingPtr &r) | |||
205 | : ptr_(r.ptr_), cntrl_(r.cntrl_) { | |||
206 | if (cntrl_) | |||
207 | cntrl_->add_shared(); | |||
208 | } | |||
209 | ||||
210 | template <class T> | |||
211 | template <class Y> | |||
212 | inline SharingPtr<T>::SharingPtr(const SharingPtr<Y> &r) | |||
213 | : ptr_(r.ptr_), cntrl_(r.cntrl_) { | |||
214 | if (cntrl_) | |||
215 | cntrl_->add_shared(); | |||
216 | } | |||
217 | ||||
218 | template <class T> SharingPtr<T>::~SharingPtr() { | |||
219 | if (cntrl_) | |||
220 | cntrl_->release_shared(); | |||
221 | } | |||
222 | ||||
223 | template <class T> | |||
224 | inline SharingPtr<T> &SharingPtr<T>::operator=(const SharingPtr &r) { | |||
225 | SharingPtr(r).swap(*this); | |||
226 | return *this; | |||
227 | } | |||
228 | ||||
229 | template <class T> | |||
230 | template <class Y> | |||
231 | inline SharingPtr<T> &SharingPtr<T>::operator=(const SharingPtr<Y> &r) { | |||
232 | SharingPtr(r).swap(*this); | |||
233 | return *this; | |||
234 | } | |||
235 | ||||
236 | template <class T> inline void SharingPtr<T>::swap(SharingPtr &r) { | |||
237 | std::swap(ptr_, r.ptr_); | |||
238 | std::swap(cntrl_, r.cntrl_); | |||
239 | } | |||
240 | ||||
241 | template <class T> inline void SharingPtr<T>::reset() { | |||
242 | SharingPtr().swap(*this); | |||
243 | } | |||
244 | ||||
245 | template <class T> inline void SharingPtr<T>::reset(std::nullptr_t p) { | |||
246 | reset(); | |||
247 | } | |||
248 | ||||
249 | template <class T> template <class Y> inline void SharingPtr<T>::reset(Y *p) { | |||
250 | SharingPtr(p).swap(*this); | |||
251 | } | |||
252 | ||||
253 | template <class T> SharingPtr<T> SharingPtr<T>::make_shared() { | |||
254 | typedef imp::shared_ptr_emplace<T> CntrlBlk; | |||
255 | SharingPtr<T> r; | |||
256 | r.cntrl_ = new CntrlBlk(); | |||
257 | r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get(); | |||
258 | return r; | |||
259 | } | |||
260 | ||||
261 | template <class T> | |||
262 | template <class A0> | |||
263 | SharingPtr<T> SharingPtr<T>::make_shared(A0 &a0) { | |||
264 | typedef imp::shared_ptr_emplace<T> CntrlBlk; | |||
265 | SharingPtr<T> r; | |||
266 | r.cntrl_ = new CntrlBlk(a0); | |||
267 | r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get(); | |||
268 | return r; | |||
269 | } | |||
270 | ||||
271 | template <class T> | |||
272 | template <class A0, class A1> | |||
273 | SharingPtr<T> SharingPtr<T>::make_shared(A0 &a0, A1 &a1) { | |||
274 | typedef imp::shared_ptr_emplace<T> CntrlBlk; | |||
275 | SharingPtr<T> r; | |||
276 | r.cntrl_ = new CntrlBlk(a0, a1); | |||
277 | r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get(); | |||
278 | return r; | |||
279 | } | |||
280 | ||||
281 | template <class T> | |||
282 | template <class A0, class A1, class A2> | |||
283 | SharingPtr<T> SharingPtr<T>::make_shared(A0 &a0, A1 &a1, A2 &a2) { | |||
284 | typedef imp::shared_ptr_emplace<T> CntrlBlk; | |||
285 | SharingPtr<T> r; | |||
286 | r.cntrl_ = new CntrlBlk(a0, a1, a2); | |||
287 | r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get(); | |||
288 | return r; | |||
289 | } | |||
290 | ||||
291 | template <class T> | |||
292 | template <class A0, class A1, class A2, class A3> | |||
293 | SharingPtr<T> SharingPtr<T>::make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3) { | |||
294 | typedef imp::shared_ptr_emplace<T> CntrlBlk; | |||
295 | SharingPtr<T> r; | |||
296 | r.cntrl_ = new CntrlBlk(a0, a1, a2, a3); | |||
297 | r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get(); | |||
298 | return r; | |||
299 | } | |||
300 | ||||
301 | template <class T> | |||
302 | template <class A0, class A1, class A2, class A3, class A4> | |||
303 | SharingPtr<T> SharingPtr<T>::make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3, | |||
304 | A4 &a4) { | |||
305 | typedef imp::shared_ptr_emplace<T> CntrlBlk; | |||
306 | SharingPtr<T> r; | |||
307 | r.cntrl_ = new CntrlBlk(a0, a1, a2, a3, a4); | |||
308 | r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get(); | |||
309 | return r; | |||
310 | } | |||
311 | ||||
312 | template <class T> inline SharingPtr<T> make_shared() { | |||
313 | return SharingPtr<T>::make_shared(); | |||
314 | } | |||
315 | ||||
316 | template <class T, class A0> inline SharingPtr<T> make_shared(A0 &a0) { | |||
317 | return SharingPtr<T>::make_shared(a0); | |||
318 | } | |||
319 | ||||
320 | template <class T, class A0, class A1> | |||
321 | inline SharingPtr<T> make_shared(A0 &a0, A1 &a1) { | |||
322 | return SharingPtr<T>::make_shared(a0, a1); | |||
323 | } | |||
324 | ||||
325 | template <class T, class A0, class A1, class A2> | |||
326 | inline SharingPtr<T> make_shared(A0 &a0, A1 &a1, A2 &a2) { | |||
327 | return SharingPtr<T>::make_shared(a0, a1, a2); | |||
328 | } | |||
329 | ||||
330 | template <class T, class A0, class A1, class A2, class A3> | |||
331 | inline SharingPtr<T> make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3) { | |||
332 | return SharingPtr<T>::make_shared(a0, a1, a2, a3); | |||
333 | } | |||
334 | ||||
335 | template <class T, class A0, class A1, class A2, class A3, class A4> | |||
336 | inline SharingPtr<T> make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3, A4 &a4) { | |||
337 | return SharingPtr<T>::make_shared(a0, a1, a2, a3, a4); | |||
338 | } | |||
339 | ||||
340 | template <class T, class U> | |||
341 | inline bool operator==(const SharingPtr<T> &__x, const SharingPtr<U> &__y) { | |||
342 | return __x.get() == __y.get(); | |||
343 | } | |||
344 | ||||
345 | template <class T, class U> | |||
346 | inline bool operator!=(const SharingPtr<T> &__x, const SharingPtr<U> &__y) { | |||
347 | return !(__x == __y); | |||
348 | } | |||
349 | ||||
350 | template <class T, class U> | |||
351 | inline bool operator<(const SharingPtr<T> &__x, const SharingPtr<U> &__y) { | |||
352 | return __x.get() < __y.get(); | |||
353 | } | |||
354 | ||||
355 | template <class T> inline void swap(SharingPtr<T> &__x, SharingPtr<T> &__y) { | |||
356 | __x.swap(__y); | |||
357 | } | |||
358 | ||||
359 | template <class T, class U> | |||
360 | inline SharingPtr<T> static_pointer_cast(const SharingPtr<U> &r) { | |||
361 | return SharingPtr<T>(r, static_cast<T *>(r.get())); | |||
362 | } | |||
363 | ||||
364 | template <class T, class U> | |||
365 | SharingPtr<T> const_pointer_cast(const SharingPtr<U> &r) { | |||
366 | return SharingPtr<T>(r, const_cast<T *>(r.get())); | |||
367 | } | |||
368 | ||||
369 | template <class T> class LoggingSharingPtr : public SharingPtr<T> { | |||
370 | typedef SharingPtr<T> base; | |||
371 | ||||
372 | public: | |||
373 | typedef void (*Callback)(void *, const LoggingSharingPtr &, bool action); | |||
374 | // action: false means increment just happened | |||
375 | // true means decrement is about to happen | |||
376 | ||||
377 | LoggingSharingPtr() : cb_(0), baton_(nullptr) {} | |||
378 | ||||
379 | LoggingSharingPtr(Callback cb, void *baton) : cb_(cb), baton_(baton) { | |||
380 | if (cb_) | |||
381 | cb_(baton_, *this, false); | |||
382 | } | |||
383 | ||||
384 | template <class Y> | |||
385 | LoggingSharingPtr(Y *p) : base(p), cb_(0), baton_(nullptr) {} | |||
386 | ||||
387 | template <class Y> | |||
388 | LoggingSharingPtr(Y *p, Callback cb, void *baton) | |||
389 | : base(p), cb_(cb), baton_(baton) { | |||
390 | if (cb_) | |||
391 | cb_(baton_, *this, false); | |||
392 | } | |||
393 | ||||
394 | ~LoggingSharingPtr() { | |||
395 | if (cb_) | |||
396 | cb_(baton_, *this, true); | |||
397 | } | |||
398 | ||||
399 | LoggingSharingPtr(const LoggingSharingPtr &p) | |||
400 | : base(p), cb_(p.cb_), baton_(p.baton_) { | |||
401 | if (cb_) | |||
402 | cb_(baton_, *this, false); | |||
403 | } | |||
404 | ||||
405 | LoggingSharingPtr &operator=(const LoggingSharingPtr &p) { | |||
406 | if (cb_) | |||
407 | cb_(baton_, *this, true); | |||
408 | base::operator=(p); | |||
409 | cb_ = p.cb_; | |||
410 | baton_ = p.baton_; | |||
411 | if (cb_) | |||
412 | cb_(baton_, *this, false); | |||
413 | return *this; | |||
414 | } | |||
415 | ||||
416 | void reset() { | |||
417 | if (cb_) | |||
418 | cb_(baton_, *this, true); | |||
419 | base::reset(); | |||
420 | } | |||
421 | ||||
422 | template <class Y> void reset(Y *p) { | |||
423 | if (cb_) | |||
424 | cb_(baton_, *this, true); | |||
425 | base::reset(p); | |||
426 | if (cb_) | |||
427 | cb_(baton_, *this, false); | |||
428 | } | |||
429 | ||||
430 | void SetCallback(Callback cb, void *baton) { | |||
431 | cb_ = cb; | |||
432 | baton_ = baton; | |||
433 | } | |||
434 | ||||
435 | void ClearCallback() { | |||
436 | cb_ = 0; | |||
437 | baton_ = 0; | |||
438 | } | |||
439 | ||||
440 | private: | |||
441 | Callback cb_; | |||
442 | void *baton_; | |||
443 | }; | |||
444 | ||||
445 | template <class T> class IntrusiveSharingPtr; | |||
446 | ||||
447 | template <class T> class ReferenceCountedBase { | |||
448 | public: | |||
449 | explicit ReferenceCountedBase() : shared_owners_(-1) {} | |||
450 | ||||
451 | void add_shared(); | |||
452 | ||||
453 | void release_shared(); | |||
454 | ||||
455 | long use_count() const { return shared_owners_ + 1; } | |||
456 | ||||
457 | protected: | |||
458 | long shared_owners_; | |||
459 | ||||
460 | friend class IntrusiveSharingPtr<T>; | |||
461 | ||||
462 | private: | |||
463 | ReferenceCountedBase(const ReferenceCountedBase &); | |||
464 | ReferenceCountedBase &operator=(const ReferenceCountedBase &); | |||
465 | }; | |||
466 | ||||
467 | template <class T> void lldb_private::ReferenceCountedBase<T>::add_shared() { | |||
468 | #ifdef _MSC_VER | |||
469 | _InterlockedIncrement(&shared_owners_); | |||
470 | #else | |||
471 | ++shared_owners_; | |||
472 | #endif | |||
473 | } | |||
474 | ||||
475 | template <class T> | |||
476 | void lldb_private::ReferenceCountedBase<T>::release_shared() { | |||
477 | #ifdef _MSC_VER | |||
478 | if (_InterlockedDecrement(&shared_owners_) == -1) | |||
479 | #else | |||
480 | if (--shared_owners_ == -1) | |||
481 | #endif | |||
482 | delete static_cast<T *>(this); | |||
483 | } | |||
484 | ||||
485 | template <class T> | |||
486 | class ReferenceCountedBaseVirtual : public imp::shared_count { | |||
487 | public: | |||
488 | explicit ReferenceCountedBaseVirtual() : imp::shared_count(-1) {} | |||
489 | ||||
490 | ~ReferenceCountedBaseVirtual() override = default; | |||
491 | ||||
492 | void on_zero_shared() override; | |||
493 | }; | |||
494 | ||||
495 | template <class T> void ReferenceCountedBaseVirtual<T>::on_zero_shared() {} | |||
496 | ||||
497 | template <typename T> class IntrusiveSharingPtr { | |||
498 | public: | |||
499 | typedef T element_type; | |||
500 | ||||
501 | explicit IntrusiveSharingPtr() : ptr_(0) {} | |||
502 | ||||
503 | explicit IntrusiveSharingPtr(T *ptr) : ptr_(ptr) { add_shared(); } | |||
504 | ||||
505 | IntrusiveSharingPtr(const IntrusiveSharingPtr &rhs) : ptr_(rhs.ptr_) { | |||
506 | add_shared(); | |||
507 | } | |||
508 | ||||
509 | template <class X> | |||
510 | IntrusiveSharingPtr(const IntrusiveSharingPtr<X> &rhs) : ptr_(rhs.get()) { | |||
511 | add_shared(); | |||
512 | } | |||
513 | ||||
514 | IntrusiveSharingPtr &operator=(const IntrusiveSharingPtr &rhs) { | |||
515 | reset(rhs.get()); | |||
516 | return *this; | |||
517 | } | |||
518 | ||||
519 | template <class X> | |||
520 | IntrusiveSharingPtr &operator=(const IntrusiveSharingPtr<X> &rhs) { | |||
521 | reset(rhs.get()); | |||
522 | return *this; | |||
523 | } | |||
524 | ||||
525 | IntrusiveSharingPtr &operator=(T *ptr) { | |||
526 | reset(ptr); | |||
527 | return *this; | |||
528 | } | |||
529 | ||||
530 | ~IntrusiveSharingPtr() { | |||
531 | release_shared(); | |||
532 | ptr_ = nullptr; | |||
533 | } | |||
534 | ||||
535 | T &operator*() const { return *ptr_; } | |||
536 | ||||
537 | T *operator->() const { return ptr_; } | |||
538 | ||||
539 | T *get() const { return ptr_; } | |||
540 | ||||
541 | explicit operator bool() const { return ptr_ != 0; } | |||
542 | ||||
543 | void swap(IntrusiveSharingPtr &rhs) { | |||
544 | std::swap(ptr_, rhs.ptr_); | |||
545 | #if defined(ENABLE_SP_LOGGING) | |||
546 | track_sp(this, ptr_, use_count()); | |||
547 | track_sp(&rhs, rhs.ptr_, rhs.use_count()); | |||
548 | #endif | |||
549 | } | |||
550 | ||||
551 | void reset(T *ptr = nullptr) { IntrusiveSharingPtr(ptr).swap(*this); } | |||
552 | ||||
553 | long use_count() const { | |||
554 | if (ptr_) | |||
555 | return ptr_->use_count(); | |||
556 | return 0; | |||
557 | } | |||
558 | ||||
559 | bool unique() const { return use_count() == 1; } | |||
560 | ||||
561 | private: | |||
562 | element_type *ptr_; | |||
563 | ||||
564 | void add_shared() { | |||
565 | if (ptr_) { | |||
566 | ptr_->add_shared(); | |||
567 | #if defined(ENABLE_SP_LOGGING) | |||
568 | track_sp(this, ptr_, ptr_->use_count()); | |||
569 | #endif | |||
570 | } | |||
571 | } | |||
572 | void release_shared() { | |||
573 | if (ptr_) { | |||
574 | #if defined(ENABLE_SP_LOGGING) | |||
575 | track_sp(this, nullptr, ptr_->use_count() - 1); | |||
576 | #endif | |||
577 | ptr_->release_shared(); | |||
578 | } | |||
579 | } | |||
580 | }; | |||
581 | ||||
582 | template <class T, class U> | |||
583 | inline bool operator==(const IntrusiveSharingPtr<T> &lhs, | |||
584 | const IntrusiveSharingPtr<U> &rhs) { | |||
585 | return lhs.get() == rhs.get(); | |||
586 | } | |||
587 | ||||
588 | template <class T, class U> | |||
589 | inline bool operator!=(const IntrusiveSharingPtr<T> &lhs, | |||
590 | const IntrusiveSharingPtr<U> &rhs) { | |||
591 | return lhs.get() != rhs.get(); | |||
592 | } | |||
593 | ||||
594 | template <class T, class U> | |||
595 | inline bool operator==(const IntrusiveSharingPtr<T> &lhs, U *rhs) { | |||
596 | return lhs.get() == rhs; | |||
597 | } | |||
598 | ||||
599 | template <class T, class U> | |||
600 | inline bool operator!=(const IntrusiveSharingPtr<T> &lhs, U *rhs) { | |||
601 | return lhs.get() != rhs; | |||
602 | } | |||
603 | ||||
604 | template <class T, class U> | |||
605 | inline bool operator==(T *lhs, const IntrusiveSharingPtr<U> &rhs) { | |||
606 | return lhs == rhs.get(); | |||
607 | } | |||
608 | ||||
609 | template <class T, class U> | |||
610 | inline bool operator!=(T *lhs, const IntrusiveSharingPtr<U> &rhs) { | |||
611 | return lhs != rhs.get(); | |||
612 | } | |||
613 | ||||
614 | } // namespace lldb_private | |||
615 | ||||
616 | #endif // utility_SharingPtr_h_ |