brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.4 KiB · 7fc6eb5 Raw
168 lines · cpp
1//===-- GenericOptional.cpp ----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===---------------------------------------------------------------------===//8 9#include "Generic.h"10#include "LibCxx.h"11#include "LibStdcpp.h"12#include "MsvcStl.h"13#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"14#include "lldb/DataFormatters/FormattersHelpers.h"15#include "lldb/Target/Target.h"16 17using namespace lldb;18using namespace lldb_private;19 20bool lldb_private::formatters::GenericOptionalSummaryProvider(21    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {22  stream.Printf(" Has Value=%s ",23                valobj.GetNumChildrenIgnoringErrors() == 0 ? "false" : "true");24 25  return true;26}27 28// Synthetic Children Provider29namespace {30 31class GenericOptionalFrontend : public SyntheticChildrenFrontEnd {32public:33  enum class StdLib {34    LibCxx,35    LibStdcpp,36    MsvcStl,37  };38 39  GenericOptionalFrontend(ValueObject &valobj, StdLib stdlib);40 41  llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {42    if (name == "$$dereference$$")43      return 0;44    auto optional_idx = formatters::ExtractIndexFromString(name.GetCString());45    if (!optional_idx) {46      return llvm::createStringError("Type has no child named '%s'",47                                     name.AsCString());48    }49    return *optional_idx;50  }51 52  llvm::Expected<uint32_t> CalculateNumChildren() override {53    return m_has_value ? 1U : 0U;54  }55 56  ValueObjectSP GetChildAtIndex(uint32_t idx) override;57  lldb::ChildCacheState Update() override;58 59private:60  bool m_has_value = false;61  StdLib m_stdlib;62};63 64} // namespace65 66GenericOptionalFrontend::GenericOptionalFrontend(ValueObject &valobj,67                                                 StdLib stdlib)68    : SyntheticChildrenFrontEnd(valobj), m_stdlib(stdlib) {69  if (auto target_sp = m_backend.GetTargetSP()) {70    Update();71  }72}73 74lldb::ChildCacheState GenericOptionalFrontend::Update() {75  ValueObjectSP engaged_sp;76 77  if (m_stdlib == StdLib::LibCxx)78    engaged_sp = m_backend.GetChildMemberWithName("__engaged_");79  else if (m_stdlib == StdLib::LibStdcpp) {80    if (ValueObjectSP payload = m_backend.GetChildMemberWithName("_M_payload"))81      engaged_sp = payload->GetChildMemberWithName("_M_engaged");82  } else if (m_stdlib == StdLib::MsvcStl)83    engaged_sp = m_backend.GetChildMemberWithName("_Has_value");84 85  if (!engaged_sp)86    return lldb::ChildCacheState::eRefetch;87 88  // _M_engaged/__engaged is a bool flag and is true if the optional contains a89  // value. Converting it to unsigned gives us a size of 1 if it contains a90  // value and 0 if not.91  m_has_value = engaged_sp->GetValueAsUnsigned(0) != 0;92 93  return lldb::ChildCacheState::eRefetch;94}95 96ValueObjectSP GenericOptionalFrontend::GetChildAtIndex(uint32_t _idx) {97  if (!m_has_value)98    return ValueObjectSP();99 100  ValueObjectSP val_sp;101 102  if (m_stdlib == StdLib::LibCxx)103    // __val_ contains the underlying value of an optional if it has one.104    // Currently because it is part of an anonymous union105    // GetChildMemberWithName() does not peer through and find it unless we are106    // at the parent itself. We can obtain the parent through __engaged_.107    val_sp = m_backend.GetChildMemberWithName("__engaged_")108                 ->GetParent()109                 ->GetChildAtIndex(0)110                 ->GetChildMemberWithName("__val_");111  else if (m_stdlib == StdLib::LibStdcpp) {112    val_sp = m_backend.GetChildMemberWithName("_M_payload")113                 ->GetChildMemberWithName("_M_payload");114 115    // In some implementations, _M_value contains the underlying value of an116    // optional, and in other versions, it's in the payload member.117    ValueObjectSP candidate = val_sp->GetChildMemberWithName("_M_value");118    if (candidate)119      val_sp = candidate;120  } else if (m_stdlib == StdLib::MsvcStl)121    // Same issue as with LibCxx122    val_sp = m_backend.GetChildMemberWithName("_Has_value")123                 ->GetParent()124                 ->GetChildAtIndex(0)125                 ->GetChildMemberWithName("_Value");126 127  if (!val_sp)128    return ValueObjectSP();129 130  CompilerType holder_type = val_sp->GetCompilerType();131 132  if (!holder_type)133    return ValueObjectSP();134 135  return val_sp->Clone(ConstString("Value"));136}137 138SyntheticChildrenFrontEnd *139formatters::LibStdcppOptionalSyntheticFrontEndCreator(140    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {141  if (valobj_sp)142    return new GenericOptionalFrontend(143        *valobj_sp, GenericOptionalFrontend::StdLib::LibStdcpp);144  return nullptr;145}146 147SyntheticChildrenFrontEnd *formatters::LibcxxOptionalSyntheticFrontEndCreator(148    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {149  if (valobj_sp)150    return new GenericOptionalFrontend(*valobj_sp,151                                       GenericOptionalFrontend::StdLib::LibCxx);152  return nullptr;153}154 155bool formatters::IsMsvcStlOptional(ValueObject &valobj) {156  if (auto valobj_sp = valobj.GetNonSyntheticValue())157    return valobj_sp->GetChildMemberWithName("_Has_value") != nullptr;158  return false;159}160 161SyntheticChildrenFrontEnd *formatters::MsvcStlOptionalSyntheticFrontEndCreator(162    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {163  if (valobj_sp)164    return new GenericOptionalFrontend(165        *valobj_sp, GenericOptionalFrontend::StdLib::MsvcStl);166  return nullptr;167}168