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/ConstString.h"
13 #include "lldb/Core/ValueObject.h"
14 #include "lldb/DataFormatters/FormattersHelpers.h"
15 #include "lldb/DataFormatters/TypeSynthetic.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 
48 } // end of anonymous namespace
49 
50 LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd(
51     lldb::ValueObjectSP valobj_sp)
52     : SyntheticChildrenFrontEnd(*valobj_sp) {
53   Update();
54 }
55 
56 bool LibStdcppUniquePtrSyntheticFrontEnd::Update() {
57   ValueObjectSP valobj_backend_sp = m_backend.GetSP();
58   if (!valobj_backend_sp)
59     return false;
60 
61   ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue();
62   if (!valobj_sp)
63     return false;
64 
65   ValueObjectSP tuple_sp =
66       valobj_sp->GetChildMemberWithName(ConstString("_M_t"), true);
67   if (!tuple_sp)
68     return false;
69 
70   std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend(
71       LibStdcppTupleSyntheticFrontEndCreator(nullptr, tuple_sp));
72 
73   m_ptr_obj = tuple_frontend->GetChildAtIndex(0);
74   if (m_ptr_obj)
75     m_ptr_obj->SetName(ConstString("pointer"));
76 
77   m_del_obj = tuple_frontend->GetChildAtIndex(1);
78   if (m_del_obj)
79     m_del_obj->SetName(ConstString("deleter"));
80 
81   if (m_ptr_obj) {
82     Error error;
83     m_obj_obj = m_ptr_obj->Dereference(error);
84     if (error.Success()) {
85       m_obj_obj->SetName(ConstString("object"));
86     }
87   }
88 
89   return false;
90 }
91 
92 bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; }
93 
94 lldb::ValueObjectSP
95 LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
96   if (idx == 0)
97     return m_obj_obj;
98   if (idx == 1)
99     return m_del_obj;
100   if (idx == 2)
101     return m_ptr_obj;
102   return lldb::ValueObjectSP();
103 }
104 
105 size_t LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() {
106   if (m_del_obj)
107     return 2;
108   if (m_ptr_obj && m_ptr_obj->GetValueAsUnsigned(0) != 0)
109     return 1;
110   return 0;
111 }
112 
113 size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName(
114     const ConstString &name) {
115   if (name == ConstString("obj") || name == ConstString("object"))
116     return 0;
117   if (name == ConstString("del") || name == ConstString("deleter"))
118     return 1;
119   if (name == ConstString("ptr") || name == ConstString("pointer"))
120     return 2;
121   return UINT32_MAX;
122 }
123 
124 bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary(
125     Stream &stream, const TypeSummaryOptions &options) {
126   if (!m_ptr_obj)
127     return false;
128 
129   bool success;
130   uint64_t ptr_value = m_ptr_obj->GetValueAsUnsigned(0, &success);
131   if (!success)
132     return false;
133   if (ptr_value == 0)
134     stream.Printf("nullptr");
135   else
136     stream.Printf("0x%" PRIx64, ptr_value);
137   return true;
138 }
139 
140 SyntheticChildrenFrontEnd *
141 lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator(
142     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
143   return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp)
144                     : nullptr);
145 }
146 
147 bool lldb_private::formatters::LibStdcppUniquePointerSummaryProvider(
148     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
149   LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP());
150   return formatter.GetSummary(stream, options);
151 }
152