Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/DataFormatters/TypeSynthetic.h
Line
Count
Source (jump to first uncovered line)
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
20
#include "lldb/lldb-enumerations.h"
21
#include "lldb/lldb-public.h"
22
23
#include "lldb/Core/ValueObject.h"
24
#include "lldb/Utility/StructuredData.h"
25
26
namespace lldb_private {
27
class SyntheticChildrenFrontEnd {
28
protected:
29
  ValueObject &m_backend;
30
31
0
  void SetValid(bool valid) { m_valid = valid; }
32
33
0
  bool IsValid() { return m_valid; }
34
35
public:
36
  SyntheticChildrenFrontEnd(ValueObject &backend)
37
1.86k
      : m_backend(backend), m_valid(true) {}
38
39
1.55k
  virtual ~SyntheticChildrenFrontEnd() = default;
40
41
  virtual size_t CalculateNumChildren() = 0;
42
43
767
  virtual size_t CalculateNumChildren(uint32_t max) {
44
767
    auto count = CalculateNumChildren();
45
767
    return count <= max ? count : 
max0
;
46
767
  }
47
48
  virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx) = 0;
49
50
  virtual size_t GetIndexOfChildWithName(ConstString name) = 0;
51
52
  // this function is assumed to always succeed and it if fails, the front-end
53
  // should know to deal with it in the correct way (most probably, by refusing
54
  // to return any children) the return value of Update() should actually be
55
  // interpreted as "ValueObjectSyntheticFilter cache is good/bad" if =true,
56
  // ValueObjectSyntheticFilter is allowed to use the children it fetched
57
  // previously and cached if =false, ValueObjectSyntheticFilter must throw
58
  // away its cache, and query again for children
59
  virtual bool Update() = 0;
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() = 0;
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
1.50k
  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
76
1.54k
  virtual ConstString GetSyntheticTypeName() { return ConstString(); }
77
78
  typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
79
  typedef std::unique_ptr<SyntheticChildrenFrontEnd> AutoPointer;
80
81
protected:
82
  lldb::ValueObjectSP
83
  CreateValueObjectFromExpression(llvm::StringRef name,
84
                                  llvm::StringRef expression,
85
                                  const ExecutionContext &exe_ctx);
86
87
  lldb::ValueObjectSP
88
  CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address,
89
                               const ExecutionContext &exe_ctx,
90
                               CompilerType type);
91
92
  lldb::ValueObjectSP CreateValueObjectFromData(llvm::StringRef name,
93
                                                const DataExtractor &data,
94
                                                const ExecutionContext &exe_ctx,
95
                                                CompilerType type);
96
97
private:
98
  bool m_valid;
99
  SyntheticChildrenFrontEnd(const SyntheticChildrenFrontEnd &) = delete;
100
  const SyntheticChildrenFrontEnd &
101
  operator=(const SyntheticChildrenFrontEnd &) = delete;
