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