Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp
39642 views
1
//===-- GenericOptional.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 "Generic.h"
10
#include "LibCxx.h"
11
#include "LibStdcpp.h"
12
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
13
#include "lldb/DataFormatters/FormattersHelpers.h"
14
#include "lldb/Target/Target.h"
15
16
using namespace lldb;
17
using namespace lldb_private;
18
19
bool lldb_private::formatters::GenericOptionalSummaryProvider(
20
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
21
stream.Printf(" Has Value=%s ",
22
valobj.GetNumChildrenIgnoringErrors() == 0 ? "false" : "true");
23
24
return true;
25
}
26
27
// Synthetic Children Provider
28
namespace {
29
30
class GenericOptionalFrontend : public SyntheticChildrenFrontEnd {
31
public:
32
enum class StdLib {
33
LibCxx,
34
LibStdcpp,
35
};
36
37
GenericOptionalFrontend(ValueObject &valobj, StdLib stdlib);
38
39
size_t GetIndexOfChildWithName(ConstString name) override {
40
return formatters::ExtractIndexFromString(name.GetCString());
41
}
42
43
bool MightHaveChildren() override { return true; }
44
llvm::Expected<uint32_t> CalculateNumChildren() override {
45
return m_has_value ? 1U : 0U;
46
}
47
48
ValueObjectSP GetChildAtIndex(uint32_t idx) override;
49
lldb::ChildCacheState Update() override;
50
51
private:
52
bool m_has_value = false;
53
StdLib m_stdlib;
54
};
55
56
} // namespace
57
58
GenericOptionalFrontend::GenericOptionalFrontend(ValueObject &valobj,
59
StdLib stdlib)
60
: SyntheticChildrenFrontEnd(valobj), m_stdlib(stdlib) {
61
if (auto target_sp = m_backend.GetTargetSP()) {
62
Update();
63
}
64
}
65
66
lldb::ChildCacheState GenericOptionalFrontend::Update() {
67
ValueObjectSP engaged_sp;
68
69
if (m_stdlib == StdLib::LibCxx)
70
engaged_sp = m_backend.GetChildMemberWithName("__engaged_");
71
else if (m_stdlib == StdLib::LibStdcpp)
72
engaged_sp = m_backend.GetChildMemberWithName("_M_payload")
73
->GetChildMemberWithName("_M_engaged");
74
75
if (!engaged_sp)
76
return lldb::ChildCacheState::eRefetch;
77
78
// _M_engaged/__engaged is a bool flag and is true if the optional contains a
79
// value. Converting it to unsigned gives us a size of 1 if it contains a
80
// value and 0 if not.
81
m_has_value = engaged_sp->GetValueAsUnsigned(0) != 0;
82
83
return lldb::ChildCacheState::eRefetch;
84
}
85
86
ValueObjectSP GenericOptionalFrontend::GetChildAtIndex(uint32_t _idx) {
87
if (!m_has_value)
88
return ValueObjectSP();
89
90
ValueObjectSP val_sp;
91
92
if (m_stdlib == StdLib::LibCxx)
93
// __val_ contains the underlying value of an optional if it has one.
94
// Currently because it is part of an anonymous union
95
// GetChildMemberWithName() does not peer through and find it unless we are
96
// at the parent itself. We can obtain the parent through __engaged_.
97
val_sp = m_backend.GetChildMemberWithName("__engaged_")
98
->GetParent()
99
->GetChildAtIndex(0)
100
->GetChildMemberWithName("__val_");
101
else if (m_stdlib == StdLib::LibStdcpp) {
102
val_sp = m_backend.GetChildMemberWithName("_M_payload")
103
->GetChildMemberWithName("_M_payload");
104
105
// In some implementations, _M_value contains the underlying value of an
106
// optional, and in other versions, it's in the payload member.
107
ValueObjectSP candidate = val_sp->GetChildMemberWithName("_M_value");
108
if (candidate)
109
val_sp = candidate;
110
}
111
112
if (!val_sp)
113
return ValueObjectSP();
114
115
CompilerType holder_type = val_sp->GetCompilerType();
116
117
if (!holder_type)
118
return ValueObjectSP();
119
120
return val_sp->Clone(ConstString("Value"));
121
}
122
123
SyntheticChildrenFrontEnd *
124
formatters::LibStdcppOptionalSyntheticFrontEndCreator(
125
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
126
if (valobj_sp)
127
return new GenericOptionalFrontend(
128
*valobj_sp, GenericOptionalFrontend::StdLib::LibStdcpp);
129
return nullptr;
130
}
131
132
SyntheticChildrenFrontEnd *formatters::LibcxxOptionalSyntheticFrontEndCreator(
133
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
134
if (valobj_sp)
135
return new GenericOptionalFrontend(*valobj_sp,
136
GenericOptionalFrontend::StdLib::LibCxx);
137
return nullptr;
138
}
139
140