102
};
103
104
class SyntheticValueProviderFrontEnd : public SyntheticChildrenFrontEnd {
105
public:
106
  SyntheticValueProviderFrontEnd(ValueObject &backend)
107
0
      : SyntheticChildrenFrontEnd(backend) {}
108
109
  ~SyntheticValueProviderFrontEnd() override = default;
110
111
0
  size_t CalculateNumChildren() override { return 0; }
112
113
0
  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override { return nullptr; }
114
115
0
  size_t GetIndexOfChildWithName(ConstString name) override {
116
0
    return UINT32_MAX;
117
0
  }
118
119
0
  bool Update() override { return false; }
120
121
0
  bool MightHaveChildren() override { return false; }
122
123
  lldb::ValueObjectSP GetSyntheticValue() override = 0;
124
125
private:
126
  SyntheticValueProviderFrontEnd(const SyntheticValueProviderFrontEnd &) =
127
      delete;
128
  const SyntheticValueProviderFrontEnd &
129
  operator=(const SyntheticValueProviderFrontEnd &) = delete;
130
};
131
132
class SyntheticChildren {
133
public:
134
  class Flags {
135
  public:
136
27.3k
    Flags() = default;
137
138
79.9k
    Flags(const Flags &other) : m_flags(other.m_flags) {}
139
140
11
    Flags(uint32_t value) : m_flags(value) {}
141
142
0
    Flags &operator=(const Flags &rhs) {
143
0
      if (&rhs != this)
144
0
        m_flags = rhs.m_flags;
145
0
146
0
      return *this;
147
0
    }
148
149
0
    Flags &operator=(const uint32_t &rhs) {
150
0
      m_flags = rhs;
151
0
      return *this;
152
0
    }
153
154
0
    Flags &Clear() {
155
0
      m_flags = 0;
156
0
      return *this;
157
0
    }
158
159
864
    bool GetCascades() const {
160
864
      return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade;
161
864
    }
162
163
3.49k
    Flags &SetCascades(bool value = true) {
164
3.49k
      if (value)
165
3.49k
        m_flags |= lldb::eTypeOptionCascade;
166
0
      else
167
0
        m_flags &= ~lldb::eTypeOptionCascade;
168
3.49k
      return *this;
169
3.49k
    }
170
171
864
    bool GetSkipPointers() const {
172
864
      return (m_flags & lldb::eTypeOptionSkipPointers) ==
173
864
             lldb::eTypeOptionSkipPointers;
174
864
    }
175
176
3.49k
    Flags &SetSkipPointers(bool value = true) {
177
3.49k
      if (value)
178
1.36k
        m_flags |= lldb::eTypeOptionSkipPointers;
179
2.13k
      else
180
2.13k
        m_flags &= ~lldb::eTypeOptionSkipPointers;
181
3.49k
      return *this;
182
3.49k
    }
183
184
862
    bool GetSkipReferences() const {
185
862
      return (m_flags & lldb::eTypeOptionSkipReferences) ==
186
862
             lldb::eTypeOptionSkipReferences;
187
862
    }
188
189
3.49k
    Flags &SetSkipReferences(bool value = true) {
190
3.49k
      if (value)
191
1.36k
        m_flags |= lldb::eTypeOptionSkipReferences;
192
2.13k
      else
193
2.13k
        m_flags &= ~lldb::eTypeOptionSkipReferences;
194
3.49k
      return *this;
195
3.49k
    }
196
197
538
    bool GetNonCacheable() const {
198
538
      return (m_flags & lldb::eTypeOptionNonCacheable) ==
199
538
             lldb::eTypeOptionNonCacheable;
200
538
    }
201
202
1.36k
    Flags &SetNonCacheable(bool value = true) {
203
1.36k
      if (value)
204
1.36k
        m_flags |= lldb::eTypeOptionNonCacheable;
205
0
      else
206
0
        m_flags &= ~lldb::eTypeOptionNonCacheable;
207
1.36k
      return *this;
208
1.36k
    }
209
210
1.84k
    bool GetFrontEndWantsDereference() const {
211
1.84k
      return (m_flags & lldb::eTypeOptionFrontEndWantsDereference) ==
212
1.84k
             lldb::eTypeOptionFrontEndWantsDereference;
213
1.84k
    }
214
215
1.36k
    Flags &SetFrontEndWantsDereference(bool value = true) {
216
1.36k
      if (value)
217
1.36k
        m_flags |= lldb::eTypeOptionFrontEndWantsDereference;
218
0
      else
219
0
        m_flags &= ~lldb::eTypeOptionFrontEndWantsDereference;
220
1.36k
      return *this;
221
1.36k
    }
222
223
2
    uint32_t GetValue() { return m_flags; }
224
225
0
    void SetValue(uint32_t value) { m_flags = value; }
226
227
  private:
228
    uint32_t m_flags = lldb::eTypeOptionCascade;
229
  };
230
231
  SyntheticChildren(const Flags &flags);
232
233
  virtual ~SyntheticChildren();
234
235
864
  bool Cascades() const { return m_flags.GetCascades(); }
236
237
864
  bool SkipsPointers() const { return m_flags.GetSkipPointers(); }
238
239
862
  bool SkipsReferences() const { return m_flags.GetSkipReferences(); }
240
241
538
  bool NonCacheable() const { return m_flags.GetNonCacheable(); }
242
243
1.84k
  bool WantsDereference() const { return m_flags.GetFrontEndWantsDereference();}
244
245
0
  void SetCascades(bool value) { m_flags.SetCascades(value); }
246
247
0
  void SetSkipsPointers(bool value) { m_flags.SetSkipPointers(value); }
248
249
0
  void SetSkipsReferences(bool value) { m_flags.SetSkipReferences(value); }
250
251
0
  void SetNonCacheable(bool value) { m_flags.SetNonCacheable(value); }
252
253
2
  uint32_t GetOptions() { return m_flags.GetValue(); }
254
255
0
  void SetOptions(uint32_t value) { m_flags.SetValue(value); }
256
257
  virtual bool IsScripted() = 0;
258
259
  virtual std::string GetDescription() = 0;
260
261
  virtual SyntheticChildrenFrontEnd::AutoPointer
262
  GetFrontEnd(ValueObject &backend) = 0;
263
264
  typedef std::shared_ptr<SyntheticChildren> SharedPointer;
265
266
54.0k
  uint32_t &GetRevision() { return m_my_revision; }
267
268
protected:
269
  uint32_t m_my_revision = 0;
270
  Flags m_flags;
271
272
private:
273
  SyntheticChildren(const SyntheticChildren &) = delete;
274
  const SyntheticChildren &operator=(const SyntheticChildren &) = delete;
275
};
276
277
class TypeFilterImpl : public SyntheticChildren {
278
  std::vector<std::string> m_expression_paths;
279
280
public:
281
  TypeFilterImpl(const SyntheticChildren::Flags &flags)
282
35
      : SyntheticChildren(flags) {}
283
284
  TypeFilterImpl(const SyntheticChildren::Flags &flags,
285
                 const std::initializer_list<const char *> items)
286
0
      : SyntheticChildren(flags) {
287
0
    for (auto path : items)
288
0
      AddExpressionPath(path);
289
0
  }
290
291
8
  void AddExpressionPath(const char *path) {
292
8
    AddExpressionPath(std::string(path));
293
8
  }
294
295
0
  void Clear() { m_expression_paths.clear(); }
296
297
159
  size_t GetCount() const { return m_expression_paths.size(); }
298
299
104
  const char *GetExpressionPathAtIndex(size_t i) const {
300
104
    return m_expression_paths[i].c_str();
301
104
  }
302
303
2
  bool SetExpressionPathAtIndex(size_t i, const char *path) {
304
2
    return SetExpressionPathAtIndex(i, std::string(path));
305
2
  }
306
307
  void AddExpressionPath(const std::string &path);
308
309
  bool SetExpressionPathAtIndex(size_t i, const std::string &path);
310
311
0
  bool IsScripted() override { return false; }
312
313
  std::string GetDescription() override;
314
315
  class FrontEnd : public SyntheticChildrenFrontEnd {
316
  public:
317
    FrontEnd(TypeFilterImpl *flt, ValueObject &backend)
318
38
        : SyntheticChildrenFrontEnd(backend), filter(flt) {}
319
320
28
    ~FrontEnd() override = default;
321
322
38
    size_t CalculateNumChildren() override { return filter->GetCount(); }
323
324
74
    lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
325
74
      if (idx >= filter->GetCount())
326
0
        return lldb::ValueObjectSP();
327
74
      return m_backend.GetSyntheticExpressionPathChild(
328
74
          filter->GetExpressionPathAtIndex(idx), true);
329
74
    }
330
331
38
    bool Update() override { return false; }
332
333
6
    bool MightHaveChildren() override { return filter->GetCount() > 0; }
334
335
    size_t GetIndexOfChildWithName(ConstString name) override;
336
337
    typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
338
339
  private:
340
    TypeFilterImpl *filter;
341
342
    FrontEnd(const FrontEnd &) = delete;
343
    const FrontEnd &operator=(const FrontEnd &) = delete;
344
  };
