Coverage Report

Created: 2023-09-12 09:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- LibCxxSpan.cpp ----------------------------------------------------===//
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
#include "LibCxx.h"
10
11
#include "lldb/Core/ValueObject.h"
12
#include "lldb/DataFormatters/FormattersHelpers.h"
13
#include "lldb/Utility/ConstString.h"
14
#include "llvm/ADT/APSInt.h"
15
#include <optional>
16
17
using namespace lldb;
18
using namespace lldb_private;
19
using namespace lldb_private::formatters;
20
21
namespace lldb_private {
22
namespace formatters {
23
24
class LibcxxStdSpanSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
25
public:
26
  LibcxxStdSpanSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
27
28
40
  ~LibcxxStdSpanSyntheticFrontEnd() override = default;
29
30
  size_t CalculateNumChildren() override;
31
32
  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
33
34
  /// Determines properties of the std::span<> associated with this object
35
  //
36
  // std::span can either be instantiated with a compile-time known
37
  // extent or a std::dynamic_extent (this is the default if only the
38
  // type template argument is provided). The layout of std::span
39
  // depends on whether the extent is dynamic or not. For static
40
  // extents (e.g., std::span<int, 9>):
41
  //
42
  // (std::__1::span<const int, 9>) s = {
43
  //   __data = 0x000000016fdff494
44
  // }
45
  //
46
  // For dynamic extents, e.g., std::span<int>, the layout is:
47
  //
48
  // (std::__1::span<const int, 18446744073709551615>) s = {
49
  //   __data = 0x000000016fdff494
50
  //   __size = 6
51
  // }
52
  //
53
  // This function checks for a '__size' member to determine the number
54
  // of elements in the span. If no such member exists, we get the size
55
  // from the only other place it can be: the template argument.
56
  bool Update() override;
57
58
  bool MightHaveChildren() override;
59
60
  size_t GetIndexOfChildWithName(ConstString name) override;
61
62
private:
63
  ValueObject *m_start = nullptr; ///< First element of span. Held, not owned.
64
  CompilerType m_element_type{};  ///< Type of span elements.
65
  size_t m_num_elements = 0;      ///< Number of elements in span.
66
  uint32_t m_element_size = 0;    ///< Size in bytes of each span element.
67
};
68
69
lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::
70
    LibcxxStdSpanSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
71
40
    : SyntheticChildrenFrontEnd(*valobj_sp) {
72
40
  if (valobj_sp)
73
40
    Update();
74
40
}
75
76
size_t lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::
77
34
    CalculateNumChildren() {
78
34
  return m_num_elements;
79
34
}
80
81
lldb::ValueObjectSP
82
lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::GetChildAtIndex(
83
64
    size_t idx) {
84
64
  if (!m_start)
85
0
    return {};
86
87
64
  uint64_t offset = idx * m_element_size;
88
64
  offset = offset + m_start->GetValueAsUnsigned(0);
89
64
  StreamString name;
90
64
  name.Printf("[%" PRIu64 "]", (uint64_t)idx);
91
64
  return CreateValueObjectFromAddress(name.GetString(), offset,
92
64
                                      m_backend.GetExecutionContextRef(),
93
64
                                      m_element_type);
94
64
}
95
96
80
bool lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::Update() {
97
  // Get element type.
98
80
  ValueObjectSP data_type_finder_sp = GetChildMemberWithName(
99
80
      m_backend, {ConstString("__data_"), ConstString("__data")});
100
80
  if (!data_type_finder_sp)
101
0
    return false;
102
103
80
  m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType();
104
105
  // Get element size.
106
80
  if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) {
107
80
    m_element_size = *size;
108
109
    // Get data.
110
80
    if (m_element_size > 0) {
111
80
      m_start = data_type_finder_sp.get();
112
80
    }
113
114
    // Get number of elements.
115
80
    if (auto size_sp = GetChildMemberWithName(
116
80
            m_backend, {ConstString("__size_"), ConstString("__size")})) {
117
24
      m_num_elements = size_sp->GetValueAsUnsigned(0);
118
56
    } else if (auto arg =
119
56
                   m_backend.GetCompilerType().GetIntegralTemplateArgument(1)) {
120
121
56
      m_num_elements = arg->value.getLimitedValue();
122
56
    }
123
80
  }
124
125
80
  return true;
126
80
}
127
128
bool lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::
129
4
    MightHaveChildren() {
130
4
  return true;
131
4
}
132
133
size_t lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::
134
0
    GetIndexOfChildWithName(ConstString name) {
135
0
  if (!m_start)
136
0
    return UINT32_MAX;
137
0
  return ExtractIndexFromString(name.GetCString());
138
0
}
139
140
lldb_private::SyntheticChildrenFrontEnd *
141
LibcxxStdSpanSyntheticFrontEndCreator(CXXSyntheticChildren *,
142
40
                                      lldb::ValueObjectSP valobj_sp) {
143
40
  if (!valobj_sp)
144
0
    return nullptr;
145
40
  CompilerType type = valobj_sp->GetCompilerType();
146
40
  if (!type.IsValid() || type.GetNumTemplateArguments() != 2)
147
0
    return nullptr;
148
40
  return new LibcxxStdSpanSyntheticFrontEnd(valobj_sp);
149
40
}
150
151
} // namespace formatters
152
} // namespace lldb_private