blob: 0b34b4e2fc8991f49f92749a4c879f1b64d48577 [file] [log] [blame]
Raphael Isemann80814282020-01-24 08:23:27 +01001//===-- LibStdcppUniquePointer.cpp ----------------------------------------===//
Tamas Berghammerd161b212016-10-21 15:02:44 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Tamas Berghammerd161b212016-10-21 15:02:44 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "LibStdcpp.h"
10
Tamas Berghammerd161b212016-10-21 15:02:44 +000011#include "lldb/Core/ValueObject.h"
12#include "lldb/DataFormatters/FormattersHelpers.h"
13#include "lldb/DataFormatters/TypeSynthetic.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000014#include "lldb/Utility/ConstString.h"
Tamas Berghammerd161b212016-10-21 15:02:44 +000015
Tamas Berghammerde2cc6e2016-10-21 15:05:03 +000016#include <memory>
17#include <vector>
18
Tamas Berghammerd161b212016-10-21 15:02:44 +000019using namespace lldb;
20using namespace lldb_private;
21using namespace lldb_private::formatters;
22
23namespace {
24
25class LibStdcppUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
26public:
27 explicit LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
28
29 size_t CalculateNumChildren() override;
30
31 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
32
33 bool Update() override;
34
35 bool MightHaveChildren() override;
36
Adrian Prantl0e4c4822019-03-06 21:22:25 +000037 size_t GetIndexOfChildWithName(ConstString name) override;
Tamas Berghammerd161b212016-10-21 15:02:44 +000038
39 bool GetSummary(Stream &stream, const TypeSummaryOptions &options);
40
41private:
Cameron Desrochers89386da2019-10-09 18:27:33 +000042 // The lifetime of a ValueObject and all its derivative ValueObjects
43 // (children, clones, etc.) is managed by a ClusterManager. These
44 // objects are only destroyed when every shared pointer to any of them
45 // is destroyed, so we must not store a shared pointer to any ValueObject
46 // derived from our backend ValueObject (since we're in the same cluster).
47 ValueObject* m_ptr_obj = nullptr;
48 ValueObject* m_obj_obj = nullptr;
49 ValueObject* m_del_obj = nullptr;
Pavel Labathb312b132018-03-08 16:03:09 +000050
51 ValueObjectSP GetTuple();
Tamas Berghammerd161b212016-10-21 15:02:44 +000052};
53
54} // end of anonymous namespace
55
56LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd(
57 lldb::ValueObjectSP valobj_sp)
58 : SyntheticChildrenFrontEnd(*valobj_sp) {
59 Update();
60}
61
Pavel Labathb312b132018-03-08 16:03:09 +000062ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetTuple() {
Tamas Berghammerd161b212016-10-21 15:02:44 +000063 ValueObjectSP valobj_backend_sp = m_backend.GetSP();
Pavel Labathb312b132018-03-08 16:03:09 +000064
Tamas Berghammerd161b212016-10-21 15:02:44 +000065 if (!valobj_backend_sp)
Pavel Labathb312b132018-03-08 16:03:09 +000066 return nullptr;
Tamas Berghammerd161b212016-10-21 15:02:44 +000067
68 ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue();
69 if (!valobj_sp)
Pavel Labathb312b132018-03-08 16:03:09 +000070 return nullptr;
Tamas Berghammerd161b212016-10-21 15:02:44 +000071
Pavel Labathb312b132018-03-08 16:03:09 +000072 ValueObjectSP obj_child_sp =
Tamas Berghammerd161b212016-10-21 15:02:44 +000073 valobj_sp->GetChildMemberWithName(ConstString("_M_t"), true);
Pavel Labathcb512a32018-06-11 14:52:52 +000074 if (!obj_child_sp)
75 return nullptr;
Pavel Labathb312b132018-03-08 16:03:09 +000076
77 ValueObjectSP obj_subchild_sp =
78 obj_child_sp->GetChildMemberWithName(ConstString("_M_t"), true);
79
Adrian Prantl05097242018-04-30 16:49:04 +000080 // if there is a _M_t subchild, the tuple is found in the obj_subchild_sp
81 // (for libstdc++ 6.0.23).
Pavel Labathb312b132018-03-08 16:03:09 +000082 if (obj_subchild_sp) {
83 return obj_subchild_sp;
84 }
85
86 return obj_child_sp;
87}
88
89bool LibStdcppUniquePtrSyntheticFrontEnd::Update() {
90 ValueObjectSP tuple_sp = GetTuple();
91
Tamas Berghammerd161b212016-10-21 15:02:44 +000092 if (!tuple_sp)
93 return false;
94
95 std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend(
96 LibStdcppTupleSyntheticFrontEndCreator(nullptr, tuple_sp));
97
Tamas Berghammer4fbb55b2017-03-31 20:48:00 +000098 ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0);
99 if (ptr_obj)
Cameron Desrochers89386da2019-10-09 18:27:33 +0000100 m_ptr_obj = ptr_obj->Clone(ConstString("pointer")).get();
Tamas Berghammerd161b212016-10-21 15:02:44 +0000101
Tamas Berghammer4fbb55b2017-03-31 20:48:00 +0000102 ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1);
103 if (del_obj)
Cameron Desrochers89386da2019-10-09 18:27:33 +0000104 m_del_obj = del_obj->Clone(ConstString("deleter")).get();
Tamas Berghammerd161b212016-10-21 15:02:44 +0000105
106 if (m_ptr_obj) {
Zachary Turner97206d52017-05-12 04:51:55 +0000107 Status error;
Tamas Berghammer4fbb55b2017-03-31 20:48:00 +0000108 ValueObjectSP obj_obj = m_ptr_obj->Dereference(error);
Tamas Berghammerd161b212016-10-21 15:02:44 +0000109 if (error.Success()) {
Cameron Desrochers89386da2019-10-09 18:27:33 +0000110 m_obj_obj = obj_obj->Clone(ConstString("object")).get();
Tamas Berghammerd161b212016-10-21 15:02:44 +0000111 }
112 }
113
114 return false;
115}
116
117bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; }
118
119lldb::ValueObjectSP
120LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
Cameron Desrochers745e57c2019-10-09 21:15:48 +0000121 if (idx == 0 && m_ptr_obj)
Cameron Desrochers89386da2019-10-09 18:27:33 +0000122 return m_ptr_obj->GetSP();
Cameron Desrochers745e57c2019-10-09 21:15:48 +0000123 if (idx == 1 && m_del_obj)
Cameron Desrochers89386da2019-10-09 18:27:33 +0000124 return m_del_obj->GetSP();
Cameron Desrochers745e57c2019-10-09 21:15:48 +0000125 if (idx == 2 && m_obj_obj)
Cameron Desrochers89386da2019-10-09 18:27:33 +0000126 return m_obj_obj->GetSP();
Tamas Berghammerd161b212016-10-21 15:02:44 +0000127 return lldb::ValueObjectSP();
128}
129
130size_t LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() {
131 if (m_del_obj)
132 return 2;
Tamas Berghammeraf8953a2017-03-31 20:07:20 +0000133 return 1;
Tamas Berghammerd161b212016-10-21 15:02:44 +0000134}
135
136size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName(
Adrian Prantl0e4c4822019-03-06 21:22:25 +0000137 ConstString name) {
Raphael Isemann05cfdb02019-04-26 07:21:36 +0000138 if (name == "ptr" || name == "pointer")
Tamas Berghammerd161b212016-10-21 15:02:44 +0000139 return 0;
Raphael Isemann05cfdb02019-04-26 07:21:36 +0000140 if (name == "del" || name == "deleter")
Tamas Berghammerd161b212016-10-21 15:02:44 +0000141 return 1;
Raphael Isemann05cfdb02019-04-26 07:21:36 +0000142 if (name == "obj" || name == "object" || name == "$$dereference$$")
Tamas Berghammerd161b212016-10-21 15:02:44 +0000143 return 2;
144 return UINT32_MAX;
145}
146
147bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary(
148 Stream &stream, const TypeSummaryOptions &options) {
149 if (!m_ptr_obj)
150 return false;
151
Pavel Labath833e3d12016-11-09 10:42:29 +0000152 bool success;
153 uint64_t ptr_value = m_ptr_obj->GetValueAsUnsigned(0, &success);
154 if (!success)
155 return false;
156 if (ptr_value == 0)
Tamas Berghammerd161b212016-10-21 15:02:44 +0000157 stream.Printf("nullptr");
Pavel Labath833e3d12016-11-09 10:42:29 +0000158 else
159 stream.Printf("0x%" PRIx64, ptr_value);
Tamas Berghammerd161b212016-10-21 15:02:44 +0000160 return true;
161}
162
163SyntheticChildrenFrontEnd *
164lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator(
165 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
166 return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp)
167 : nullptr);
168}
169
170bool lldb_private::formatters::LibStdcppUniquePointerSummaryProvider(
171 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
172 LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP());
173 return formatter.GetSummary(stream, options);
174}