345
346
  SyntheticChildrenFrontEnd::AutoPointer
347
38
  GetFrontEnd(ValueObject &backend) override {
348
38
    return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend));
349
38
  }
350
351
  typedef std::shared_ptr<TypeFilterImpl> SharedPointer;
352
353
private:
354
  TypeFilterImpl(const TypeFilterImpl &) = delete;
355
  const TypeFilterImpl &operator=(const TypeFilterImpl &) = delete;
356
};
357
358
class CXXSyntheticChildren : public SyntheticChildren {
359
public:
360
  typedef std::function<SyntheticChildrenFrontEnd *(CXXSyntheticChildren *,
361
                                                    lldb::ValueObjectSP)>
362
      CreateFrontEndCallback;
363
  CXXSyntheticChildren(const SyntheticChildren::Flags &flags,
364
                       const char *description, CreateFrontEndCallback callback);
365
366
  virtual ~CXXSyntheticChildren();
367
368
0
  bool IsScripted() override { return false; }
369
370
  std::string GetDescription() override;
371
372
  SyntheticChildrenFrontEnd::AutoPointer
373
1.70k
  GetFrontEnd(ValueObject &backend) override {
374
1.70k
    return SyntheticChildrenFrontEnd::AutoPointer(
375
1.70k
        m_create_callback(this, backend.GetSP()));
376
1.70k
  }
377
378
protected:
379
  CreateFrontEndCallback m_create_callback;
380
  std::string m_description;
381
382
private:
383
  CXXSyntheticChildren(const CXXSyntheticChildren &) = delete;
384
  const CXXSyntheticChildren &operator=(const CXXSyntheticChildren &) = delete;
385
};
386
387
class ScriptedSyntheticChildren : public SyntheticChildren {
388
  std::string m_python_class;
389
  std::string m_python_code;
390
391
public:
392
  ScriptedSyntheticChildren(const SyntheticChildren::Flags &flags,
393
                            const char *pclass, const char *pcode = nullptr)
394
6.87k
      : SyntheticChildren(flags) {
395
6.87k
    if (pclass)
396
6.87k
      m_python_class = pclass;
397
6.87k
    if (pcode)
398
6
      m_python_code = pcode;
399
6.87k
  }
400
401
35
  const char *GetPythonClassName() { return m_python_class.c_str(); }
402
403
6
  const char *GetPythonCode() { return m_python_code.c_str(); }
404
405
0
  void SetPythonClassName(const char *fname) {
406
0
    m_python_class.assign(fname);
407
0
    m_python_code.clear();
408
0
  }
409
410
0
  void SetPythonCode(const char *script) { m_python_code.assign(script); }
411
412
  std::string GetDescription() override;
413
414
0
  bool IsScripted() override { return true; }
415
416
  class FrontEnd : public SyntheticChildrenFrontEnd {
417
  public:
418
    FrontEnd(std::string pclass, ValueObject &backend);
419
420
    ~FrontEnd() override;
421
422
    bool IsValid();
423
424
    size_t CalculateNumChildren() override;
425
426
    size_t CalculateNumChildren(uint32_t max) override;
427
428
    lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
429
430
    bool Update() override;
431
432
    bool MightHaveChildren() override;
433
434
    size_t GetIndexOfChildWithName(ConstString name) override;
435
436
    lldb::ValueObjectSP GetSyntheticValue() override;
437
438
    ConstString GetSyntheticTypeName() override;
439
440
    typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
441
442
  private:
443
    std::string m_python_class;
444
    StructuredData::ObjectSP m_wrapper_sp;
445
    ScriptInterpreter *m_interpreter;
446
447
    FrontEnd(const FrontEnd &) = delete;
448
    const FrontEnd &operator=(const FrontEnd &) = delete;
449
  };
450
451
  SyntheticChildrenFrontEnd::AutoPointer
452
105
  GetFrontEnd(ValueObject &backend) override {
453
105
    auto synth_ptr = SyntheticChildrenFrontEnd::AutoPointer(
454
105
        new FrontEnd(m_python_class, backend));
455
105
    if (synth_ptr && ((FrontEnd *)synth_ptr.get())->IsValid())
456
102
      return synth_ptr;
457
3
    return nullptr;
458
105
  }
459
460
private:
461
  ScriptedSyntheticChildren(const ScriptedSyntheticChildren &) = delete;
462
  const ScriptedSyntheticChildren &
463
  operator=(const ScriptedSyntheticChildren &) = delete;
464
};
465
} // namespace lldb_private
466
467
#endif // LLDB_DATAFORMATTERS_TYPESYNTHETIC_H