1 //===-- LibStdcppTuple.cpp --------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "LibStdcpp.h" 11 12 #include "lldb/Core/ValueObject.h" 13 #include "lldb/DataFormatters/FormattersHelpers.h" 14 #include "lldb/DataFormatters/TypeSynthetic.h" 15 #include "lldb/Utility/ConstString.h" 16 17 #include <memory> 18 #include <vector> 19 20 using namespace lldb; 21 using namespace lldb_private; 22 using namespace lldb_private::formatters; 23 24 namespace { 25 26 class LibStdcppTupleSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 27 public: 28 explicit LibStdcppTupleSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 29 30 size_t CalculateNumChildren() override; 31 32 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 33 34 bool Update() override; 35 36 bool MightHaveChildren() override; 37 38 size_t GetIndexOfChildWithName(const ConstString &name) override; 39 40 private: 41 std::vector<ValueObjectSP> m_members; 42 }; 43 44 } // end of anonymous namespace 45 46 LibStdcppTupleSyntheticFrontEnd::LibStdcppTupleSyntheticFrontEnd( 47 lldb::ValueObjectSP valobj_sp) 48 : SyntheticChildrenFrontEnd(*valobj_sp) { 49 Update(); 50 } 51 52 bool LibStdcppTupleSyntheticFrontEnd::Update() { 53 m_members.clear(); 54 55 ValueObjectSP valobj_backend_sp = m_backend.GetSP(); 56 if (!valobj_backend_sp) 57 return false; 58 59 ValueObjectSP next_child_sp = valobj_backend_sp->GetNonSyntheticValue(); 60 while (next_child_sp != nullptr) { 61 ValueObjectSP current_child = next_child_sp; 62 next_child_sp = nullptr; 63 64 size_t child_count = current_child->GetNumChildren(); 65 for (size_t i = 0; i < child_count; ++i) { 66 ValueObjectSP child_sp = current_child->GetChildAtIndex(i, true); 67 llvm::StringRef name_str = child_sp->GetName().GetStringRef(); 68 if (name_str.startswith("std::_Tuple_impl<")) { 69 next_child_sp = child_sp; 70 } else if (name_str.startswith("std::_Head_base<")) { 71 ValueObjectSP value_sp = 72 child_sp->GetChildMemberWithName(ConstString("_M_head_impl"), true); 73 if (value_sp) { 74 StreamString name; 75 name.Printf("[%zd]", m_members.size()); 76 m_members.push_back(value_sp->Clone(ConstString(name.GetString()))); 77 } 78 } 79 } 80 } 81 82 return false; 83 } 84 85 bool LibStdcppTupleSyntheticFrontEnd::MightHaveChildren() { return true; } 86 87 lldb::ValueObjectSP 88 LibStdcppTupleSyntheticFrontEnd::GetChildAtIndex(size_t idx) { 89 if (idx < m_members.size()) 90 return m_members[idx]; 91 return lldb::ValueObjectSP(); 92 } 93 94 size_t LibStdcppTupleSyntheticFrontEnd::CalculateNumChildren() { 95 return m_members.size(); 96 } 97 98 size_t LibStdcppTupleSyntheticFrontEnd::GetIndexOfChildWithName( 99 const ConstString &name) { 100 return ExtractIndexFromString(name.GetCString()); 101 } 102 103 SyntheticChildrenFrontEnd * 104 lldb_private::formatters::LibStdcppTupleSyntheticFrontEndCreator( 105 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 106 return (valobj_sp ? new LibStdcppTupleSyntheticFrontEnd(valobj_sp) : nullptr); 107 } 108