Bug Summary

File:tools/lldb/include/lldb/Utility/SharingPtr.h
Warning:line 148, column 37
Returning null reference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name LibStdcppUniquePointer.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-8/lib/clang/8.0.0 -D HAVE_ROUND -D LLDB_CONFIGURATION_RELEASE -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/lldb/source/Plugins/Language/CPlusPlus -I /build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Language/CPlusPlus -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/lldb/include -I /build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/include -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/include -I /build/llvm-toolchain-snapshot-8~svn345461/include -I /usr/include/python2.7 -I /build/llvm-toolchain-snapshot-8~svn345461/tools/clang/include -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/. -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/include/clang/8.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-8/lib/clang/8.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-deprecated-register -Wno-vla-extension -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/lldb/source/Plugins/Language/CPlusPlus -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-10-27-211344-32123-1 -x c++ /build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp -faddrsig

/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp

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
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 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
42private:
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
52LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd(
53 lldb::ValueObjectSP valobj_sp)
54 : SyntheticChildrenFrontEnd(*valobj_sp) {
13
Calling 'SharingPtr::operator*'
55 Update();
56}
57
58ValueObjectSP 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
85bool 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
113bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; }
114
115lldb::ValueObjectSP
116LibStdcppUniquePtrSyntheticFrontEnd::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
126size_t LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() {
127 if (m_del_obj)
128 return 2;
129 return 1;
130}
131
132size_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
144bool 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
160SyntheticChildrenFrontEnd *
161lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator(
162 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
163 return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp)
164 : nullptr);
165}
166
167bool lldb_private::formatters::LibStdcppUniquePointerSummaryProvider(
168 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
169 LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP());
1
Calling 'ValueObject::GetSP'
11
Returning from 'ValueObject::GetSP'
12
Calling constructor for 'LibStdcppUniquePtrSyntheticFrontEnd'
170 return formatter.GetSummary(stream, options);
171}

/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/include/lldb/Core/ValueObject.h

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
43namespace lldb_private {
44class Declaration;
45}
46namespace lldb_private {
47class DumpValueObjectOptions;
48}
49namespace lldb_private {
50class EvaluateExpressionOptions;
51}
52namespace lldb_private {
53class ExecutionContextScope;
54}
55namespace lldb_private {
56class Log;
57}
58namespace lldb_private {
59class Scalar;
60}
61namespace lldb_private {
62class Stream;
63}
64namespace lldb_private {
65class SymbolContextScope;
66}
67namespace lldb_private {
68class TypeFormatImpl;
69}
70namespace lldb_private {
71class TypeSummaryImpl;
72}
73namespace lldb_private {
74class TypeSummaryOptions;
75}
76namespace 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
127class ValueObject : public UserID {
128public:
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); }
2
Calling 'ClusterManager::GetSharedPointer'
10
Returning from 'ClusterManager::GetSharedPointer'
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
821protected:
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
1025private:
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//------------------------------------------------------------------------------
1046class 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
1055public:
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_

/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/include/lldb/Utility/SharedCluster.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
20namespace lldb_private {
21
22namespace imp {
23template <typename T>
24class shared_ptr_refcount : public lldb_private::imp::shared_count {
25public:
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
35private:
36 T *manager;
37};
38
39} // namespace imp
40
41template <class T> class ClusterManager {
42public:
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)) {
3
Assuming the condition is true
4
Taking true branch
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;
5
Null pointer value stored to 'desired_object'
71 }
72 }
73 return typename lldb_private::SharingPtr<T>(
7
Calling constructor for 'SharingPtr<lldb_private::ValueObject>'
9
Returning from constructor for 'SharingPtr<lldb_private::ValueObject>'
74 desired_object, new imp::shared_ptr_refcount<ClusterManager>(this));
6
Passing null pointer value via 1st parameter 'p'
75 }
76
77private:
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_

/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/include/lldb/Utility/SharingPtr.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
34extern "C" void track_sp(void *sp_this, void *ptr, long count);
35
36#endif
37
38namespace lldb_private {
39
40namespace imp {
41
42class shared_count {
43 shared_count(const shared_count &);
44 shared_count &operator=(const shared_count &);
45
46public:
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
53protected:
54#ifdef _MSC_VER
55 long shared_owners_;
56#else
57 std::atomic<long> shared_owners_;
58#endif
59 virtual ~shared_count();
60
61private:
62 virtual void on_zero_shared() = 0;
63};
64
65template <class T> class shared_ptr_pointer : public shared_count {
66 T data_;
67
68public:
69 shared_ptr_pointer(T p) : data_(p) {}
70
71private:
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
80template <class T> void shared_ptr_pointer<T>::on_zero_shared() {
81 delete data_;
82}
83
84template <class T> class shared_ptr_emplace : public shared_count {
85 T data_;
86
87public:
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
105private:
106 void on_zero_shared() override;
107
108public:
109 T *get() { return &data_; }
110};
111
112template <class T> void shared_ptr_emplace<T>::on_zero_shared() {}
113
114} // namespace imp
115
116template <class T> class SharingPtr {
117public:
118 typedef T element_type;
119
120private:
121 element_type *ptr_;
122 imp::shared_count *cntrl_;
123
124 struct nat {
125 int for_bool_;
126 };
127
128public:
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_; }
14
Returning null reference
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
170private:
171 template <class U> friend class SharingPtr;
172};
173
174template <class T>
175inline SharingPtr<T>::SharingPtr() : ptr_(nullptr), cntrl_(nullptr) {}
176
177template <class T>
178inline SharingPtr<T>::SharingPtr(std::nullptr_t)
179 : ptr_(nullptr), cntrl_(nullptr) {}
180
181template <class T>
182template <class Y>
183SharingPtr<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
190template <class T>
191template <class Y>
192SharingPtr<T>::SharingPtr(Y *p, imp::shared_count *cntrl_block)
193 : ptr_(p), cntrl_(cntrl_block) {}
8
Null pointer value stored to 'valobj_sp.ptr_'
194
195template <class T>
196template <class Y>
197inline 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
203template <class T>
204inline SharingPtr<T>::SharingPtr(const SharingPtr &r)
205 : ptr_(r.ptr_), cntrl_(r.cntrl_) {
206 if (cntrl_)
207 cntrl_->add_shared();
208}
209
210template <class T>
211template <class Y>
212inline SharingPtr<T>::SharingPtr(const SharingPtr<Y> &r)
213 : ptr_(r.ptr_), cntrl_(r.cntrl_) {
214 if (cntrl_)
215 cntrl_->add_shared();
216}
217
218template <class T> SharingPtr<T>::~SharingPtr() {
219 if (cntrl_)
220 cntrl_->release_shared();
221}
222
223template <class T>
224inline SharingPtr<T> &SharingPtr<T>::operator=(const SharingPtr &r) {
225 SharingPtr(r).swap(*this);
226 return *this;
227}
228
229template <class T>
230template <class Y>
231inline SharingPtr<T> &SharingPtr<T>::operator=(const SharingPtr<Y> &r) {
232 SharingPtr(r).swap(*this);
233 return *this;
234}
235
236template <class T> inline void SharingPtr<T>::swap(SharingPtr &r) {
237 std::swap(ptr_, r.ptr_);
238 std::swap(cntrl_, r.cntrl_);
239}
240
241template <class T> inline void SharingPtr<T>::reset() {
242 SharingPtr().swap(*this);
243}
244
245template <class T> inline void SharingPtr<T>::reset(std::nullptr_t p) {
246 reset();
247}
248
249template <class T> template <class Y> inline void SharingPtr<T>::reset(Y *p) {
250 SharingPtr(p).swap(*this);
251}
252
253template <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
261template <class T>
262template <class A0>
263SharingPtr<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
271template <class T>
272template <class A0, class A1>
273SharingPtr<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
281template <class T>
282template <class A0, class A1, class A2>
283SharingPtr<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
291template <class T>
292template <class A0, class A1, class A2, class A3>
293SharingPtr<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
301template <class T>
302template <class A0, class A1, class A2, class A3, class A4>
303SharingPtr<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
312template <class T> inline SharingPtr<T> make_shared() {
313 return SharingPtr<T>::make_shared();
314}
315
316template <class T, class A0> inline SharingPtr<T> make_shared(A0 &a0) {
317 return SharingPtr<T>::make_shared(a0);
318}
319
320template <class T, class A0, class A1>
321inline SharingPtr<T> make_shared(A0 &a0, A1 &a1) {
322 return SharingPtr<T>::make_shared(a0, a1);
323}
324
325template <class T, class A0, class A1, class A2>
326inline SharingPtr<T> make_shared(A0 &a0, A1 &a1, A2 &a2) {
327 return SharingPtr<T>::make_shared(a0, a1, a2);
328}
329
330template <class T, class A0, class A1, class A2, class A3>
331inline SharingPtr<T> make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3) {
332 return SharingPtr<T>::make_shared(a0, a1, a2, a3);
333}
334
335template <class T, class A0, class A1, class A2, class A3, class A4>
336inline 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
340template <class T, class U>
341inline bool operator==(const SharingPtr<T> &__x, const SharingPtr<U> &__y) {
342 return __x.get() == __y.get();
343}
344
345template <class T, class U>
346inline bool operator!=(const SharingPtr<T> &__x, const SharingPtr<U> &__y) {
347 return !(__x == __y);
348}
349
350template <class T, class U>
351inline bool operator<(const SharingPtr<T> &__x, const SharingPtr<U> &__y) {
352 return __x.get() < __y.get();
353}
354
355template <class T> inline void swap(SharingPtr<T> &__x, SharingPtr<T> &__y) {
356 __x.swap(__y);
357}
358
359template <class T, class U>
360inline SharingPtr<T> static_pointer_cast(const SharingPtr<U> &r) {
361 return SharingPtr<T>(r, static_cast<T *>(r.get()));
362}
363
364template <class T, class U>
365SharingPtr<T> const_pointer_cast(const SharingPtr<U> &r) {
366 return SharingPtr<T>(r, const_cast<T *>(r.get()));
367}
368
369template <class T> class LoggingSharingPtr : public SharingPtr<T> {
370 typedef SharingPtr<T> base;
371
372public:
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
440private:
441 Callback cb_;
442 void *baton_;
443};
444
445template <class T> class IntrusiveSharingPtr;
446
447template <class T> class ReferenceCountedBase {
448public:
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
457protected:
458 long shared_owners_;
459
460 friend class IntrusiveSharingPtr<T>;
461
462private:
463 ReferenceCountedBase(const ReferenceCountedBase &);
464 ReferenceCountedBase &operator=(const ReferenceCountedBase &);
465};
466
467template <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
475template <class T>
476void 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
485template <class T>
486class ReferenceCountedBaseVirtual : public imp::shared_count {
487public:
488 explicit ReferenceCountedBaseVirtual() : imp::shared_count(-1) {}
489
490 ~ReferenceCountedBaseVirtual() override = default;
491
492 void on_zero_shared() override;
493};
494
495template <class T> void ReferenceCountedBaseVirtual<T>::on_zero_shared() {}
496
497template <typename T> class IntrusiveSharingPtr {
498public:
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
561private:
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
582template <class T, class U>
583inline bool operator==(const IntrusiveSharingPtr<T> &lhs,
584 const IntrusiveSharingPtr<U> &rhs) {
585 return lhs.get() == rhs.get();
586}
587
588template <class T, class U>
589inline bool operator!=(const IntrusiveSharingPtr<T> &lhs,
590 const IntrusiveSharingPtr<U> &rhs) {
591 return lhs.get() != rhs.get();
592}
593
594template <class T, class U>
595inline bool operator==(const IntrusiveSharingPtr<T> &lhs, U *rhs) {
596 return lhs.get() == rhs;
597}
598
599template <class T, class U>
600inline bool operator!=(const IntrusiveSharingPtr<T> &lhs, U *rhs) {
601 return lhs.get() != rhs;
602}
603
604template <class T, class U>
605inline bool operator==(T *lhs, const IntrusiveSharingPtr<U> &rhs) {
606 return lhs == rhs.get();
607}
608
609template <class T, class U>
610inline 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_