xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10eae32dcSDimitry Andric //===-- GenericOptional.cpp ----------------------------------------------===//
20eae32dcSDimitry Andric //
30eae32dcSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40eae32dcSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50eae32dcSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60eae32dcSDimitry Andric //
70eae32dcSDimitry Andric //===---------------------------------------------------------------------===//
80eae32dcSDimitry Andric 
90eae32dcSDimitry Andric #include "Generic.h"
100eae32dcSDimitry Andric #include "LibCxx.h"
110eae32dcSDimitry Andric #include "LibStdcpp.h"
120eae32dcSDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
130eae32dcSDimitry Andric #include "lldb/DataFormatters/FormattersHelpers.h"
140eae32dcSDimitry Andric #include "lldb/Target/Target.h"
150eae32dcSDimitry Andric 
160eae32dcSDimitry Andric using namespace lldb;
170eae32dcSDimitry Andric using namespace lldb_private;
180eae32dcSDimitry Andric 
190eae32dcSDimitry Andric bool lldb_private::formatters::GenericOptionalSummaryProvider(
200eae32dcSDimitry Andric     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
210eae32dcSDimitry Andric   stream.Printf(" Has Value=%s ",
22*0fca6ea1SDimitry Andric                 valobj.GetNumChildrenIgnoringErrors() == 0 ? "false" : "true");
230eae32dcSDimitry Andric 
240eae32dcSDimitry Andric   return true;
250eae32dcSDimitry Andric }
260eae32dcSDimitry Andric 
270eae32dcSDimitry Andric // Synthetic Children Provider
280eae32dcSDimitry Andric namespace {
290eae32dcSDimitry Andric 
300eae32dcSDimitry Andric class GenericOptionalFrontend : public SyntheticChildrenFrontEnd {
310eae32dcSDimitry Andric public:
320eae32dcSDimitry Andric   enum class StdLib {
330eae32dcSDimitry Andric     LibCxx,
340eae32dcSDimitry Andric     LibStdcpp,
350eae32dcSDimitry Andric   };
360eae32dcSDimitry Andric 
370eae32dcSDimitry Andric   GenericOptionalFrontend(ValueObject &valobj, StdLib stdlib);
380eae32dcSDimitry Andric 
390eae32dcSDimitry Andric   size_t GetIndexOfChildWithName(ConstString name) override {
400eae32dcSDimitry Andric     return formatters::ExtractIndexFromString(name.GetCString());
410eae32dcSDimitry Andric   }
420eae32dcSDimitry Andric 
430eae32dcSDimitry Andric   bool MightHaveChildren() override { return true; }
44*0fca6ea1SDimitry Andric   llvm::Expected<uint32_t> CalculateNumChildren() override {
45*0fca6ea1SDimitry Andric     return m_has_value ? 1U : 0U;
46*0fca6ea1SDimitry Andric   }
470eae32dcSDimitry Andric 
48*0fca6ea1SDimitry Andric   ValueObjectSP GetChildAtIndex(uint32_t idx) override;
49*0fca6ea1SDimitry Andric   lldb::ChildCacheState Update() override;
500eae32dcSDimitry Andric 
510eae32dcSDimitry Andric private:
520eae32dcSDimitry Andric   bool m_has_value = false;
530eae32dcSDimitry Andric   StdLib m_stdlib;
540eae32dcSDimitry Andric };
550eae32dcSDimitry Andric 
560eae32dcSDimitry Andric } // namespace
570eae32dcSDimitry Andric 
580eae32dcSDimitry Andric GenericOptionalFrontend::GenericOptionalFrontend(ValueObject &valobj,
590eae32dcSDimitry Andric                                                  StdLib stdlib)
600eae32dcSDimitry Andric     : SyntheticChildrenFrontEnd(valobj), m_stdlib(stdlib) {
610eae32dcSDimitry Andric   if (auto target_sp = m_backend.GetTargetSP()) {
620eae32dcSDimitry Andric     Update();
630eae32dcSDimitry Andric   }
640eae32dcSDimitry Andric }
650eae32dcSDimitry Andric 
66*0fca6ea1SDimitry Andric lldb::ChildCacheState GenericOptionalFrontend::Update() {
670eae32dcSDimitry Andric   ValueObjectSP engaged_sp;
680eae32dcSDimitry Andric 
690eae32dcSDimitry Andric   if (m_stdlib == StdLib::LibCxx)
7006c3fb27SDimitry Andric     engaged_sp = m_backend.GetChildMemberWithName("__engaged_");
710eae32dcSDimitry Andric   else if (m_stdlib == StdLib::LibStdcpp)
7206c3fb27SDimitry Andric     engaged_sp = m_backend.GetChildMemberWithName("_M_payload")
7306c3fb27SDimitry Andric                      ->GetChildMemberWithName("_M_engaged");
740eae32dcSDimitry Andric 
750eae32dcSDimitry Andric   if (!engaged_sp)
76*0fca6ea1SDimitry Andric     return lldb::ChildCacheState::eRefetch;
770eae32dcSDimitry Andric 
780eae32dcSDimitry Andric   // _M_engaged/__engaged is a bool flag and is true if the optional contains a
790eae32dcSDimitry Andric   // value. Converting it to unsigned gives us a size of 1 if it contains a
800eae32dcSDimitry Andric   // value and 0 if not.
810eae32dcSDimitry Andric   m_has_value = engaged_sp->GetValueAsUnsigned(0) != 0;
820eae32dcSDimitry Andric 
83*0fca6ea1SDimitry Andric   return lldb::ChildCacheState::eRefetch;
840eae32dcSDimitry Andric }
850eae32dcSDimitry Andric 
86*0fca6ea1SDimitry Andric ValueObjectSP GenericOptionalFrontend::GetChildAtIndex(uint32_t _idx) {
870eae32dcSDimitry Andric   if (!m_has_value)
880eae32dcSDimitry Andric     return ValueObjectSP();
890eae32dcSDimitry Andric 
900eae32dcSDimitry Andric   ValueObjectSP val_sp;
910eae32dcSDimitry Andric 
920eae32dcSDimitry Andric   if (m_stdlib == StdLib::LibCxx)
930eae32dcSDimitry Andric     // __val_ contains the underlying value of an optional if it has one.
940eae32dcSDimitry Andric     // Currently because it is part of an anonymous union
950eae32dcSDimitry Andric     // GetChildMemberWithName() does not peer through and find it unless we are
960eae32dcSDimitry Andric     // at the parent itself. We can obtain the parent through __engaged_.
9706c3fb27SDimitry Andric     val_sp = m_backend.GetChildMemberWithName("__engaged_")
980eae32dcSDimitry Andric                  ->GetParent()
9906c3fb27SDimitry Andric                  ->GetChildAtIndex(0)
10006c3fb27SDimitry Andric                  ->GetChildMemberWithName("__val_");
1010eae32dcSDimitry Andric   else if (m_stdlib == StdLib::LibStdcpp) {
10206c3fb27SDimitry Andric     val_sp = m_backend.GetChildMemberWithName("_M_payload")
10306c3fb27SDimitry Andric                  ->GetChildMemberWithName("_M_payload");
1040eae32dcSDimitry Andric 
1050eae32dcSDimitry Andric     // In some implementations, _M_value contains the underlying value of an
1060eae32dcSDimitry Andric     // optional, and in other versions, it's in the payload member.
10706c3fb27SDimitry Andric     ValueObjectSP candidate = val_sp->GetChildMemberWithName("_M_value");
1080eae32dcSDimitry Andric     if (candidate)
1090eae32dcSDimitry Andric       val_sp = candidate;
1100eae32dcSDimitry Andric   }
1110eae32dcSDimitry Andric 
1120eae32dcSDimitry Andric   if (!val_sp)
1130eae32dcSDimitry Andric     return ValueObjectSP();
1140eae32dcSDimitry Andric 
1150eae32dcSDimitry Andric   CompilerType holder_type = val_sp->GetCompilerType();
1160eae32dcSDimitry Andric 
1170eae32dcSDimitry Andric   if (!holder_type)
1180eae32dcSDimitry Andric     return ValueObjectSP();
1190eae32dcSDimitry Andric 
1200eae32dcSDimitry Andric   return val_sp->Clone(ConstString("Value"));
1210eae32dcSDimitry Andric }
1220eae32dcSDimitry Andric 
1230eae32dcSDimitry Andric SyntheticChildrenFrontEnd *
1240eae32dcSDimitry Andric formatters::LibStdcppOptionalSyntheticFrontEndCreator(
1250eae32dcSDimitry Andric     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
1260eae32dcSDimitry Andric   if (valobj_sp)
1270eae32dcSDimitry Andric     return new GenericOptionalFrontend(
1280eae32dcSDimitry Andric         *valobj_sp, GenericOptionalFrontend::StdLib::LibStdcpp);
1290eae32dcSDimitry Andric   return nullptr;
1300eae32dcSDimitry Andric }
1310eae32dcSDimitry Andric 
1320eae32dcSDimitry Andric SyntheticChildrenFrontEnd *formatters::LibcxxOptionalSyntheticFrontEndCreator(
1330eae32dcSDimitry Andric     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
1340eae32dcSDimitry Andric   if (valobj_sp)
1350eae32dcSDimitry Andric     return new GenericOptionalFrontend(*valobj_sp,
1360eae32dcSDimitry Andric                                        GenericOptionalFrontend::StdLib::LibCxx);
1370eae32dcSDimitry Andric   return nullptr;
1380eae32dcSDimitry Andric }
139