15ffd83dbSDimitry Andric //===-- LibStdcppTuple.cpp ------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "LibStdcpp.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
120b57cec5SDimitry Andric #include "lldb/DataFormatters/FormattersHelpers.h"
130b57cec5SDimitry Andric #include "lldb/DataFormatters/TypeSynthetic.h"
140b57cec5SDimitry Andric #include "lldb/Utility/ConstString.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include <memory>
170b57cec5SDimitry Andric #include <vector>
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric using namespace lldb;
200b57cec5SDimitry Andric using namespace lldb_private;
210b57cec5SDimitry Andric using namespace lldb_private::formatters;
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric namespace {
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric class LibStdcppTupleSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
260b57cec5SDimitry Andric public:
270b57cec5SDimitry Andric   explicit LibStdcppTupleSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric   size_t CalculateNumChildren() override;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric   lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric   bool Update() override;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric   bool MightHaveChildren() override;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric   size_t GetIndexOfChildWithName(ConstString name) override;
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric private:
409dba64beSDimitry Andric   // The lifetime of a ValueObject and all its derivative ValueObjects
419dba64beSDimitry Andric   // (children, clones, etc.) is managed by a ClusterManager. These
429dba64beSDimitry Andric   // objects are only destroyed when every shared pointer to any of them
439dba64beSDimitry Andric   // is destroyed, so we must not store a shared pointer to any ValueObject
449dba64beSDimitry Andric   // derived from our backend ValueObject (since we're in the same cluster).
459dba64beSDimitry Andric   std::vector<ValueObject*> m_members;
460b57cec5SDimitry Andric };
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric } // end of anonymous namespace
490b57cec5SDimitry Andric 
LibStdcppTupleSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)500b57cec5SDimitry Andric LibStdcppTupleSyntheticFrontEnd::LibStdcppTupleSyntheticFrontEnd(
510b57cec5SDimitry Andric     lldb::ValueObjectSP valobj_sp)
520b57cec5SDimitry Andric     : SyntheticChildrenFrontEnd(*valobj_sp) {
530b57cec5SDimitry Andric   Update();
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
Update()560b57cec5SDimitry Andric bool LibStdcppTupleSyntheticFrontEnd::Update() {
570b57cec5SDimitry Andric   m_members.clear();
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   ValueObjectSP valobj_backend_sp = m_backend.GetSP();
600b57cec5SDimitry Andric   if (!valobj_backend_sp)
610b57cec5SDimitry Andric     return false;
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   ValueObjectSP next_child_sp = valobj_backend_sp->GetNonSyntheticValue();
640b57cec5SDimitry Andric   while (next_child_sp != nullptr) {
650b57cec5SDimitry Andric     ValueObjectSP current_child = next_child_sp;
660b57cec5SDimitry Andric     next_child_sp = nullptr;
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric     size_t child_count = current_child->GetNumChildren();
690b57cec5SDimitry Andric     for (size_t i = 0; i < child_count; ++i) {
7006c3fb27SDimitry Andric       ValueObjectSP child_sp = current_child->GetChildAtIndex(i);
710b57cec5SDimitry Andric       llvm::StringRef name_str = child_sp->GetName().GetStringRef();
725f757f3fSDimitry Andric       if (name_str.starts_with("std::_Tuple_impl<")) {
730b57cec5SDimitry Andric         next_child_sp = child_sp;
745f757f3fSDimitry Andric       } else if (name_str.starts_with("std::_Head_base<")) {
750b57cec5SDimitry Andric         ValueObjectSP value_sp =
7606c3fb27SDimitry Andric             child_sp->GetChildMemberWithName("_M_head_impl");
770b57cec5SDimitry Andric         if (value_sp) {
780b57cec5SDimitry Andric           StreamString name;
790b57cec5SDimitry Andric           name.Printf("[%zd]", m_members.size());
809dba64beSDimitry Andric           m_members.push_back(value_sp->Clone(ConstString(name.GetString())).get());
810b57cec5SDimitry Andric         }
820b57cec5SDimitry Andric       }
830b57cec5SDimitry Andric     }
840b57cec5SDimitry Andric   }
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   return false;
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric 
MightHaveChildren()890b57cec5SDimitry Andric bool LibStdcppTupleSyntheticFrontEnd::MightHaveChildren() { return true; }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric lldb::ValueObjectSP
GetChildAtIndex(size_t idx)920b57cec5SDimitry Andric LibStdcppTupleSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
939dba64beSDimitry Andric   if (idx < m_members.size() && m_members[idx])
949dba64beSDimitry Andric     return m_members[idx]->GetSP();
950b57cec5SDimitry Andric   return lldb::ValueObjectSP();
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric 
CalculateNumChildren()980b57cec5SDimitry Andric size_t LibStdcppTupleSyntheticFrontEnd::CalculateNumChildren() {
990b57cec5SDimitry Andric   return m_members.size();
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric 
GetIndexOfChildWithName(ConstString name)1020b57cec5SDimitry Andric size_t LibStdcppTupleSyntheticFrontEnd::GetIndexOfChildWithName(
1030b57cec5SDimitry Andric     ConstString name) {
1040b57cec5SDimitry Andric   return ExtractIndexFromString(name.GetCString());
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric SyntheticChildrenFrontEnd *
LibStdcppTupleSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)1080b57cec5SDimitry Andric lldb_private::formatters::LibStdcppTupleSyntheticFrontEndCreator(
1090b57cec5SDimitry Andric     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
1100b57cec5SDimitry Andric   return (valobj_sp ? new LibStdcppTupleSyntheticFrontEnd(valobj_sp) : nullptr);
1110b57cec5SDimitry Andric }
112