Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- LibStdcppUniquePointer.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 "LibStdcpp.h"
10
11
#include "lldb/Core/ValueObject.h"
12
#include "lldb/DataFormatters/FormattersHelpers.h"
13
#include "lldb/DataFormatters/TypeSynthetic.h"
14
#include "lldb/Utility/ConstString.h"
15
16
#include <memory>
17
#include <vector>
18
19
using namespace lldb;
20
using namespace lldb_private;
21
using namespace lldb_private::formatters;
22
23
namespace {
24
25
class LibStdcppUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
26
public:
27
  explicit LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
28
29
  size_t CalculateNumChildren() override;
30
31
  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
32
33
  bool Update() override;
34
35
  bool MightHaveChildren() override;
36
37
  size_t GetIndexOfChildWithName(ConstString name) override;
38
39
  bool GetSummary(Stream &stream, const TypeSummaryOptions &options);
40
41
private:
42
  // The lifetime of a ValueObject and all its derivative ValueObjects
43
  // (children, clones, etc.) is managed by a ClusterManager. These
44
  // objects are only destroyed when every shared pointer to any of them
45
  // is destroyed, so we must not store a shared pointer to any ValueObject
46
  // derived from our backend ValueObject (since we're in the same cluster).
47
  ValueObject* m_ptr_obj = nullptr;
48
  ValueObject* m_obj_obj = nullptr;
49
  ValueObject* m_del_obj = nullptr;
50
51
  ValueObjectSP GetTuple();
52
};
53
54
} // end of anonymous namespace
55
56
LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd(
57
    lldb::ValueObjectSP valobj_sp)
58
2
    : SyntheticChildrenFrontEnd(*valobj_sp) {
59
2
  Update();
60
2
}
61
62
3
ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetTuple() {
63
3
  ValueObjectSP valobj_backend_sp = m_backend.GetSP();
64
65
3
  if (!valobj_backend_sp)
66
0
    return nullptr;
67
68
3
  ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue();
69
3
  if (!valobj_sp)
70
0
    return nullptr;
71
72
3
  ValueObjectSP obj_child_sp = valobj_sp->GetChildMemberWithName("_M_t");
73
3
  if (!obj_child_sp)
74
3
      return nullptr;
75
76
0
  ValueObjectSP obj_subchild_sp = obj_child_sp->GetChildMemberWithName("_M_t");
77
78
  // if there is a _M_t subchild, the tuple is found in the obj_subchild_sp
79
  // (for libstdc++ 6.0.23).
80
0
  if (obj_subchild_sp) {
81
0
    return obj_subchild_sp;
82
0
  }
83
84
0
  return obj_child_sp;
85
0
}
86
87
3
bool LibStdcppUniquePtrSyntheticFrontEnd::Update() {
88
3
  ValueObjectSP tuple_sp = GetTuple();
89
90
3
  if (!tuple_sp)
91
3
    return false;
92
93
0
  std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend(
94
0
      LibStdcppTupleSyntheticFrontEndCreator(nullptr, tuple_sp));
95
96
0
  ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0);
97
0
  if (ptr_obj)
98
0
    m_ptr_obj = ptr_obj->Clone(ConstString("pointer")).get();
99
100
  // Add a 'deleter' child if there was a non-empty deleter type specified.
101
  //
102
  // The object might have size=1 in the TypeSystem but occupies no dedicated
103
  // storage due to no_unique_address, so infer the actual size from the total
104
  // size of the unique_ptr class. If sizeof(unique_ptr) == sizeof(void*) then
105
  // the deleter is empty and should be hidden.
106
0
  if (tuple_sp->GetByteSize() > ptr_obj->GetByteSize()) {
107
0
    ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1);
108
0
    if (del_obj)
109
0
      m_del_obj = del_obj->Clone(ConstString("deleter")).get();
110
0
  }
111
0
  m_obj_obj = nullptr;
112
113
0
  return false;
114
3
}
115
116
1
bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; }
117
118
lldb::ValueObjectSP
119
1
LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
120
1
  if (idx == 0 && m_ptr_obj)
121
0
    return m_ptr_obj->GetSP();
122
1
  if (idx == 1 && 
m_del_obj0
)
123
0
    return m_del_obj->GetSP();
124
1
  if (idx == 2) {
125
0
    if (m_ptr_obj && !m_obj_obj) {
126
0
      Status error;
127
0
      ValueObjectSP obj_obj = m_ptr_obj->Dereference(error);
128
0
      if (error.Success()) {
129
0
        m_obj_obj = obj_obj->Clone(ConstString("object")).get();
130
0
      }
131
0
    }
132
0
    if (m_obj_obj)
133
0
      return m_obj_obj->GetSP();
134
0
  }
135
1
  return lldb::ValueObjectSP();
136
1
}
137
138
1
size_t LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() {
139
1
  if (m_del_obj)
140
0
    return 2;
141
1
  return 1;
142
1
}
143
144
size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName(
145
0
    ConstString name) {
146
0
  if (name == "ptr" || name == "pointer")
147
0
    return 0;
148
0
  if (name == "del" || name == "deleter")
149
0
    return 1;
150
0
  if (name == "obj" || name == "object" || name == "$$dereference$$")
151
0
    return 2;
152
0
  return UINT32_MAX;
153
0
}
154
155
bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary(
156
1
    Stream &stream, const TypeSummaryOptions &options) {
157
1
  if (!m_ptr_obj)
158
1
    return false;
159
160
0
  bool success;
161
0
  uint64_t ptr_value = m_ptr_obj->GetValueAsUnsigned(0, &success);
162
0
  if (!success)
163
0
    return false;
164
0
  if (ptr_value == 0)
165
0
    stream.Printf("nullptr");
166
0
  else
167
0
    stream.Printf("0x%" PRIx64, ptr_value);
168
0
  return true;
169
0
}
170
171
SyntheticChildrenFrontEnd *
172
lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator(
173
1
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
174
1
  return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp)
175
1
                    : 
nullptr0
);
176
1
}
177
178
bool lldb_private::formatters::LibStdcppUniquePointerSummaryProvider(
179
1
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
180
1
  LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP());
181
1
  return formatter.GetSummary(stream, options);
182
1
}