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