File indexing completed on 2026-05-10 08:42:47
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLDB_DATAFORMATTERS_TYPESYNTHETIC_H
0010 #define LLDB_DATAFORMATTERS_TYPESYNTHETIC_H
0011
0012 #include <cstdint>
0013
0014 #include <functional>
0015 #include <initializer_list>
0016 #include <memory>
0017 #include <string>
0018 #include <vector>
0019
0020 #include "lldb/lldb-enumerations.h"
0021 #include "lldb/lldb-public.h"
0022
0023 #include "lldb/Utility/StructuredData.h"
0024 #include "lldb/ValueObject/ValueObject.h"
0025
0026 namespace lldb_private {
0027 class SyntheticChildrenFrontEnd {
0028 protected:
0029 ValueObject &m_backend;
0030
0031 void SetValid(bool valid) { m_valid = valid; }
0032
0033 bool IsValid() { return m_valid; }
0034
0035 public:
0036 SyntheticChildrenFrontEnd(ValueObject &backend)
0037 : m_backend(backend), m_valid(true) {}
0038
0039 virtual ~SyntheticChildrenFrontEnd() = default;
0040
0041 virtual llvm::Expected<uint32_t> CalculateNumChildren() = 0;
0042
0043 virtual llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) {
0044 auto count = CalculateNumChildren();
0045 if (!count)
0046 return count;
0047 return *count <= max ? *count : max;
0048 }
0049
0050 uint32_t CalculateNumChildrenIgnoringErrors(uint32_t max = UINT32_MAX);
0051
0052 virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) = 0;
0053
0054 virtual size_t GetIndexOfChildWithName(ConstString name) = 0;
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 virtual lldb::ChildCacheState Update() = 0;
0065
0066
0067
0068
0069
0070
0071 virtual bool MightHaveChildren() = 0;
0072
0073
0074
0075
0076 virtual lldb::ValueObjectSP GetSyntheticValue() { return nullptr; }
0077
0078
0079
0080
0081 virtual ConstString GetSyntheticTypeName() { return ConstString(); }
0082
0083 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
0084 typedef std::unique_ptr<SyntheticChildrenFrontEnd> AutoPointer;
0085
0086 protected:
0087 lldb::ValueObjectSP
0088 CreateValueObjectFromExpression(llvm::StringRef name,
0089 llvm::StringRef expression,
0090 const ExecutionContext &exe_ctx);
0091
0092 lldb::ValueObjectSP
0093 CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address,
0094 const ExecutionContext &exe_ctx,
0095 CompilerType type);
0096
0097 lldb::ValueObjectSP CreateValueObjectFromData(llvm::StringRef name,
0098 const DataExtractor &data,
0099 const ExecutionContext &exe_ctx,
0100 CompilerType type);
0101
0102 private:
0103 bool m_valid;
0104 SyntheticChildrenFrontEnd(const SyntheticChildrenFrontEnd &) = delete;
0105 const SyntheticChildrenFrontEnd &
0106 operator=(const SyntheticChildrenFrontEnd &) = delete;
0107 };
0108
0109 class SyntheticValueProviderFrontEnd : public SyntheticChildrenFrontEnd {
0110 public:
0111 SyntheticValueProviderFrontEnd(ValueObject &backend)
0112 : SyntheticChildrenFrontEnd(backend) {}
0113
0114 ~SyntheticValueProviderFrontEnd() override = default;
0115
0116 llvm::Expected<uint32_t> CalculateNumChildren() override { return 0; }
0117
0118 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override { return nullptr; }
0119
0120 size_t GetIndexOfChildWithName(ConstString name) override {
0121 return UINT32_MAX;
0122 }
0123
0124 lldb::ChildCacheState Update() override {
0125 return lldb::ChildCacheState::eRefetch;
0126 }
0127
0128 bool MightHaveChildren() override { return false; }
0129
0130 lldb::ValueObjectSP GetSyntheticValue() override = 0;
0131
0132 private:
0133 SyntheticValueProviderFrontEnd(const SyntheticValueProviderFrontEnd &) =
0134 delete;
0135 const SyntheticValueProviderFrontEnd &
0136 operator=(const SyntheticValueProviderFrontEnd &) = delete;
0137 };
0138
0139 class SyntheticChildren {
0140 public:
0141 class Flags {
0142 public:
0143 Flags() = default;
0144
0145 Flags(const Flags &other) : m_flags(other.m_flags) {}
0146
0147 Flags(uint32_t value) : m_flags(value) {}
0148
0149 Flags &operator=(const Flags &rhs) {
0150 if (&rhs != this)
0151 m_flags = rhs.m_flags;
0152
0153 return *this;
0154 }
0155
0156 Flags &operator=(const uint32_t &rhs) {
0157 m_flags = rhs;
0158 return *this;
0159 }
0160
0161 Flags &Clear() {
0162 m_flags = 0;
0163 return *this;
0164 }
0165
0166 bool GetCascades() const {
0167 return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade;
0168 }
0169
0170 Flags &SetCascades(bool value = true) {
0171 if (value)
0172 m_flags |= lldb::eTypeOptionCascade;
0173 else
0174 m_flags &= ~lldb::eTypeOptionCascade;
0175 return *this;
0176 }
0177
0178 bool GetSkipPointers() const {
0179 return (m_flags & lldb::eTypeOptionSkipPointers) ==
0180 lldb::eTypeOptionSkipPointers;
0181 }
0182
0183 Flags &SetSkipPointers(bool value = true) {
0184 if (value)
0185 m_flags |= lldb::eTypeOptionSkipPointers;
0186 else
0187 m_flags &= ~lldb::eTypeOptionSkipPointers;
0188 return *this;
0189 }
0190
0191 bool GetSkipReferences() const {
0192 return (m_flags & lldb::eTypeOptionSkipReferences) ==
0193 lldb::eTypeOptionSkipReferences;
0194 }
0195
0196 Flags &SetSkipReferences(bool value = true) {
0197 if (value)
0198 m_flags |= lldb::eTypeOptionSkipReferences;
0199 else
0200 m_flags &= ~lldb::eTypeOptionSkipReferences;
0201 return *this;
0202 }
0203
0204 bool GetNonCacheable() const {
0205 return (m_flags & lldb::eTypeOptionNonCacheable) ==
0206 lldb::eTypeOptionNonCacheable;
0207 }
0208
0209 Flags &SetNonCacheable(bool value = true) {
0210 if (value)
0211 m_flags |= lldb::eTypeOptionNonCacheable;
0212 else
0213 m_flags &= ~lldb::eTypeOptionNonCacheable;
0214 return *this;
0215 }
0216
0217 bool GetFrontEndWantsDereference() const {
0218 return (m_flags & lldb::eTypeOptionFrontEndWantsDereference) ==
0219 lldb::eTypeOptionFrontEndWantsDereference;
0220 }
0221
0222 Flags &SetFrontEndWantsDereference(bool value = true) {
0223 if (value)
0224 m_flags |= lldb::eTypeOptionFrontEndWantsDereference;
0225 else
0226 m_flags &= ~lldb::eTypeOptionFrontEndWantsDereference;
0227 return *this;
0228 }
0229
0230 uint32_t GetValue() { return m_flags; }
0231
0232 void SetValue(uint32_t value) { m_flags = value; }
0233
0234 private:
0235 uint32_t m_flags = lldb::eTypeOptionCascade;
0236 };
0237
0238 SyntheticChildren(const Flags &flags);
0239
0240 virtual ~SyntheticChildren();
0241
0242 bool Cascades() const { return m_flags.GetCascades(); }
0243
0244 bool SkipsPointers() const { return m_flags.GetSkipPointers(); }
0245
0246 bool SkipsReferences() const { return m_flags.GetSkipReferences(); }
0247
0248 bool NonCacheable() const { return m_flags.GetNonCacheable(); }
0249
0250 bool WantsDereference() const { return m_flags.GetFrontEndWantsDereference();}
0251
0252 void SetCascades(bool value) { m_flags.SetCascades(value); }
0253
0254 void SetSkipsPointers(bool value) { m_flags.SetSkipPointers(value); }
0255
0256 void SetSkipsReferences(bool value) { m_flags.SetSkipReferences(value); }
0257
0258 void SetNonCacheable(bool value) { m_flags.SetNonCacheable(value); }
0259
0260 uint32_t GetOptions() { return m_flags.GetValue(); }
0261
0262 void SetOptions(uint32_t value) { m_flags.SetValue(value); }
0263
0264 virtual bool IsScripted() = 0;
0265
0266 virtual std::string GetDescription() = 0;
0267
0268 virtual SyntheticChildrenFrontEnd::AutoPointer
0269 GetFrontEnd(ValueObject &backend) = 0;
0270
0271 typedef std::shared_ptr<SyntheticChildren> SharedPointer;
0272
0273 uint32_t &GetRevision() { return m_my_revision; }
0274
0275 protected:
0276 uint32_t m_my_revision = 0;
0277 Flags m_flags;
0278
0279 private:
0280 SyntheticChildren(const SyntheticChildren &) = delete;
0281 const SyntheticChildren &operator=(const SyntheticChildren &) = delete;
0282 };
0283
0284 class TypeFilterImpl : public SyntheticChildren {
0285 std::vector<std::string> m_expression_paths;
0286
0287 public:
0288 TypeFilterImpl(const SyntheticChildren::Flags &flags)
0289 : SyntheticChildren(flags) {}
0290
0291 TypeFilterImpl(const SyntheticChildren::Flags &flags,
0292 const std::initializer_list<const char *> items)
0293 : SyntheticChildren(flags) {
0294 for (auto path : items)
0295 AddExpressionPath(path);
0296 }
0297
0298 void AddExpressionPath(const char *path) {
0299 AddExpressionPath(std::string(path));
0300 }
0301
0302 void Clear() { m_expression_paths.clear(); }
0303
0304 size_t GetCount() const { return m_expression_paths.size(); }
0305
0306 const char *GetExpressionPathAtIndex(size_t i) const {
0307 return m_expression_paths[i].c_str();
0308 }
0309
0310 bool SetExpressionPathAtIndex(size_t i, const char *path) {
0311 return SetExpressionPathAtIndex(i, std::string(path));
0312 }
0313
0314 void AddExpressionPath(const std::string &path);
0315
0316 bool SetExpressionPathAtIndex(size_t i, const std::string &path);
0317
0318 bool IsScripted() override { return false; }
0319
0320 std::string GetDescription() override;
0321
0322 class FrontEnd : public SyntheticChildrenFrontEnd {
0323 public:
0324 FrontEnd(TypeFilterImpl *flt, ValueObject &backend)
0325 : SyntheticChildrenFrontEnd(backend), filter(flt) {}
0326
0327 ~FrontEnd() override = default;
0328
0329 llvm::Expected<uint32_t> CalculateNumChildren() override {
0330 return filter->GetCount();
0331 }
0332
0333 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {
0334 if (idx >= filter->GetCount())
0335 return lldb::ValueObjectSP();
0336 return m_backend.GetSyntheticExpressionPathChild(
0337 filter->GetExpressionPathAtIndex(idx), true);
0338 }
0339
0340 lldb::ChildCacheState Update() override {
0341 return lldb::ChildCacheState::eRefetch;
0342 }
0343
0344 bool MightHaveChildren() override { return filter->GetCount() > 0; }
0345
0346 size_t GetIndexOfChildWithName(ConstString name) override;
0347
0348 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
0349
0350 private:
0351 TypeFilterImpl *filter;
0352
0353 FrontEnd(const FrontEnd &) = delete;
0354 const FrontEnd &operator=(const FrontEnd &) = delete;
0355 };
0356
0357 SyntheticChildrenFrontEnd::AutoPointer
0358 GetFrontEnd(ValueObject &backend) override {
0359 return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend));
0360 }
0361
0362 typedef std::shared_ptr<TypeFilterImpl> SharedPointer;
0363
0364 private:
0365 TypeFilterImpl(const TypeFilterImpl &) = delete;
0366 const TypeFilterImpl &operator=(const TypeFilterImpl &) = delete;
0367 };
0368
0369 class CXXSyntheticChildren : public SyntheticChildren {
0370 public:
0371 typedef std::function<SyntheticChildrenFrontEnd *(CXXSyntheticChildren *,
0372 lldb::ValueObjectSP)>
0373 CreateFrontEndCallback;
0374 CXXSyntheticChildren(const SyntheticChildren::Flags &flags,
0375 const char *description, CreateFrontEndCallback callback);
0376
0377 virtual ~CXXSyntheticChildren();
0378
0379 bool IsScripted() override { return false; }
0380
0381 std::string GetDescription() override;
0382
0383 SyntheticChildrenFrontEnd::AutoPointer
0384 GetFrontEnd(ValueObject &backend) override {
0385 return SyntheticChildrenFrontEnd::AutoPointer(
0386 m_create_callback(this, backend.GetSP()));
0387 }
0388
0389 protected:
0390 CreateFrontEndCallback m_create_callback;
0391 std::string m_description;
0392
0393 private:
0394 CXXSyntheticChildren(const CXXSyntheticChildren &) = delete;
0395 const CXXSyntheticChildren &operator=(const CXXSyntheticChildren &) = delete;
0396 };
0397
0398 class ScriptedSyntheticChildren : public SyntheticChildren {
0399 std::string m_python_class;
0400 std::string m_python_code;
0401
0402 public:
0403 ScriptedSyntheticChildren(const SyntheticChildren::Flags &flags,
0404 const char *pclass, const char *pcode = nullptr)
0405 : SyntheticChildren(flags) {
0406 if (pclass)
0407 m_python_class = pclass;
0408 if (pcode)
0409 m_python_code = pcode;
0410 }
0411
0412 const char *GetPythonClassName() { return m_python_class.c_str(); }
0413
0414 const char *GetPythonCode() { return m_python_code.c_str(); }
0415
0416 void SetPythonClassName(const char *fname) {
0417 m_python_class.assign(fname);
0418 m_python_code.clear();
0419 }
0420
0421 void SetPythonCode(const char *script) { m_python_code.assign(script); }
0422
0423 std::string GetDescription() override;
0424
0425 bool IsScripted() override { return true; }
0426
0427 class FrontEnd : public SyntheticChildrenFrontEnd {
0428 public:
0429 FrontEnd(std::string pclass, ValueObject &backend);
0430
0431 ~FrontEnd() override;
0432
0433 bool IsValid();
0434
0435 llvm::Expected<uint32_t> CalculateNumChildren() override;
0436
0437 llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
0438
0439 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
0440
0441 lldb::ChildCacheState Update() override;
0442
0443 bool MightHaveChildren() override;
0444
0445 size_t GetIndexOfChildWithName(ConstString name) override;
0446
0447 lldb::ValueObjectSP GetSyntheticValue() override;
0448
0449 ConstString GetSyntheticTypeName() override;
0450
0451 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
0452
0453 private:
0454 std::string m_python_class;
0455 StructuredData::ObjectSP m_wrapper_sp;
0456 ScriptInterpreter *m_interpreter;
0457
0458 FrontEnd(const FrontEnd &) = delete;
0459 const FrontEnd &operator=(const FrontEnd &) = delete;
0460 };
0461
0462 SyntheticChildrenFrontEnd::AutoPointer
0463 GetFrontEnd(ValueObject &backend) override {
0464 auto synth_ptr = SyntheticChildrenFrontEnd::AutoPointer(
0465 new FrontEnd(m_python_class, backend));
0466 if (synth_ptr && ((FrontEnd *)synth_ptr.get())->IsValid())
0467 return synth_ptr;
0468 return nullptr;
0469 }
0470
0471 private:
0472 ScriptedSyntheticChildren(const ScriptedSyntheticChildren &) = delete;
0473 const ScriptedSyntheticChildren &
0474 operator=(const ScriptedSyntheticChildren &) = delete;
0475 };
0476 }
0477
0478 #endif