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