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