Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp
39642 views
//===-- GenericOptional.cpp ----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===---------------------------------------------------------------------===//78#include "Generic.h"9#include "LibCxx.h"10#include "LibStdcpp.h"11#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"12#include "lldb/DataFormatters/FormattersHelpers.h"13#include "lldb/Target/Target.h"1415using namespace lldb;16using namespace lldb_private;1718bool lldb_private::formatters::GenericOptionalSummaryProvider(19ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {20stream.Printf(" Has Value=%s ",21valobj.GetNumChildrenIgnoringErrors() == 0 ? "false" : "true");2223return true;24}2526// Synthetic Children Provider27namespace {2829class GenericOptionalFrontend : public SyntheticChildrenFrontEnd {30public:31enum class StdLib {32LibCxx,33LibStdcpp,34};3536GenericOptionalFrontend(ValueObject &valobj, StdLib stdlib);3738size_t GetIndexOfChildWithName(ConstString name) override {39return formatters::ExtractIndexFromString(name.GetCString());40}4142bool MightHaveChildren() override { return true; }43llvm::Expected<uint32_t> CalculateNumChildren() override {44return m_has_value ? 1U : 0U;45}4647ValueObjectSP GetChildAtIndex(uint32_t idx) override;48lldb::ChildCacheState Update() override;4950private:51bool m_has_value = false;52StdLib m_stdlib;53};5455} // namespace5657GenericOptionalFrontend::GenericOptionalFrontend(ValueObject &valobj,58StdLib stdlib)59: SyntheticChildrenFrontEnd(valobj), m_stdlib(stdlib) {60if (auto target_sp = m_backend.GetTargetSP()) {61Update();62}63}6465lldb::ChildCacheState GenericOptionalFrontend::Update() {66ValueObjectSP engaged_sp;6768if (m_stdlib == StdLib::LibCxx)69engaged_sp = m_backend.GetChildMemberWithName("__engaged_");70else if (m_stdlib == StdLib::LibStdcpp)71engaged_sp = m_backend.GetChildMemberWithName("_M_payload")72->GetChildMemberWithName("_M_engaged");7374if (!engaged_sp)75return lldb::ChildCacheState::eRefetch;7677// _M_engaged/__engaged is a bool flag and is true if the optional contains a78// value. Converting it to unsigned gives us a size of 1 if it contains a79// value and 0 if not.80m_has_value = engaged_sp->GetValueAsUnsigned(0) != 0;8182return lldb::ChildCacheState::eRefetch;83}8485ValueObjectSP GenericOptionalFrontend::GetChildAtIndex(uint32_t _idx) {86if (!m_has_value)87return ValueObjectSP();8889ValueObjectSP val_sp;9091if (m_stdlib == StdLib::LibCxx)92// __val_ contains the underlying value of an optional if it has one.93// Currently because it is part of an anonymous union94// GetChildMemberWithName() does not peer through and find it unless we are95// at the parent itself. We can obtain the parent through __engaged_.96val_sp = m_backend.GetChildMemberWithName("__engaged_")97->GetParent()98->GetChildAtIndex(0)99->GetChildMemberWithName("__val_");100else if (m_stdlib == StdLib::LibStdcpp) {101val_sp = m_backend.GetChildMemberWithName("_M_payload")102->GetChildMemberWithName("_M_payload");103104// In some implementations, _M_value contains the underlying value of an105// optional, and in other versions, it's in the payload member.106ValueObjectSP candidate = val_sp->GetChildMemberWithName("_M_value");107if (candidate)108val_sp = candidate;109}110111if (!val_sp)112return ValueObjectSP();113114CompilerType holder_type = val_sp->GetCompilerType();115116if (!holder_type)117return ValueObjectSP();118119return val_sp->Clone(ConstString("Value"));120}121122SyntheticChildrenFrontEnd *123formatters::LibStdcppOptionalSyntheticFrontEndCreator(124CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {125if (valobj_sp)126return new GenericOptionalFrontend(127*valobj_sp, GenericOptionalFrontend::StdLib::LibStdcpp);128return nullptr;129}130131SyntheticChildrenFrontEnd *formatters::LibcxxOptionalSyntheticFrontEndCreator(132CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {133if (valobj_sp)134return new GenericOptionalFrontend(*valobj_sp,135GenericOptionalFrontend::StdLib::LibCxx);136return nullptr;137}138139140