Coverage Report

Created: 2022-07-16 07:03

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- LibCxxUnorderedMap.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 "Plugins/TypeSystem/Clang/TypeSystemClang.h"
12
#include "lldb/Core/ValueObject.h"
13
#include "lldb/Core/ValueObjectConstResult.h"
14
#include "lldb/DataFormatters/FormattersHelpers.h"
15
#include "lldb/Target/Target.h"
16
#include "lldb/Utility/DataBufferHeap.h"
17
#include "lldb/Utility/Endian.h"
18
#include "lldb/Utility/Status.h"
19
#include "lldb/Utility/Stream.h"
20
21
using namespace lldb;
22
using namespace lldb_private;
23
using namespace lldb_private::formatters;
24
25
namespace lldb_private {
26
namespace formatters {
27
class LibcxxStdUnorderedMapSyntheticFrontEnd
28
    : public SyntheticChildrenFrontEnd {
29
public:
30
  LibcxxStdUnorderedMapSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
31
32
21
  ~LibcxxStdUnorderedMapSyntheticFrontEnd() override = default;
33
34
  size_t CalculateNumChildren() override;
35
36
  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
37
38
  bool Update() override;
39
40
  bool MightHaveChildren() override;
41
42
  size_t GetIndexOfChildWithName(ConstString name) override;
43
44
private:
45
  CompilerType m_element_type;
46
  CompilerType m_node_type;
47
  ValueObject *m_tree = nullptr;
48
  size_t m_num_elements = 0;
49
  ValueObject *m_next_element = nullptr;
50
  std::vector<std::pair<ValueObject *, uint64_t>> m_elements_cache;
51
};
52
} // namespace formatters
53
} // namespace lldb_private
54
55
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
56
    LibcxxStdUnorderedMapSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
57
    : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type(),
58
21
      m_elements_cache() {
59
21
  if (valobj_sp)
60
21
    Update();
61
21
}
62
63
size_t lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
64
117
    CalculateNumChildren() {
65
117
  return m_num_elements;
66
117
}
67
68
lldb::ValueObjectSP lldb_private::formatters::
69
96
    LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
70
96
  if (idx >= CalculateNumChildren())
71
0
    return lldb::ValueObjectSP();
72
96
  if (m_tree == nullptr)
73
0
    return lldb::ValueObjectSP();
74
75
192
  
while (96
idx >= m_elements_cache.size()) {
76
96
    if (m_next_element == nullptr)
77
0
      return lldb::ValueObjectSP();
78
79
96
    Status error;
80
96
    ValueObjectSP node_sp = m_next_element->Dereference(error);
81
96
    if (!node_sp || error.Fail())
82
0
      return lldb::ValueObjectSP();
83
84
96
    ValueObjectSP value_sp =
85
96
        node_sp->GetChildMemberWithName(ConstString("__value_"), true);
86
96
    ValueObjectSP hash_sp =
87
96
        node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
88
96
    if (!hash_sp || 
!value_sp0
) {
89
96
      if (!m_element_type) {
90
69
        auto p1_sp = m_backend.GetChildAtNamePath({ConstString("__table_"),
91
69
                                                   ConstString("__p1_")});
92
69
        if (!p1_sp)
93
0
          return nullptr;
94
95
69
        ValueObjectSP first_sp = nullptr;
96
69
        switch (p1_sp->GetCompilerType().GetNumDirectBaseClasses()) {
97
0
        case 1:
98
          // Assume a pre llvm r300140 __compressed_pair implementation:
99
0
          first_sp = p1_sp->GetChildMemberWithName(ConstString("__first_"),
100
0
                                                   true);
101
0
          break;
102
69
        case 2: {
103
          // Assume a post llvm r300140 __compressed_pair implementation:
104
69
          ValueObjectSP first_elem_parent_sp =
105
69
            p1_sp->GetChildAtIndex(0, true);
106
69
          first_sp = p1_sp->GetChildMemberWithName(ConstString("__value_"),
107
69
                                                   true);
108
69
          break;
109
0
        }
110
0
        default:
111
0
          return nullptr;
112
69
        }
113
114
69
        if (!first_sp)
115
0
          return nullptr;
116
69
        m_element_type = first_sp->GetCompilerType();
117
69
        m_element_type = m_element_type.GetTypeTemplateArgument(0);
118
69
        m_element_type = m_element_type.GetPointeeType();
119
69
        m_node_type = m_element_type;
120
69
        m_element_type = m_element_type.GetTypeTemplateArgument(0);
121
69
        std::string name;
122
69
        m_element_type =
123
69
            m_element_type.GetFieldAtIndex(0, name, nullptr, nullptr, nullptr);
124
69
        m_element_type = m_element_type.GetTypedefedType();
125
69
      }
126
96
      if (!m_node_type)
127
0
        return nullptr;
128
96
      node_sp = node_sp->Cast(m_node_type);
129
96
      value_sp = node_sp->GetChildMemberWithName(ConstString("__value_"), true);
130
96
      hash_sp = node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
131
96
      if (!value_sp || !hash_sp)
132
0
        return nullptr;
133
96
    }
134
96
    m_elements_cache.push_back(
135
96
        {value_sp.get(), hash_sp->GetValueAsUnsigned(0)});
136
96
    m_next_element =
137
96
        node_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
138
96
    if (!m_next_element || m_next_element->GetValueAsUnsigned(0) == 0)
139
18
      m_next_element = nullptr;
140
96
  }
