brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.9 KiB · 52a3d98 Raw
189 lines · cpp
1//===-- MsvcStlVariant.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 "MsvcStl.h"10#include "lldb/DataFormatters/FormattersHelpers.h"11#include "lldb/Symbol/CompilerType.h"12#include <optional>13 14using namespace lldb;15using namespace lldb_private;16 17namespace {18 19// A variant when using DWARF looks as follows:20// (lldb) fr v -R v121// (std::variant<int, double, char>) v1 = {22//   std::_SMF_control<std::_Variant_base<int, double, char>, int, double, char>23//   = {24//     std::_Variant_storage<int, double, char> = {25//        = {26//         _Head = 027//         _Tail = {28//            = {29//             _Head = 230//             _Tail = {31//                = {32//                 _Head = '\0'33//                 _Tail = {}34//               }35//             }36//           }37//         }38//       }39//     }40//     _Which = '\x01'41//   }42// }43 44ValueObjectSP GetStorageMember(ValueObject &valobj, llvm::StringRef name) {45  // Find the union46  ValueObjectSP union_sp = valobj.GetChildAtIndex(0);47  if (!union_sp)48    return nullptr;49  return union_sp->GetChildMemberWithName(name);50}51 52ValueObjectSP GetHead(ValueObject &valobj) {53  return GetStorageMember(valobj, "_Head");54}55ValueObjectSP GetTail(ValueObject &valobj) {56  return GetStorageMember(valobj, "_Tail");57}58 59std::optional<int64_t> GetIndexValue(ValueObject &valobj) {60  ValueObjectSP index_sp = valobj.GetChildMemberWithName("_Which");61  if (!index_sp)62    return std::nullopt;63 64  return {index_sp->GetValueAsSigned(-1)};65}66 67ValueObjectSP GetNthStorage(ValueObject &outer, int64_t index) {68  // We need to find the std::_Variant_storage base class.69 70  // -> std::_SMF_control (typedef to std::_Variant_base)71  ValueObjectSP container_sp = outer.GetSP()->GetChildAtIndex(0);72  if (!container_sp)73    return nullptr;74  // -> std::_Variant_storage75  container_sp = container_sp->GetChildAtIndex(0);76  if (!container_sp)77    return nullptr;78 79  for (int64_t i = 0; i < index; i++) {80    container_sp = GetTail(*container_sp);81    if (!container_sp)82      return nullptr;83  }84  return container_sp;85}86 87} // namespace88 89bool formatters::IsMsvcStlVariant(ValueObject &valobj) {90  if (auto valobj_sp = valobj.GetNonSyntheticValue()) {91    return valobj_sp->GetChildMemberWithName("_Which") != nullptr;92  }93  return false;94}95 96bool formatters::MsvcStlVariantSummaryProvider(97    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {98  ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());99  if (!valobj_sp)100    return false;101 102  auto index = GetIndexValue(*valobj_sp);103  if (!index)104    return false;105 106  if (*index < 0) {107    stream.Printf(" No Value");108    return true;109  }110 111  ValueObjectSP storage = GetNthStorage(*valobj_sp, *index);112  if (!storage)113    return false;114  CompilerType storage_type = storage->GetCompilerType();115  if (!storage_type)116    return false;117  // Resolve the typedef118  if (storage_type.IsTypedefType())119    storage_type = storage_type.GetTypedefedType();120 121  CompilerType active_type = storage_type.GetTypeTemplateArgument(1, true);122  if (!active_type)123    return false;124 125  stream << " Active Type = " << active_type.GetDisplayTypeName() << " ";126  return true;127}128 129namespace {130class VariantFrontEnd : public SyntheticChildrenFrontEnd {131public:132  VariantFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) {133    Update();134  }135 136  llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {137    auto optional_idx = formatters::ExtractIndexFromString(name.GetCString());138    if (!optional_idx) {139      return llvm::createStringError("Type has no child named '%s'",140                                     name.AsCString());141    }142    return *optional_idx;143  }144 145  lldb::ChildCacheState Update() override;146  llvm::Expected<uint32_t> CalculateNumChildren() override { return m_size; }147  ValueObjectSP GetChildAtIndex(uint32_t idx) override;148 149private:150  size_t m_size = 0;151};152} // namespace153 154lldb::ChildCacheState VariantFrontEnd::Update() {155  m_size = 0;156 157  auto index = GetIndexValue(m_backend);158  if (index && *index >= 0)159    m_size = 1;160 161  return lldb::ChildCacheState::eRefetch;162}163 164ValueObjectSP VariantFrontEnd::GetChildAtIndex(uint32_t idx) {165  if (idx >= m_size)166    return nullptr;167 168  auto index = GetIndexValue(m_backend);169  if (!index)170    return nullptr;171 172  ValueObjectSP storage_sp = GetNthStorage(m_backend, *index);173  if (!storage_sp)174    return nullptr;175 176  ValueObjectSP head_sp = GetHead(*storage_sp);177  if (!head_sp)178    return nullptr;179 180  return head_sp->Clone(ConstString("Value"));181}182 183SyntheticChildrenFrontEnd *formatters::MsvcStlVariantSyntheticFrontEndCreator(184    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {185  if (valobj_sp)186    return new VariantFrontEnd(*valobj_sp);187  return nullptr;188}189