brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.6 KiB · 7f012b7 Raw
146 lines · cpp
1//===-- GenericInitializerList.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 "lldb/DataFormatters/FormattersHelpers.h"10#include "lldb/Utility/ConstString.h"11#include "lldb/ValueObject/ValueObject.h"12#include <cstddef>13#include <optional>14#include <type_traits>15 16using namespace lldb;17using namespace lldb_private;18 19namespace generic_check {20template <class T>21using size_func = decltype(T::GetSizeMember(std::declval<ValueObject &>()));22template <class T>23using start_func = decltype(T::GetStartMember(std::declval<ValueObject &>()));24namespace {25template <typename...> struct check_func : std::true_type {};26} // namespace27 28template <typename T>29using has_functions = check_func<size_func<T>, start_func<T>>;30} // namespace generic_check31 32struct LibCxx {33  static ValueObjectSP GetStartMember(ValueObject &backend) {34    return backend.GetChildMemberWithName("__begin_");35  }36 37  static ValueObjectSP GetSizeMember(ValueObject &backend) {38    return backend.GetChildMemberWithName("__size_");39  }40};41 42struct LibStdcpp {43  static ValueObjectSP GetStartMember(ValueObject &backend) {44    return backend.GetChildMemberWithName("_M_array");45  }46 47  static ValueObjectSP GetSizeMember(ValueObject &backend) {48    return backend.GetChildMemberWithName("_M_len");49  }50};51 52namespace lldb_private::formatters {53 54template <class StandardImpl>55class GenericInitializerListSyntheticFrontEnd56    : public SyntheticChildrenFrontEnd {57public:58  static_assert(generic_check::has_functions<StandardImpl>::value,59                "Missing Required Functions.");60 61  GenericInitializerListSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)62      : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {63    if (valobj_sp)64      Update();65  }66 67  ~GenericInitializerListSyntheticFrontEnd() override {68    // this needs to stay around because it's a child object who will follow its69    // parent's life cycle70    // delete m_start;71  }72 73  llvm::Expected<uint32_t> CalculateNumChildren() override {74    m_num_elements = 0;75 76    const ValueObjectSP size_sp(StandardImpl::GetSizeMember(m_backend));77    if (size_sp)78      m_num_elements = size_sp->GetValueAsUnsigned(0);79    return m_num_elements;80  }81 82  lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {83    if (!m_start)84      return {};85 86    uint64_t offset = static_cast<uint64_t>(idx) * m_element_size;87    offset = offset + m_start->GetValueAsUnsigned(0);88    StreamString name;89    name.Printf("[%" PRIu64 "]", (uint64_t)idx);90    return CreateValueObjectFromAddress(name.GetString(), offset,91                                        m_backend.GetExecutionContextRef(),92                                        m_element_type);93  }94 95  lldb::ChildCacheState Update() override {96    m_start = nullptr;97    m_num_elements = 0;98    m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0);99    if (!m_element_type.IsValid())100      return lldb::ChildCacheState::eRefetch;101 102    llvm::Expected<uint64_t> size_or_err = m_element_type.GetByteSize(nullptr);103    if (!size_or_err)104      LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters), size_or_err.takeError(),105                      "{0}");106    else {107      m_element_size = *size_or_err;108      // Store raw pointers or end up with a circular dependency.109      m_start = StandardImpl::GetStartMember(m_backend).get();110    }111 112    return lldb::ChildCacheState::eRefetch;113  }114 115  llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {116    if (!m_start) {117      return llvm::createStringError("Type has no child named '%s'",118                                     name.AsCString());119    }120    auto optional_idx = formatters::ExtractIndexFromString(name.GetCString());121    if (!optional_idx) {122      return llvm::createStringError("Type has no child named '%s'",123                                     name.AsCString());124    }125    return *optional_idx;126  }127 128private:129  ValueObject *m_start = nullptr;130  CompilerType m_element_type;131  uint32_t m_element_size = 0;132  size_t m_num_elements = 0;133};134 135SyntheticChildrenFrontEnd *GenericInitializerListSyntheticFrontEndCreator(136    CXXSyntheticChildren * /*unused*/, lldb::ValueObjectSP valobj_sp) {137  if (!valobj_sp)138    return nullptr;139 140  if (LibCxx::GetStartMember(*valobj_sp) != nullptr)141    return new GenericInitializerListSyntheticFrontEnd<LibCxx>(valobj_sp);142 143  return new GenericInitializerListSyntheticFrontEnd<LibStdcpp>(valobj_sp);144}145} // namespace lldb_private::formatters146