LLDB mainline
TypeSynthetic.h
Go to the documentation of this file.
1//===-- TypeSynthetic.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_DATAFORMATTERS_TYPESYNTHETIC_H
10#define LLDB_DATAFORMATTERS_TYPESYNTHETIC_H
11
12#include <cstdint>
13
14#include <functional>
15#include <initializer_list>
16#include <memory>
17#include <string>
18#include <vector>
19
21#include "lldb/lldb-public.h"
22
25
26namespace lldb_private {
28protected:
30
31public:
33
34 virtual ~SyntheticChildrenFrontEnd() = default;
35
36 virtual llvm::Expected<uint32_t> CalculateNumChildren() = 0;
37
38 virtual llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) {
39 auto count = CalculateNumChildren();
40 if (!count)
41 return count;
42 return *count <= max ? *count : max;
43 }
44
45 uint32_t CalculateNumChildrenIgnoringErrors(uint32_t max = UINT32_MAX);
46
47 virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) = 0;
48
49 virtual llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) = 0;
50
51 /// This function is assumed to always succeed and if it fails, the front-end
52 /// should know to deal with it in the correct way (most probably, by refusing
53 /// to return any children). The return value of \ref Update should actually
54 /// be interpreted as "ValueObjectSynthetic cache is good/bad". If this
55 /// function returns \ref lldb::ChildCacheState::eReuse, \ref
56 /// ValueObjectSynthetic is allowed to use the children it fetched
57 /// previously and cached. Otherwise, \ref ValueObjectSynthetic must
58 /// throw away its cache, and query again for children.
60
61 // if this function returns false, then CalculateNumChildren() MUST return 0
62 // since UI frontends might validly decide not to inquire for children given
63 // a false return value from this call if it returns true, then
64 // CalculateNumChildren() can return any number >= 0 (0 being valid) it
65 // should if at all possible be more efficient than CalculateNumChildren()
66 virtual bool MightHaveChildren() { return true; }
67
68 // if this function returns a non-null ValueObject, then the returned
69 // ValueObject will stand for this ValueObject whenever a "value" request is
70 // made to this ValueObject
71 virtual lldb::ValueObjectSP GetSyntheticValue() { return nullptr; }
72
73 // if this function returns a non-empty ConstString, then clients are
74 // expected to use the return as the name of the type of this ValueObject for
75 // display purposes
77
78 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
79 typedef std::unique_ptr<SyntheticChildrenFrontEnd> AutoPointer;
80
81protected:
83 CreateValueObjectFromExpression(llvm::StringRef name,
84 llvm::StringRef expression,
85 const ExecutionContext &exe_ctx);
86
88 CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address,
89 const ExecutionContext &exe_ctx,
90 CompilerType type, bool do_deref = true);
91
93 const DataExtractor &data,
94 const ExecutionContext &exe_ctx,
95 CompilerType type);
96
97private:
101};
102
104public:
107
109
110 llvm::Expected<uint32_t> CalculateNumChildren() override { return 0; }
111
112 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override { return nullptr; }
113
114 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {
115 return llvm::createStringError("Type has no child named '%s'",
116 name.AsCString());
117 }
118
122
123 bool MightHaveChildren() override { return false; }
124
126
127private:
129 delete;
132};
133
135public:
136 class Flags {
137 public:
138 Flags() = default;
139
140 Flags(const Flags &other) : m_flags(other.m_flags) {}
141
142 Flags(uint32_t value) : m_flags(value) {}
143
144 Flags &operator=(const Flags &rhs) {
145 if (&rhs != this)
146 m_flags = rhs.m_flags;
147
148 return *this;
149 }
150
151 Flags &operator=(const uint32_t &rhs) {
152 m_flags = rhs;
153 return *this;
154 }
155
157 m_flags = 0;
158 return *this;
159 }
160
161 bool GetCascades() const {
162 return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade;
163 }
164
165 Flags &SetCascades(bool value = true) {
166 if (value)
167 m_flags |= lldb::eTypeOptionCascade;
168 else
169 m_flags &= ~lldb::eTypeOptionCascade;
170 return *this;
171 }
172
173 bool GetSkipPointers() const {
174 return (m_flags & lldb::eTypeOptionSkipPointers) ==
175 lldb::eTypeOptionSkipPointers;
176 }
177
178 Flags &SetSkipPointers(bool value = true) {
179 if (value)
180 m_flags |= lldb::eTypeOptionSkipPointers;
181 else
182 m_flags &= ~lldb::eTypeOptionSkipPointers;
183 return *this;
184 }
185
186 bool GetSkipReferences() const {
187 return (m_flags & lldb::eTypeOptionSkipReferences) ==
188 lldb::eTypeOptionSkipReferences;
189 }
190
191 Flags &SetSkipReferences(bool value = true) {
192 if (value)
193 m_flags |= lldb::eTypeOptionSkipReferences;
194 else
195 m_flags &= ~lldb::eTypeOptionSkipReferences;
196 return *this;
197 }
198
199 bool GetNonCacheable() const {
200 return (m_flags & lldb::eTypeOptionNonCacheable) ==
201 lldb::eTypeOptionNonCacheable;
202 }
203
204 Flags &SetNonCacheable(bool value = true) {
205 if (value)
206 m_flags |= lldb::eTypeOptionNonCacheable;
207 else
208 m_flags &= ~lldb::eTypeOptionNonCacheable;
209 return *this;
210 }
211
213 return (m_flags & lldb::eTypeOptionFrontEndWantsDereference) ==
214 lldb::eTypeOptionFrontEndWantsDereference;
215 }
216
217 Flags &SetFrontEndWantsDereference(bool value = true) {
218 if (value)
219 m_flags |= lldb::eTypeOptionFrontEndWantsDereference;
220 else
221 m_flags &= ~lldb::eTypeOptionFrontEndWantsDereference;
222 return *this;
223 }
224
225 uint32_t GetValue() { return m_flags; }
226
227 void SetValue(uint32_t value) { m_flags = value; }
228
229 private:
230 uint32_t m_flags = lldb::eTypeOptionCascade;
231 };
232
233 SyntheticChildren(const Flags &flags);
234
236
237 bool Cascades() const { return m_flags.GetCascades(); }
238
239 bool SkipsPointers() const { return m_flags.GetSkipPointers(); }
240
241 bool SkipsReferences() const { return m_flags.GetSkipReferences(); }
242
243 bool NonCacheable() const { return m_flags.GetNonCacheable(); }
244
245 bool WantsDereference() const { return m_flags.GetFrontEndWantsDereference();}
246
247 void SetCascades(bool value) { m_flags.SetCascades(value); }
248
249 void SetSkipsPointers(bool value) { m_flags.SetSkipPointers(value); }
250
251 void SetSkipsReferences(bool value) { m_flags.SetSkipReferences(value); }
252
253 void SetNonCacheable(bool value) { m_flags.SetNonCacheable(value); }
254
255 uint32_t GetOptions() { return m_flags.GetValue(); }
256
257 void SetOptions(uint32_t value) { m_flags.SetValue(value); }
258
259 virtual bool IsScripted() = 0;
260
261 virtual std::string GetDescription() = 0;
262
264 GetFrontEnd(ValueObject &backend) = 0;
265
266 typedef std::shared_ptr<SyntheticChildren> SharedPointer;
267
268 uint32_t &GetRevision() { return m_my_revision; }
269
270 uint32_t GetPtrMatchDepth() { return m_ptr_match_depth; }
271
272 void SetPtrMatchDepth(uint32_t value) { m_ptr_match_depth = value; }
273
274protected:
275 uint32_t m_my_revision = 0;
277 uint32_t m_ptr_match_depth = 1;
278
279private:
282};
283
285 std::vector<std::string> m_expression_paths;
286
287public:
290
292 const std::initializer_list<const char *> items)
293 : SyntheticChildren(flags) {
294 for (auto path : items)
295 AddExpressionPath(path);
296 }
297
298 void AddExpressionPath(const char *path) {
299 AddExpressionPath(std::string(path));
300 }
301
302 void Clear() { m_expression_paths.clear(); }
303
304 size_t GetCount() const { return m_expression_paths.size(); }
305
306 const char *GetExpressionPathAtIndex(size_t i) const {
307 return m_expression_paths[i].c_str();
308 }
309
310 bool SetExpressionPathAtIndex(size_t i, const char *path) {
311 return SetExpressionPathAtIndex(i, std::string(path));
312 }
313
314 void AddExpressionPath(const std::string &path);
315
316 bool SetExpressionPathAtIndex(size_t i, const std::string &path);
317
318 bool IsScripted() override { return false; }
319
320 std::string GetDescription() override;
321
323 public:
325 : SyntheticChildrenFrontEnd(backend), filter(flt) {}
326
327 ~FrontEnd() override = default;
328
329 llvm::Expected<uint32_t> CalculateNumChildren() override {
330 return filter->GetCount();
331 }
332
333 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {
334 if (idx >= filter->GetCount())
335 return lldb::ValueObjectSP();
336 return m_backend.GetSyntheticExpressionPathChild(
337 filter->GetExpressionPathAtIndex(idx), true);
338 }
339
343
344 bool MightHaveChildren() override { return filter->GetCount() > 0; }
345
346 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
347
348 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
349
350 private:
352
353 FrontEnd(const FrontEnd &) = delete;
354 const FrontEnd &operator=(const FrontEnd &) = delete;
355 };
356
358 GetFrontEnd(ValueObject &backend) override {
359 return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend));
360 }
361
362 typedef std::shared_ptr<TypeFilterImpl> SharedPointer;
363
364private:
366 const TypeFilterImpl &operator=(const TypeFilterImpl &) = delete;
367};
368
370public:
371 typedef std::function<SyntheticChildrenFrontEnd *(CXXSyntheticChildren *,
375 const char *description, CreateFrontEndCallback callback);
376
378
379 bool IsScripted() override { return false; }
380
381 std::string GetDescription() override;
382
384 GetFrontEnd(ValueObject &backend) override {
386 m_create_callback(this, backend.GetSP()));
387 }
388
389protected:
391 std::string m_description;
392
393private:
396};
397
399 std::string m_python_class;
400 std::string m_python_code;
401
402public:
404 const char *pclass, const char *pcode = nullptr)
405 : SyntheticChildren(flags) {
406 if (pclass)
407 m_python_class = pclass;
408 if (pcode)
409 m_python_code = pcode;
410 }
411
412 const char *GetPythonClassName() { return m_python_class.c_str(); }
413
414 const char *GetPythonCode() { return m_python_code.c_str(); }
415
416 void SetPythonClassName(const char *fname) {
417 m_python_class.assign(fname);
418 m_python_code.clear();
419 }
420
421 void SetPythonCode(const char *script) { m_python_code.assign(script); }
422
423 std::string GetDescription() override;
424
425 bool IsScripted() override { return true; }
426
428 public:
429 FrontEnd(std::string pclass, ValueObject &backend);
430
431 ~FrontEnd() override;
432
433 bool IsValid();
434
435 llvm::Expected<uint32_t> CalculateNumChildren() override;
436
437 llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
438
439 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
440
441 lldb::ChildCacheState Update() override;
442
443 bool MightHaveChildren() override;
444
445 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
446
448
450
451 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
452
453 private:
454 std::string m_python_class;
457
458 FrontEnd(const FrontEnd &) = delete;
459 const FrontEnd &operator=(const FrontEnd &) = delete;
460 };
461
463 GetFrontEnd(ValueObject &backend) override {
465 new FrontEnd(m_python_class, backend));
466 if (synth_ptr && ((FrontEnd *)synth_ptr.get())->IsValid())
467 return synth_ptr;
468 return nullptr;
469 }
470
471private:
475};
476} // namespace lldb_private
477
478#endif // LLDB_DATAFORMATTERS_TYPESYNTHETIC_H
CXXSyntheticChildren(const CXXSyntheticChildren &)=delete
const CXXSyntheticChildren & operator=(const CXXSyntheticChildren &)=delete
CreateFrontEndCallback m_create_callback
std::string GetDescription() override
SyntheticChildrenFrontEnd::AutoPointer GetFrontEnd(ValueObject &backend) override
CXXSyntheticChildren(const SyntheticChildren::Flags &flags, const char *description, CreateFrontEndCallback callback)
std::function< SyntheticChildrenFrontEnd *(CXXSyntheticChildren *, lldb::ValueObjectSP)> CreateFrontEndCallback
Generic representation of a type in a programming language.
A uniqued constant string class.
Definition ConstString.h:40
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
An data extractor class.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
llvm::Expected< size_t > GetIndexOfChildWithName(ConstString name) override
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
std::shared_ptr< SyntheticChildrenFrontEnd > SharedPointer
FrontEnd(std::string pclass, ValueObject &backend)
llvm::Expected< uint32_t > CalculateNumChildren() override
const FrontEnd & operator=(const FrontEnd &)=delete
SyntheticChildrenFrontEnd::AutoPointer GetFrontEnd(ValueObject &backend) override
void SetPythonClassName(const char *fname)
ScriptedSyntheticChildren(const SyntheticChildren::Flags &flags, const char *pclass, const char *pcode=nullptr)
const ScriptedSyntheticChildren & operator=(const ScriptedSyntheticChildren &)=delete
void SetPythonCode(const char *script)
ScriptedSyntheticChildren(const ScriptedSyntheticChildren &)=delete
std::shared_ptr< Object > ObjectSP
uint32_t CalculateNumChildrenIgnoringErrors(uint32_t max=UINT32_MAX)
virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx)=0
virtual lldb::ChildCacheState Update()=0
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
lldb::ValueObjectSP CreateValueObjectFromExpression(llvm::StringRef name, llvm::StringRef expression, const ExecutionContext &exe_ctx)
virtual lldb::ValueObjectSP GetSyntheticValue()
virtual llvm::Expected< uint32_t > CalculateNumChildren(uint32_t max)
std::unique_ptr< SyntheticChildrenFrontEnd > AutoPointer
lldb::ValueObjectSP CreateValueObjectFromData(llvm::StringRef name, const DataExtractor &data, const ExecutionContext &exe_ctx, CompilerType type)
std::shared_ptr< SyntheticChildrenFrontEnd > SharedPointer
virtual llvm::Expected< uint32_t > CalculateNumChildren()=0
virtual ConstString GetSyntheticTypeName()
SyntheticChildrenFrontEnd(const SyntheticChildrenFrontEnd &)=delete
virtual llvm::Expected< size_t > GetIndexOfChildWithName(ConstString name)=0
SyntheticChildrenFrontEnd(ValueObject &backend)
const SyntheticChildrenFrontEnd & operator=(const SyntheticChildrenFrontEnd &)=delete
lldb::ValueObjectSP CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, CompilerType type, bool do_deref=true)
Flags & SetSkipReferences(bool value=true)
Flags & SetFrontEndWantsDereference(bool value=true)
Flags & operator=(const uint32_t &rhs)
Flags & SetSkipPointers(bool value=true)
Flags & SetCascades(bool value=true)
Flags & SetNonCacheable(bool value=true)
Flags & operator=(const Flags &rhs)
const SyntheticChildren & operator=(const SyntheticChildren &)=delete
virtual std::string GetDescription()=0
virtual SyntheticChildrenFrontEnd::AutoPointer GetFrontEnd(ValueObject &backend)=0
void SetPtrMatchDepth(uint32_t value)
SyntheticChildren(const Flags &flags)
void SetOptions(uint32_t value)
SyntheticChildren(const SyntheticChildren &)=delete
std::shared_ptr< SyntheticChildren > SharedPointer
llvm::Expected< size_t > GetIndexOfChildWithName(ConstString name) override
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
llvm::Expected< uint32_t > CalculateNumChildren() override
SyntheticValueProviderFrontEnd(const SyntheticValueProviderFrontEnd &)=delete
lldb::ValueObjectSP GetSyntheticValue() override=0
const SyntheticValueProviderFrontEnd & operator=(const SyntheticValueProviderFrontEnd &)=delete
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
FrontEnd(const FrontEnd &)=delete
llvm::Expected< size_t > GetIndexOfChildWithName(ConstString name) override
llvm::Expected< uint32_t > CalculateNumChildren() override
FrontEnd(TypeFilterImpl *flt, ValueObject &backend)
const FrontEnd & operator=(const FrontEnd &)=delete
std::shared_ptr< SyntheticChildrenFrontEnd > SharedPointer
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
std::shared_ptr< TypeFilterImpl > SharedPointer
bool SetExpressionPathAtIndex(size_t i, const char *path)
const char * GetExpressionPathAtIndex(size_t i) const
TypeFilterImpl(const SyntheticChildren::Flags &flags, const std::initializer_list< const char * > items)
void AddExpressionPath(const char *path)
std::string GetDescription() override
SyntheticChildrenFrontEnd::AutoPointer GetFrontEnd(ValueObject &backend) override
TypeFilterImpl(const SyntheticChildren::Flags &flags)
std::vector< std::string > m_expression_paths
const TypeFilterImpl & operator=(const TypeFilterImpl &)=delete
TypeFilterImpl(const TypeFilterImpl &)=delete
lldb::ValueObjectSP GetSP()
#define UINT32_MAX
A class that represents a running process on the host machine.
ChildCacheState
Specifies if children need to be re-computed after a call to SyntheticChildrenFrontEnd::Update.
@ eRefetch
Children need to be recomputed dynamically.
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP