1 //===-- LibStdcppUniquePointer.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 LibStdcppUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
27 public:
28 explicit LibStdcppUniquePtrSyntheticFrontEnd(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 bool GetSummary(Stream &stream, const TypeSummaryOptions &options);
41
42 private:
43 ValueObjectSP m_ptr_obj;
44 ValueObjectSP m_obj_obj;
45 ValueObjectSP m_del_obj;
46
47 ValueObjectSP GetTuple();
48 };
49
50 } // end of anonymous namespace
51
LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)52 LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd(
53 lldb::ValueObjectSP valobj_sp)
54 : SyntheticChildrenFrontEnd(*valobj_sp) {
55 Update();
56 }
57
GetTuple()58 ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetTuple() {
59 ValueObjectSP valobj_backend_sp = m_backend.GetSP();
60
61 if (!valobj_backend_sp)
62 return nullptr;
63
64 ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue();
65 if (!valobj_sp)
66 return nullptr;
67
68 ValueObjectSP obj_child_sp =
69 valobj_sp->GetChildMemberWithName(ConstString("_M_t"), true);
70 if (!obj_child_sp)
71 return nullptr;
72
73 ValueObjectSP obj_subchild_sp =
74 obj_child_sp->GetChildMemberWithName(ConstString("_M_t"), true);
75
76 // if there is a _M_t subchild, the tuple is found in the obj_subchild_sp
77 // (for libstdc++ 6.0.23).
78 if (obj_subchild_sp) {
79 return obj_subchild_sp;
80 }
81
82 return obj_child_sp;
83 }
84
Update()85 bool LibStdcppUniquePtrSyntheticFrontEnd::Update() {
86 ValueObjectSP tuple_sp = GetTuple();
87
88 if (!tuple_sp)
89 return false;
90
91 std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend(
92 LibStdcppTupleSyntheticFrontEndCreator(nullptr, tuple_sp));
93
94 ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0);
95 if (ptr_obj)
96 m_ptr_obj = ptr_obj->Clone(ConstString("pointer"));
97
98 ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1);
99 if (del_obj)
100 m_del_obj = del_obj->Clone(ConstString("deleter"));
101
102 if (m_ptr_obj) {
103 Status error;
104 ValueObjectSP obj_obj = m_ptr_obj->Dereference(error);
105 if (error.Success()) {
106 m_obj_obj = obj_obj->Clone(ConstString("object"));
107 }
108 }
109
110 return false;
111 }
112
MightHaveChildren()113 bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; }
114
115 lldb::ValueObjectSP
GetChildAtIndex(size_t idx)116 LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
117 if (idx == 0)
118 return m_ptr_obj;
119 if (idx == 1)
120 return m_del_obj;
121 if (idx == 2)
122 return m_obj_obj;
123 return lldb::ValueObjectSP();
124 }
125
CalculateNumChildren()126 size_t LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() {
127 if (m_del_obj)
128 return 2;
129 return 1;
130 }
131
GetIndexOfChildWithName(const ConstString & name)132 size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName(
133 const ConstString &name) {
134 if (name == ConstString("ptr") || name == ConstString("pointer"))
135 return 0;
136 if (name == ConstString("del") || name == ConstString("deleter"))
137 return 1;
138 if (name == ConstString("obj") || name == ConstString("object") ||
139 name == ConstString("$$dereference$$"))
140 return 2;
141 return UINT32_MAX;
142 }
143
GetSummary(Stream & stream,const TypeSummaryOptions & options)144 bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary(
145 Stream &stream, const TypeSummaryOptions &options) {
146 if (!m_ptr_obj)
147 return false;
148
149 bool success;
150 uint64_t ptr_value = m_ptr_obj->GetValueAsUnsigned(0, &success);
151 if (!success)
152 return false;
153 if (ptr_value == 0)
154 stream.Printf("nullptr");
155 else
156 stream.Printf("0x%" PRIx64, ptr_value);
157 return true;
158 }
159
160 SyntheticChildrenFrontEnd *
LibStdcppUniquePtrSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)161 lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator(
162 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
163 return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp)
164 : nullptr);
165 }
166
LibStdcppUniquePointerSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & options)167 bool lldb_private::formatters::LibStdcppUniquePointerSummaryProvider(
168 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
169 LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP());
170 return formatter.GetSummary(stream, options);
171 }
172