180814287SRaphael Isemann //===-- LibStdcppUniquePointer.cpp ----------------------------------------===//
2d161b214STamas Berghammer //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d161b214STamas Berghammer //
7d161b214STamas Berghammer //===----------------------------------------------------------------------===//
8d161b214STamas Berghammer 
9d161b214STamas Berghammer #include "LibStdcpp.h"
10d161b214STamas Berghammer 
11d161b214STamas Berghammer #include "lldb/Core/ValueObject.h"
12d161b214STamas Berghammer #include "lldb/DataFormatters/FormattersHelpers.h"
13d161b214STamas Berghammer #include "lldb/DataFormatters/TypeSynthetic.h"
14bf9a7730SZachary Turner #include "lldb/Utility/ConstString.h"
15d161b214STamas Berghammer 
16de2cc6e4STamas Berghammer #include <memory>
17de2cc6e4STamas Berghammer #include <vector>
18de2cc6e4STamas Berghammer 
19d161b214STamas Berghammer using namespace lldb;
20d161b214STamas Berghammer using namespace lldb_private;
21d161b214STamas Berghammer using namespace lldb_private::formatters;
22d161b214STamas Berghammer 
23d161b214STamas Berghammer namespace {
24d161b214STamas Berghammer 
25d161b214STamas Berghammer class LibStdcppUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
26d161b214STamas Berghammer public:
27d161b214STamas Berghammer   explicit LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
28d161b214STamas Berghammer 
29d161b214STamas Berghammer   size_t CalculateNumChildren() override;
30d161b214STamas Berghammer 
31d161b214STamas Berghammer   lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
32d161b214STamas Berghammer 
33d161b214STamas Berghammer   bool Update() override;
34d161b214STamas Berghammer 
35d161b214STamas Berghammer   bool MightHaveChildren() override;
36d161b214STamas Berghammer 
370e4c4821SAdrian Prantl   size_t GetIndexOfChildWithName(ConstString name) override;
38d161b214STamas Berghammer 
39d161b214STamas Berghammer   bool GetSummary(Stream &stream, const TypeSummaryOptions &options);
40d161b214STamas Berghammer 
41d161b214STamas Berghammer private:
4289386daaSCameron Desrochers   // The lifetime of a ValueObject and all its derivative ValueObjects
4389386daaSCameron Desrochers   // (children, clones, etc.) is managed by a ClusterManager. These
4489386daaSCameron Desrochers   // objects are only destroyed when every shared pointer to any of them
4589386daaSCameron Desrochers   // is destroyed, so we must not store a shared pointer to any ValueObject
4689386daaSCameron Desrochers   // derived from our backend ValueObject (since we're in the same cluster).
4789386daaSCameron Desrochers   ValueObject* m_ptr_obj = nullptr;
4889386daaSCameron Desrochers   ValueObject* m_obj_obj = nullptr;
4989386daaSCameron Desrochers   ValueObject* m_del_obj = nullptr;
50b312b139SPavel Labath 
51b312b139SPavel Labath   ValueObjectSP GetTuple();
52d161b214STamas Berghammer };
53d161b214STamas Berghammer 
54d161b214STamas Berghammer } // end of anonymous namespace
55d161b214STamas Berghammer 
LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)56d161b214STamas Berghammer LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd(
57d161b214STamas Berghammer     lldb::ValueObjectSP valobj_sp)
58d161b214STamas Berghammer     : SyntheticChildrenFrontEnd(*valobj_sp) {
59d161b214STamas Berghammer   Update();
60d161b214STamas Berghammer }
61d161b214STamas Berghammer 
GetTuple()62b312b139SPavel Labath ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetTuple() {
63d161b214STamas Berghammer   ValueObjectSP valobj_backend_sp = m_backend.GetSP();
64b312b139SPavel Labath 
65d161b214STamas Berghammer   if (!valobj_backend_sp)
66b312b139SPavel Labath     return nullptr;
67d161b214STamas Berghammer 
68d161b214STamas Berghammer   ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue();
69d161b214STamas Berghammer   if (!valobj_sp)
70b312b139SPavel Labath     return nullptr;
71d161b214STamas Berghammer 
72b312b139SPavel Labath   ValueObjectSP obj_child_sp =
73d161b214STamas Berghammer       valobj_sp->GetChildMemberWithName(ConstString("_M_t"), true);
74cb512a30SPavel Labath   if (!obj_child_sp)
75cb512a30SPavel Labath       return nullptr;
76b312b139SPavel Labath 
77b312b139SPavel Labath   ValueObjectSP obj_subchild_sp =
78b312b139SPavel Labath       obj_child_sp->GetChildMemberWithName(ConstString("_M_t"), true);
79b312b139SPavel Labath 
8005097246SAdrian Prantl   // if there is a _M_t subchild, the tuple is found in the obj_subchild_sp
8105097246SAdrian Prantl   // (for libstdc++ 6.0.23).
82b312b139SPavel Labath   if (obj_subchild_sp) {
83b312b139SPavel Labath     return obj_subchild_sp;
84b312b139SPavel Labath   }
85b312b139SPavel Labath 
86b312b139SPavel Labath   return obj_child_sp;
87b312b139SPavel Labath }
88b312b139SPavel Labath 
Update()89b312b139SPavel Labath bool LibStdcppUniquePtrSyntheticFrontEnd::Update() {
90b312b139SPavel Labath   ValueObjectSP tuple_sp = GetTuple();
91b312b139SPavel Labath 
92d161b214STamas Berghammer   if (!tuple_sp)
93d161b214STamas Berghammer     return false;
94d161b214STamas Berghammer 
95d161b214STamas Berghammer   std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend(
96d161b214STamas Berghammer       LibStdcppTupleSyntheticFrontEndCreator(nullptr, tuple_sp));
97d161b214STamas Berghammer 
984fbb55b7STamas Berghammer   ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0);
994fbb55b7STamas Berghammer   if (ptr_obj)
10089386daaSCameron Desrochers     m_ptr_obj = ptr_obj->Clone(ConstString("pointer")).get();
101d161b214STamas Berghammer 
102*fffb9750SJan Kratochvil   // Add a 'deleter' child if there was a non-empty deleter type specified.
103*fffb9750SJan Kratochvil   //
104*fffb9750SJan Kratochvil   // The object might have size=1 in the TypeSystem but occupies no dedicated
105*fffb9750SJan Kratochvil   // storage due to no_unique_address, so infer the actual size from the total
106*fffb9750SJan Kratochvil   // size of the unique_ptr class. If sizeof(unique_ptr) == sizeof(void*) then
107*fffb9750SJan Kratochvil   // the deleter is empty and should be hidden.
108*fffb9750SJan Kratochvil   if (tuple_sp->GetByteSize() > ptr_obj->GetByteSize()) {
1094fbb55b7STamas Berghammer     ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1);
1104fbb55b7STamas Berghammer     if (del_obj)
11189386daaSCameron Desrochers       m_del_obj = del_obj->Clone(ConstString("deleter")).get();
112*fffb9750SJan Kratochvil   }
113d161b214STamas Berghammer 
114d161b214STamas Berghammer   if (m_ptr_obj) {
11597206d57SZachary Turner     Status error;
1164fbb55b7STamas Berghammer     ValueObjectSP obj_obj = m_ptr_obj->Dereference(error);
117d161b214STamas Berghammer     if (error.Success()) {
11889386daaSCameron Desrochers       m_obj_obj = obj_obj->Clone(ConstString("object")).get();
119d161b214STamas Berghammer     }
120d161b214STamas Berghammer   }
121d161b214STamas Berghammer 
122d161b214STamas Berghammer   return false;
123d161b214STamas Berghammer }
124d161b214STamas Berghammer 
MightHaveChildren()125d161b214STamas Berghammer bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; }
126d161b214STamas Berghammer 
127d161b214STamas Berghammer lldb::ValueObjectSP
GetChildAtIndex(size_t idx)128d161b214STamas Berghammer LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
129745e57c5SCameron Desrochers   if (idx == 0 && m_ptr_obj)
13089386daaSCameron Desrochers     return m_ptr_obj->GetSP();
131745e57c5SCameron Desrochers   if (idx == 1 && m_del_obj)
13289386daaSCameron Desrochers     return m_del_obj->GetSP();
133745e57c5SCameron Desrochers   if (idx == 2 && m_obj_obj)
13489386daaSCameron Desrochers     return m_obj_obj->GetSP();
135d161b214STamas Berghammer   return lldb::ValueObjectSP();
136d161b214STamas Berghammer }
137d161b214STamas Berghammer 
CalculateNumChildren()138d161b214STamas Berghammer size_t LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() {
139d161b214STamas Berghammer   if (m_del_obj)
140d161b214STamas Berghammer     return 2;
141d161b214STamas Berghammer   return 1;
142d161b214STamas Berghammer }
143d161b214STamas Berghammer 
GetIndexOfChildWithName(ConstString name)144d161b214STamas Berghammer size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName(
1450e4c4821SAdrian Prantl     ConstString name) {
14605cfdb0eSRaphael Isemann   if (name == "ptr" || name == "pointer")
147d161b214STamas Berghammer     return 0;
14805cfdb0eSRaphael Isemann   if (name == "del" || name == "deleter")
149d161b214STamas Berghammer     return 1;
15005cfdb0eSRaphael Isemann   if (name == "obj" || name == "object" || name == "$$dereference$$")
151d161b214STamas Berghammer     return 2;
152d161b214STamas Berghammer   return UINT32_MAX;
153d161b214STamas Berghammer }
154d161b214STamas Berghammer 
GetSummary(Stream & stream,const TypeSummaryOptions & options)155d161b214STamas Berghammer bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary(
156d161b214STamas Berghammer     Stream &stream, const TypeSummaryOptions &options) {
157d161b214STamas Berghammer   if (!m_ptr_obj)
158d161b214STamas Berghammer     return false;
159d161b214STamas Berghammer 
160833e3d10SPavel Labath   bool success;
161833e3d10SPavel Labath   uint64_t ptr_value = m_ptr_obj->GetValueAsUnsigned(0, &success);
162833e3d10SPavel Labath   if (!success)
163833e3d10SPavel Labath     return false;
164833e3d10SPavel Labath   if (ptr_value == 0)
165d161b214STamas Berghammer     stream.Printf("nullptr");
166833e3d10SPavel Labath   else
167833e3d10SPavel Labath     stream.Printf("0x%" PRIx64, ptr_value);
168d161b214STamas Berghammer   return true;
169d161b214STamas Berghammer }
170d161b214STamas Berghammer 
171d161b214STamas Berghammer SyntheticChildrenFrontEnd *
LibStdcppUniquePtrSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)172d161b214STamas Berghammer lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator(
173d161b214STamas Berghammer     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
174d161b214STamas Berghammer   return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp)
175d161b214STamas Berghammer                     : nullptr);
176d161b214STamas Berghammer }
177d161b214STamas Berghammer 
LibStdcppUniquePointerSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & options)178d161b214STamas Berghammer bool lldb_private::formatters::LibStdcppUniquePointerSummaryProvider(
179d161b214STamas Berghammer     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
180d161b214STamas Berghammer   LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP());
181d161b214STamas Berghammer   return formatter.GetSummary(stream, options);
182d161b214STamas Berghammer }
183