141
142
96
  std::pair<ValueObject *, uint64_t> val_hash = m_elements_cache[idx];
143
96
  if (!val_hash.first)
144
0
    return lldb::ValueObjectSP();
145
96
  StreamString stream;
146
96
  stream.Printf("[%" PRIu64 "]", (uint64_t)idx);
147
96
  DataExtractor data;
148
96
  Status error;
149
96
  val_hash.first->GetData(data, error);
150
96
  if (error.Fail())
151
0
    return lldb::ValueObjectSP();
152
96
  const bool thread_and_frame_only_if_stopped = true;
153
96
  ExecutionContext exe_ctx = val_hash.first->GetExecutionContextRef().Lock(
154
96
      thread_and_frame_only_if_stopped);
155
96
  return CreateValueObjectFromData(stream.GetString(), data, exe_ctx,
156
96
                                   val_hash.first->GetCompilerType());
157
96
}
158
159
bool lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
160
42
    Update() {
161
42
  m_num_elements = 0;
162
42
  m_next_element = nullptr;
163
42
  m_elements_cache.clear();
164
42
  ValueObjectSP table_sp =
165
42
      m_backend.GetChildMemberWithName(ConstString("__table_"), true);
166
42
  if (!table_sp)
167
0
    return false;
168
169
42
  ValueObjectSP p2_sp = table_sp->GetChildMemberWithName(
170
42
    ConstString("__p2_"), true);
171
42
  ValueObjectSP num_elements_sp = nullptr;
172
42
  llvm::SmallVector<ConstString, 3> next_path;
173
42
  switch (p2_sp->GetCompilerType().GetNumDirectBaseClasses()) {
174
0
  case 1:
175
    // Assume a pre llvm r300140 __compressed_pair implementation:
176
0
    num_elements_sp = p2_sp->GetChildMemberWithName(
177
0
      ConstString("__first_"), true);
178
0
    next_path.append({ConstString("__p1_"), ConstString("__first_"),
179
0
                      ConstString("__next_")});
180
0
    break;
181
42
  case 2: {
182
    // Assume a post llvm r300140 __compressed_pair implementation:
183
42
    ValueObjectSP first_elem_parent = p2_sp->GetChildAtIndex(0, true);
184
42
    num_elements_sp = first_elem_parent->GetChildMemberWithName(
185
42
      ConstString("__value_"), true);
186
42
    next_path.append({ConstString("__p1_"), ConstString("__value_"),
187
42
                      ConstString("__next_")});
188
42
    break;
189
0
  }
190
0
  default:
191
0
    return false;
192
42
  }
193
194
42
  if (!num_elements_sp)
195
0
    return false;
196
197
42
  m_tree = table_sp->GetChildAtNamePath(next_path).get();
198
42
  if (m_tree == nullptr)
199
0
    return false;
200
201
42
  m_num_elements = num_elements_sp->GetValueAsUnsigned(0);
202
203
42
  if (m_num_elements > 0)
204
36
    m_next_element =
205
36
        table_sp->GetChildAtNamePath(next_path).get();
206
42
  return false;
207
42
}
208
209
bool lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
210
3
    MightHaveChildren() {
211
3
  return true;
212
3
}
213
214
size_t lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
215
0
    GetIndexOfChildWithName(ConstString name) {
216
0
  return ExtractIndexFromString(name.GetCString());
217
0
}
218
219
SyntheticChildrenFrontEnd *
220
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator(
221
21
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
222
21
  return (valobj_sp ? new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp)
223
21
                    : 
nullptr0
);
224
21
}