180814287SRaphael Isemann //===-- LibCxx.cpp --------------------------------------------------------===//
233e97e63SEnrico Granata //
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
633e97e63SEnrico Granata //
733e97e63SEnrico Granata //===----------------------------------------------------------------------===//
833e97e63SEnrico Granata
933e97e63SEnrico Granata #include "LibCxx.h"
1033e97e63SEnrico Granata
1133e97e63SEnrico Granata #include "lldb/Core/Debugger.h"
1233e97e63SEnrico Granata #include "lldb/Core/FormatEntity.h"
1333e97e63SEnrico Granata #include "lldb/Core/ValueObject.h"
1433e97e63SEnrico Granata #include "lldb/Core/ValueObjectConstResult.h"
1533e97e63SEnrico Granata #include "lldb/DataFormatters/FormattersHelpers.h"
1633e97e63SEnrico Granata #include "lldb/DataFormatters/StringPrinter.h"
1733e97e63SEnrico Granata #include "lldb/DataFormatters/TypeSummary.h"
1833e97e63SEnrico Granata #include "lldb/DataFormatters/VectorIterator.h"
1901c3243fSZachary Turner #include "lldb/Target/ProcessStructReader.h"
206b58fa71SAdrian Prantl #include "lldb/Target/SectionLoadList.h"
2133e97e63SEnrico Granata #include "lldb/Target/Target.h"
227244e9c2SBen Jackson #include "lldb/Utility/ConstString.h"
23666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h"
2401c3243fSZachary Turner #include "lldb/Utility/Endian.h"
2597206d57SZachary Turner #include "lldb/Utility/Status.h"
26bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
2733e97e63SEnrico Granata
28e0678ca5SAlex Langford #include "Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h"
298be30215SAlex Langford #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
30d1e9d0b2SMichael Buch #include "lldb/lldb-enumerations.h"
317244e9c2SBen Jackson #include <tuple>
32e0678ca5SAlex Langford
3333e97e63SEnrico Granata using namespace lldb;
3433e97e63SEnrico Granata using namespace lldb_private;
3533e97e63SEnrico Granata using namespace lldb_private::formatters;
3633e97e63SEnrico Granata
LibcxxOptionalSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & options)37c53d3684SAdrian Prantl bool lldb_private::formatters::LibcxxOptionalSummaryProvider(
38c53d3684SAdrian Prantl ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
39c53d3684SAdrian Prantl ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
40c53d3684SAdrian Prantl if (!valobj_sp)
41c53d3684SAdrian Prantl return false;
42c53d3684SAdrian Prantl
43c53d3684SAdrian Prantl // An optional either contains a value or not, the member __engaged_ is
44c53d3684SAdrian Prantl // a bool flag, it is true if the optional has a value and false otherwise.
45c53d3684SAdrian Prantl ValueObjectSP engaged_sp(
46c53d3684SAdrian Prantl valobj_sp->GetChildMemberWithName(ConstString("__engaged_"), true));
47c53d3684SAdrian Prantl
48c53d3684SAdrian Prantl if (!engaged_sp)
49c53d3684SAdrian Prantl return false;
50c53d3684SAdrian Prantl
51c53d3684SAdrian Prantl llvm::StringRef engaged_as_cstring(
52c53d3684SAdrian Prantl engaged_sp->GetValueAsUnsigned(0) == 1 ? "true" : "false");
53c53d3684SAdrian Prantl
54c53d3684SAdrian Prantl stream.Printf(" Has Value=%s ", engaged_as_cstring.data());
55c53d3684SAdrian Prantl
56c53d3684SAdrian Prantl return true;
57c53d3684SAdrian Prantl }
58c53d3684SAdrian Prantl
LibcxxFunctionSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & options)596b58fa71SAdrian Prantl bool lldb_private::formatters::LibcxxFunctionSummaryProvider(
606b58fa71SAdrian Prantl ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
616b58fa71SAdrian Prantl
626b58fa71SAdrian Prantl ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
636b58fa71SAdrian Prantl
646b58fa71SAdrian Prantl if (!valobj_sp)
656b58fa71SAdrian Prantl return false;
666b58fa71SAdrian Prantl
676b58fa71SAdrian Prantl ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
686b58fa71SAdrian Prantl Process *process = exe_ctx.GetProcessPtr();
696b58fa71SAdrian Prantl
706b58fa71SAdrian Prantl if (process == nullptr)
716b58fa71SAdrian Prantl return false;
726b58fa71SAdrian Prantl
7345e78773SAlex Langford CPPLanguageRuntime *cpp_runtime = CPPLanguageRuntime::Get(*process);
746b58fa71SAdrian Prantl
75443e20baSShafik Yaghmour if (!cpp_runtime)
766b58fa71SAdrian Prantl return false;
776b58fa71SAdrian Prantl
78443e20baSShafik Yaghmour CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info =
79443e20baSShafik Yaghmour cpp_runtime->FindLibCppStdFunctionCallableInfo(valobj_sp);
806b58fa71SAdrian Prantl
81443e20baSShafik Yaghmour switch (callable_info.callable_case) {
82443e20baSShafik Yaghmour case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Invalid:
8380a11e08SShafik Yaghmour stream.Printf(" __f_ = %" PRIu64, callable_info.member_f_pointer_value);
846b58fa71SAdrian Prantl return false;
85443e20baSShafik Yaghmour break;
86443e20baSShafik Yaghmour case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Lambda:
87443e20baSShafik Yaghmour stream.Printf(
88443e20baSShafik Yaghmour " Lambda in File %s at Line %u",
89443e20baSShafik Yaghmour callable_info.callable_line_entry.file.GetFilename().GetCString(),
90443e20baSShafik Yaghmour callable_info.callable_line_entry.line);
91443e20baSShafik Yaghmour break;
92443e20baSShafik Yaghmour case CPPLanguageRuntime::LibCppStdFunctionCallableCase::CallableObject:
93443e20baSShafik Yaghmour stream.Printf(
94443e20baSShafik Yaghmour " Function in File %s at Line %u",
95443e20baSShafik Yaghmour callable_info.callable_line_entry.file.GetFilename().GetCString(),
96443e20baSShafik Yaghmour callable_info.callable_line_entry.line);
97443e20baSShafik Yaghmour break;
98443e20baSShafik Yaghmour case CPPLanguageRuntime::LibCppStdFunctionCallableCase::FreeOrMemberFunction:
99443e20baSShafik Yaghmour stream.Printf(" Function = %s ",
100443e20baSShafik Yaghmour callable_info.callable_symbol.GetName().GetCString());
101443e20baSShafik Yaghmour break;
1026b58fa71SAdrian Prantl }
1036b58fa71SAdrian Prantl
1046b58fa71SAdrian Prantl return true;
1056b58fa71SAdrian Prantl }
1066b58fa71SAdrian Prantl
LibcxxSmartPointerSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & options)107b9c1b51eSKate Stone bool lldb_private::formatters::LibcxxSmartPointerSummaryProvider(
108b9c1b51eSKate Stone ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
10933e97e63SEnrico Granata ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
11033e97e63SEnrico Granata if (!valobj_sp)
11133e97e63SEnrico Granata return false;
112b9c1b51eSKate Stone ValueObjectSP ptr_sp(
113b9c1b51eSKate Stone valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true));
114b9c1b51eSKate Stone ValueObjectSP count_sp(valobj_sp->GetChildAtNamePath(
115b9c1b51eSKate Stone {ConstString("__cntrl_"), ConstString("__shared_owners_")}));
116b9c1b51eSKate Stone ValueObjectSP weakcount_sp(valobj_sp->GetChildAtNamePath(
117b9c1b51eSKate Stone {ConstString("__cntrl_"), ConstString("__shared_weak_owners_")}));
11833e97e63SEnrico Granata
11933e97e63SEnrico Granata if (!ptr_sp)
12033e97e63SEnrico Granata return false;
12133e97e63SEnrico Granata
122b9c1b51eSKate Stone if (ptr_sp->GetValueAsUnsigned(0) == 0) {
12333e97e63SEnrico Granata stream.Printf("nullptr");
12433e97e63SEnrico Granata return true;
125b9c1b51eSKate Stone } else {
12633e97e63SEnrico Granata bool print_pointee = false;
12797206d57SZachary Turner Status error;
12833e97e63SEnrico Granata ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
129b9c1b51eSKate Stone if (pointee_sp && error.Success()) {
130b9c1b51eSKate Stone if (pointee_sp->DumpPrintableRepresentation(
131b9c1b51eSKate Stone stream, ValueObject::eValueObjectRepresentationStyleSummary,
13233e97e63SEnrico Granata lldb::eFormatInvalid,
13365d86e4fSEnrico Granata ValueObject::PrintableRepresentationSpecialCases::eDisable,
13465d86e4fSEnrico Granata false))
13533e97e63SEnrico Granata print_pointee = true;
13633e97e63SEnrico Granata }
13733e97e63SEnrico Granata if (!print_pointee)
13833e97e63SEnrico Granata stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
13933e97e63SEnrico Granata }
14033e97e63SEnrico Granata
14133e97e63SEnrico Granata if (count_sp)
14233e97e63SEnrico Granata stream.Printf(" strong=%" PRIu64, 1 + count_sp->GetValueAsUnsigned(0));
14333e97e63SEnrico Granata
14433e97e63SEnrico Granata if (weakcount_sp)
14533e97e63SEnrico Granata stream.Printf(" weak=%" PRIu64, 1 + weakcount_sp->GetValueAsUnsigned(0));
14633e97e63SEnrico Granata
14733e97e63SEnrico Granata return true;
14833e97e63SEnrico Granata }
14933e97e63SEnrico Granata
LibcxxUniquePointerSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & options)150a567d680Sshafik bool lldb_private::formatters::LibcxxUniquePointerSummaryProvider(
151a567d680Sshafik ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
152a567d680Sshafik ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
153a567d680Sshafik if (!valobj_sp)
154a567d680Sshafik return false;
155a567d680Sshafik
156a567d680Sshafik ValueObjectSP ptr_sp(
157a567d680Sshafik valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true));
158a567d680Sshafik if (!ptr_sp)
159a567d680Sshafik return false;
160a567d680Sshafik
161a567d680Sshafik ptr_sp = GetValueOfLibCXXCompressedPair(*ptr_sp);
162a567d680Sshafik if (!ptr_sp)
163a567d680Sshafik return false;
164a567d680Sshafik
165a567d680Sshafik if (ptr_sp->GetValueAsUnsigned(0) == 0) {
166a567d680Sshafik stream.Printf("nullptr");
167a567d680Sshafik return true;
168a567d680Sshafik } else {
169a567d680Sshafik bool print_pointee = false;
170a567d680Sshafik Status error;
171a567d680Sshafik ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
172a567d680Sshafik if (pointee_sp && error.Success()) {
173a567d680Sshafik if (pointee_sp->DumpPrintableRepresentation(
174a567d680Sshafik stream, ValueObject::eValueObjectRepresentationStyleSummary,
175a567d680Sshafik lldb::eFormatInvalid,
176a567d680Sshafik ValueObject::PrintableRepresentationSpecialCases::eDisable,
177a567d680Sshafik false))
178a567d680Sshafik print_pointee = true;
179a567d680Sshafik }
180a567d680Sshafik if (!print_pointee)
181a567d680Sshafik stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
182a567d680Sshafik }
183a567d680Sshafik
184a567d680Sshafik return true;
185a567d680Sshafik }
186a567d680Sshafik
18733e97e63SEnrico Granata /*
18833e97e63SEnrico Granata (lldb) fr var ibeg --raw --ptr-depth 1
189b9c1b51eSKate Stone (std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int,
190b9c1b51eSKate Stone std::__1::basic_string<char, std::__1::char_traits<char>,
191b9c1b51eSKate Stone std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::pair<int,
192b9c1b51eSKate Stone std::__1::basic_string<char, std::__1::char_traits<char>,
193b9c1b51eSKate Stone std::__1::allocator<char> > >, void *> *, long> >) ibeg = {
19433e97e63SEnrico Granata __i_ = {
19533e97e63SEnrico Granata __ptr_ = 0x0000000100103870 {
19633e97e63SEnrico Granata std::__1::__tree_node_base<void *> = {
19733e97e63SEnrico Granata std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = {
19833e97e63SEnrico Granata __left_ = 0x0000000000000000
19933e97e63SEnrico Granata }
20033e97e63SEnrico Granata __right_ = 0x0000000000000000
20133e97e63SEnrico Granata __parent_ = 0x00000001001038b0
20233e97e63SEnrico Granata __is_black_ = true
20333e97e63SEnrico Granata }
20433e97e63SEnrico Granata __value_ = {
20533e97e63SEnrico Granata first = 0
20633e97e63SEnrico Granata second = { std::string }
20733e97e63SEnrico Granata */
20833e97e63SEnrico Granata
209b9c1b51eSKate Stone lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
LibCxxMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)210b9c1b51eSKate Stone LibCxxMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
211ae1ba73aSEnrico Granata : SyntheticChildrenFrontEnd(*valobj_sp), m_pair_ptr(), m_pair_sp() {
21233e97e63SEnrico Granata if (valobj_sp)
21333e97e63SEnrico Granata Update();
21433e97e63SEnrico Granata }
21533e97e63SEnrico Granata
Update()216b9c1b51eSKate Stone bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() {
217ae1ba73aSEnrico Granata m_pair_sp.reset();
218ae1ba73aSEnrico Granata m_pair_ptr = nullptr;
219ae1ba73aSEnrico Granata
22033e97e63SEnrico Granata ValueObjectSP valobj_sp = m_backend.GetSP();
22133e97e63SEnrico Granata if (!valobj_sp)
22233e97e63SEnrico Granata return false;
22333e97e63SEnrico Granata
22433e97e63SEnrico Granata TargetSP target_sp(valobj_sp->GetTargetSP());
22533e97e63SEnrico Granata
22633e97e63SEnrico Granata if (!target_sp)
22733e97e63SEnrico Granata return false;
22833e97e63SEnrico Granata
22933e97e63SEnrico Granata if (!valobj_sp)
23033e97e63SEnrico Granata return false;
23133e97e63SEnrico Granata
23280a11e08SShafik Yaghmour static ConstString g_i_("__i_");
233ae1ba73aSEnrico Granata
23405097246SAdrian Prantl // this must be a ValueObject* because it is a child of the ValueObject we
23505097246SAdrian Prantl // are producing children for it if were a ValueObjectSP, we would end up
23605097246SAdrian Prantl // with a loop (iterator -> synthetic -> child -> parent == iterator) and
23705097246SAdrian Prantl // that would in turn leak memory by never allowing the ValueObjects to die
23805097246SAdrian Prantl // and free their memory
239b9c1b51eSKate Stone m_pair_ptr = valobj_sp
240b9c1b51eSKate Stone ->GetValueForExpressionPath(
241d2daca77SZachary Turner ".__i_.__ptr_->__value_", nullptr, nullptr,
242b9c1b51eSKate Stone ValueObject::GetValueForExpressionPathOptions()
243b9c1b51eSKate Stone .DontCheckDotVsArrowSyntax()
244b9c1b51eSKate Stone .SetSyntheticChildrenTraversal(
245b9c1b51eSKate Stone ValueObject::GetValueForExpressionPathOptions::
246b9c1b51eSKate Stone SyntheticChildrenTraversal::None),
247b9c1b51eSKate Stone nullptr)
248b9c1b51eSKate Stone .get();
24933e97e63SEnrico Granata
250ae1ba73aSEnrico Granata if (!m_pair_ptr) {
251d2daca77SZachary Turner m_pair_ptr = valobj_sp
252d2daca77SZachary Turner ->GetValueForExpressionPath(
253d2daca77SZachary Turner ".__i_.__ptr_", nullptr, nullptr,
254ae1ba73aSEnrico Granata ValueObject::GetValueForExpressionPathOptions()
255ae1ba73aSEnrico Granata .DontCheckDotVsArrowSyntax()
256ae1ba73aSEnrico Granata .SetSyntheticChildrenTraversal(
257ae1ba73aSEnrico Granata ValueObject::GetValueForExpressionPathOptions::
258ae1ba73aSEnrico Granata SyntheticChildrenTraversal::None),
259ae1ba73aSEnrico Granata nullptr)
260ae1ba73aSEnrico Granata .get();
261ae1ba73aSEnrico Granata if (m_pair_ptr) {
26280a11e08SShafik Yaghmour auto __i_(valobj_sp->GetChildMemberWithName(g_i_, true));
263ae1ba73aSEnrico Granata if (!__i_) {
264ae1ba73aSEnrico Granata m_pair_ptr = nullptr;
265ae1ba73aSEnrico Granata return false;
266ae1ba73aSEnrico Granata }
267d963a7c3SAdrian Prantl CompilerType pair_type(
268d963a7c3SAdrian Prantl __i_->GetCompilerType().GetTypeTemplateArgument(0));
269d963a7c3SAdrian Prantl std::string name;
270d963a7c3SAdrian Prantl uint64_t bit_offset_ptr;
271d963a7c3SAdrian Prantl uint32_t bitfield_bit_size_ptr;
272d963a7c3SAdrian Prantl bool is_bitfield_ptr;
273d963a7c3SAdrian Prantl pair_type = pair_type.GetFieldAtIndex(
274d963a7c3SAdrian Prantl 0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
275ae1ba73aSEnrico Granata if (!pair_type) {
276ae1ba73aSEnrico Granata m_pair_ptr = nullptr;
277ae1ba73aSEnrico Granata return false;
278ae1ba73aSEnrico Granata }
279ae1ba73aSEnrico Granata
280ae1ba73aSEnrico Granata auto addr(m_pair_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS));
281ae1ba73aSEnrico Granata m_pair_ptr = nullptr;
282ae1ba73aSEnrico Granata if (addr && addr != LLDB_INVALID_ADDRESS) {
2836e3b0cc2SRaphael Isemann TypeSystemClang *ast_ctx =
2846e3b0cc2SRaphael Isemann llvm::dyn_cast_or_null<TypeSystemClang>(pair_type.GetTypeSystem());
285ae1ba73aSEnrico Granata if (!ast_ctx)
286ae1ba73aSEnrico Granata return false;
287d1e9d0b2SMichael Buch
288d1e9d0b2SMichael Buch // Mimick layout of std::__tree_iterator::__ptr_ and read it in
289d1e9d0b2SMichael Buch // from process memory.
290d1e9d0b2SMichael Buch //
291d1e9d0b2SMichael Buch // The following shows the contiguous block of memory:
292d1e9d0b2SMichael Buch //
293d1e9d0b2SMichael Buch // +-----------------------------+ class __tree_end_node
294d1e9d0b2SMichael Buch // __ptr_ | pointer __left_; |
295d1e9d0b2SMichael Buch // +-----------------------------+ class __tree_node_base
296d1e9d0b2SMichael Buch // | pointer __right_; |
297d1e9d0b2SMichael Buch // | __parent_pointer __parent_; |
298d1e9d0b2SMichael Buch // | bool __is_black_; |
299d1e9d0b2SMichael Buch // +-----------------------------+ class __tree_node
300d1e9d0b2SMichael Buch // | __node_value_type __value_; | <<< our key/value pair
301d1e9d0b2SMichael Buch // +-----------------------------+
302d1e9d0b2SMichael Buch //
303d963a7c3SAdrian Prantl CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(
304d963a7c3SAdrian Prantl ConstString(),
305d963a7c3SAdrian Prantl {{"ptr0",
306d963a7c3SAdrian Prantl ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
307d963a7c3SAdrian Prantl {"ptr1",
308d963a7c3SAdrian Prantl ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
309d963a7c3SAdrian Prantl {"ptr2",
310d963a7c3SAdrian Prantl ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
311ae1ba73aSEnrico Granata {"cw", ast_ctx->GetBasicType(lldb::eBasicTypeBool)},
312d963a7c3SAdrian Prantl {"payload", pair_type}});
313d6a9bbf6SAdrian Prantl llvm::Optional<uint64_t> size = tree_node_type.GetByteSize(nullptr);
314d963a7c3SAdrian Prantl if (!size)
315d963a7c3SAdrian Prantl return false;
316fc54427eSJonas Devlieghere WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
317ae1ba73aSEnrico Granata ProcessSP process_sp(target_sp->GetProcessSP());
31897206d57SZachary Turner Status error;
319d963a7c3SAdrian Prantl process_sp->ReadMemory(addr, buffer_sp->GetBytes(),
320d963a7c3SAdrian Prantl buffer_sp->GetByteSize(), error);
321ae1ba73aSEnrico Granata if (error.Fail())
322ae1ba73aSEnrico Granata return false;
323d963a7c3SAdrian Prantl DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(),
324d963a7c3SAdrian Prantl process_sp->GetAddressByteSize());
325d963a7c3SAdrian Prantl auto pair_sp = CreateValueObjectFromData(
326d963a7c3SAdrian Prantl "pair", extractor, valobj_sp->GetExecutionContextRef(),
327d963a7c3SAdrian Prantl tree_node_type);
328ae1ba73aSEnrico Granata if (pair_sp)
329ae1ba73aSEnrico Granata m_pair_sp = pair_sp->GetChildAtIndex(4, true);
330ae1ba73aSEnrico Granata }
331ae1ba73aSEnrico Granata }
332ae1ba73aSEnrico Granata }
333ae1ba73aSEnrico Granata
33433e97e63SEnrico Granata return false;
33533e97e63SEnrico Granata }
33633e97e63SEnrico Granata
337b9c1b51eSKate Stone size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
CalculateNumChildren()338b9c1b51eSKate Stone CalculateNumChildren() {
33933e97e63SEnrico Granata return 2;
34033e97e63SEnrico Granata }
34133e97e63SEnrico Granata
34233e97e63SEnrico Granata lldb::ValueObjectSP
GetChildAtIndex(size_t idx)343b9c1b51eSKate Stone lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex(
344b9c1b51eSKate Stone size_t idx) {
345ae1ba73aSEnrico Granata if (m_pair_ptr)
34633e97e63SEnrico Granata return m_pair_ptr->GetChildAtIndex(idx, true);
347ae1ba73aSEnrico Granata if (m_pair_sp)
348ae1ba73aSEnrico Granata return m_pair_sp->GetChildAtIndex(idx, true);
349ae1ba73aSEnrico Granata return lldb::ValueObjectSP();
35033e97e63SEnrico Granata }
35133e97e63SEnrico Granata
352b9c1b51eSKate Stone bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
MightHaveChildren()353b9c1b51eSKate Stone MightHaveChildren() {
35433e97e63SEnrico Granata return true;
35533e97e63SEnrico Granata }
35633e97e63SEnrico Granata
357b9c1b51eSKate Stone size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
GetIndexOfChildWithName(ConstString name)3580e4c4821SAdrian Prantl GetIndexOfChildWithName(ConstString name) {
35905cfdb0eSRaphael Isemann if (name == "first")
36033e97e63SEnrico Granata return 0;
36105cfdb0eSRaphael Isemann if (name == "second")
36233e97e63SEnrico Granata return 1;
36333e97e63SEnrico Granata return UINT32_MAX;
36433e97e63SEnrico Granata }
36533e97e63SEnrico Granata
366b9c1b51eSKate Stone lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
~LibCxxMapIteratorSyntheticFrontEnd()367b9c1b51eSKate Stone ~LibCxxMapIteratorSyntheticFrontEnd() {
36833e97e63SEnrico Granata // this will be deleted when its parent dies (since it's a child object)
36933e97e63SEnrico Granata // delete m_pair_ptr;
37033e97e63SEnrico Granata }
37133e97e63SEnrico Granata
37233e97e63SEnrico Granata SyntheticChildrenFrontEnd *
LibCxxMapIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)373b9c1b51eSKate Stone lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator(
374b9c1b51eSKate Stone CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
375b9c1b51eSKate Stone return (valobj_sp ? new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp)
376b9c1b51eSKate Stone : nullptr);
37733e97e63SEnrico Granata }
37833e97e63SEnrico Granata
379d1e9d0b2SMichael Buch lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
LibCxxUnorderedMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)380d1e9d0b2SMichael Buch LibCxxUnorderedMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
381d1e9d0b2SMichael Buch : SyntheticChildrenFrontEnd(*valobj_sp) {
382d1e9d0b2SMichael Buch if (valobj_sp)
383d1e9d0b2SMichael Buch Update();
384d1e9d0b2SMichael Buch }
385d1e9d0b2SMichael Buch
386d1e9d0b2SMichael Buch bool lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
Update()387d1e9d0b2SMichael Buch Update() {
388d1e9d0b2SMichael Buch m_pair_sp.reset();
389d1e9d0b2SMichael Buch m_iter_ptr = nullptr;
390d1e9d0b2SMichael Buch
391d1e9d0b2SMichael Buch ValueObjectSP valobj_sp = m_backend.GetSP();
392d1e9d0b2SMichael Buch if (!valobj_sp)
393d1e9d0b2SMichael Buch return false;
394d1e9d0b2SMichael Buch
395d1e9d0b2SMichael Buch TargetSP target_sp(valobj_sp->GetTargetSP());
396d1e9d0b2SMichael Buch
397d1e9d0b2SMichael Buch if (!target_sp)
398d1e9d0b2SMichael Buch return false;
399d1e9d0b2SMichael Buch
400d1e9d0b2SMichael Buch if (!valobj_sp)
401d1e9d0b2SMichael Buch return false;
402d1e9d0b2SMichael Buch
403d1e9d0b2SMichael Buch auto exprPathOptions = ValueObject::GetValueForExpressionPathOptions()
404d1e9d0b2SMichael Buch .DontCheckDotVsArrowSyntax()
405d1e9d0b2SMichael Buch .SetSyntheticChildrenTraversal(
406d1e9d0b2SMichael Buch ValueObject::GetValueForExpressionPathOptions::
407d1e9d0b2SMichael Buch SyntheticChildrenTraversal::None);
408d1e9d0b2SMichael Buch
409d1e9d0b2SMichael Buch // This must be a ValueObject* because it is a child of the ValueObject we
410d1e9d0b2SMichael Buch // are producing children for it if were a ValueObjectSP, we would end up
411d1e9d0b2SMichael Buch // with a loop (iterator -> synthetic -> child -> parent == iterator) and
412d1e9d0b2SMichael Buch // that would in turn leak memory by never allowing the ValueObjects to die
413d1e9d0b2SMichael Buch // and free their memory.
414d1e9d0b2SMichael Buch m_iter_ptr =
415d1e9d0b2SMichael Buch valobj_sp
416d1e9d0b2SMichael Buch ->GetValueForExpressionPath(".__i_.__node_", nullptr, nullptr,
417d1e9d0b2SMichael Buch exprPathOptions, nullptr)
418d1e9d0b2SMichael Buch .get();
419d1e9d0b2SMichael Buch
420d1e9d0b2SMichael Buch if (m_iter_ptr) {
421d1e9d0b2SMichael Buch auto iter_child(
422d1e9d0b2SMichael Buch valobj_sp->GetChildMemberWithName(ConstString("__i_"), true));
423d1e9d0b2SMichael Buch if (!iter_child) {
424d1e9d0b2SMichael Buch m_iter_ptr = nullptr;
425d1e9d0b2SMichael Buch return false;
426d1e9d0b2SMichael Buch }
427d1e9d0b2SMichael Buch
428d1e9d0b2SMichael Buch CompilerType node_type(iter_child->GetCompilerType()
429d1e9d0b2SMichael Buch .GetTypeTemplateArgument(0)
430d1e9d0b2SMichael Buch .GetPointeeType());
431d1e9d0b2SMichael Buch
432d1e9d0b2SMichael Buch CompilerType pair_type(node_type.GetTypeTemplateArgument(0));
433d1e9d0b2SMichael Buch
434d1e9d0b2SMichael Buch std::string name;
435d1e9d0b2SMichael Buch uint64_t bit_offset_ptr;
436d1e9d0b2SMichael Buch uint32_t bitfield_bit_size_ptr;
437d1e9d0b2SMichael Buch bool is_bitfield_ptr;
438d1e9d0b2SMichael Buch
439d1e9d0b2SMichael Buch pair_type = pair_type.GetFieldAtIndex(
440d1e9d0b2SMichael Buch 0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
441d1e9d0b2SMichael Buch if (!pair_type) {
442d1e9d0b2SMichael Buch m_iter_ptr = nullptr;
443d1e9d0b2SMichael Buch return false;
444d1e9d0b2SMichael Buch }
445d1e9d0b2SMichael Buch
446d1e9d0b2SMichael Buch uint64_t addr = m_iter_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
447d1e9d0b2SMichael Buch m_iter_ptr = nullptr;
448d1e9d0b2SMichael Buch
449d1e9d0b2SMichael Buch if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
450d1e9d0b2SMichael Buch return false;
451d1e9d0b2SMichael Buch
452d1e9d0b2SMichael Buch TypeSystemClang *ast_ctx =
453d1e9d0b2SMichael Buch llvm::dyn_cast_or_null<TypeSystemClang>(pair_type.GetTypeSystem());
454d1e9d0b2SMichael Buch if (!ast_ctx)
455d1e9d0b2SMichael Buch return false;
456d1e9d0b2SMichael Buch
457d1e9d0b2SMichael Buch // Mimick layout of std::__hash_iterator::__node_ and read it in
458d1e9d0b2SMichael Buch // from process memory.
459d1e9d0b2SMichael Buch //
460d1e9d0b2SMichael Buch // The following shows the contiguous block of memory:
461d1e9d0b2SMichael Buch //
462d1e9d0b2SMichael Buch // +-----------------------------+ class __hash_node_base
463d1e9d0b2SMichael Buch // __node_ | __next_pointer __next_; |
464d1e9d0b2SMichael Buch // +-----------------------------+ class __hash_node
465d1e9d0b2SMichael Buch // | size_t __hash_; |
466d1e9d0b2SMichael Buch // | __node_value_type __value_; | <<< our key/value pair
467d1e9d0b2SMichael Buch // +-----------------------------+
468d1e9d0b2SMichael Buch //
469d1e9d0b2SMichael Buch CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(
470d1e9d0b2SMichael Buch ConstString(),
471d1e9d0b2SMichael Buch {{"__next_",
472d1e9d0b2SMichael Buch ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
473d1e9d0b2SMichael Buch {"__hash_", ast_ctx->GetBasicType(lldb::eBasicTypeUnsignedLongLong)},
474d1e9d0b2SMichael Buch {"__value_", pair_type}});
475d1e9d0b2SMichael Buch llvm::Optional<uint64_t> size = tree_node_type.GetByteSize(nullptr);
476d1e9d0b2SMichael Buch if (!size)
477d1e9d0b2SMichael Buch return false;
478d1e9d0b2SMichael Buch WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
479d1e9d0b2SMichael Buch ProcessSP process_sp(target_sp->GetProcessSP());
480d1e9d0b2SMichael Buch Status error;
481d1e9d0b2SMichael Buch process_sp->ReadMemory(addr, buffer_sp->GetBytes(),
482d1e9d0b2SMichael Buch buffer_sp->GetByteSize(), error);
483d1e9d0b2SMichael Buch if (error.Fail())
484d1e9d0b2SMichael Buch return false;
485d1e9d0b2SMichael Buch DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(),
486d1e9d0b2SMichael Buch process_sp->GetAddressByteSize());
487d1e9d0b2SMichael Buch auto pair_sp = CreateValueObjectFromData(
488d1e9d0b2SMichael Buch "pair", extractor, valobj_sp->GetExecutionContextRef(), tree_node_type);
489d1e9d0b2SMichael Buch if (pair_sp)
490d1e9d0b2SMichael Buch m_pair_sp = pair_sp->GetChildAtIndex(2, true);
491d1e9d0b2SMichael Buch }
492d1e9d0b2SMichael Buch
493d1e9d0b2SMichael Buch return false;
494d1e9d0b2SMichael Buch }
495d1e9d0b2SMichael Buch
496d1e9d0b2SMichael Buch size_t lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
CalculateNumChildren()497d1e9d0b2SMichael Buch CalculateNumChildren() {
498d1e9d0b2SMichael Buch return 2;
499d1e9d0b2SMichael Buch }
500d1e9d0b2SMichael Buch
501d1e9d0b2SMichael Buch lldb::ValueObjectSP lldb_private::formatters::
GetChildAtIndex(size_t idx)502d1e9d0b2SMichael Buch LibCxxUnorderedMapIteratorSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
503d1e9d0b2SMichael Buch if (m_pair_sp)
504d1e9d0b2SMichael Buch return m_pair_sp->GetChildAtIndex(idx, true);
505d1e9d0b2SMichael Buch return lldb::ValueObjectSP();
506d1e9d0b2SMichael Buch }
507d1e9d0b2SMichael Buch
508d1e9d0b2SMichael Buch bool lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
MightHaveChildren()509d1e9d0b2SMichael Buch MightHaveChildren() {
510d1e9d0b2SMichael Buch return true;
511d1e9d0b2SMichael Buch }
512d1e9d0b2SMichael Buch
513d1e9d0b2SMichael Buch size_t lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
GetIndexOfChildWithName(ConstString name)514d1e9d0b2SMichael Buch GetIndexOfChildWithName(ConstString name) {
515d1e9d0b2SMichael Buch if (name == "first")
516d1e9d0b2SMichael Buch return 0;
517d1e9d0b2SMichael Buch if (name == "second")
518d1e9d0b2SMichael Buch return 1;
519d1e9d0b2SMichael Buch return UINT32_MAX;
520d1e9d0b2SMichael Buch }
521d1e9d0b2SMichael Buch
522d1e9d0b2SMichael Buch SyntheticChildrenFrontEnd *
LibCxxUnorderedMapIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)523d1e9d0b2SMichael Buch lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEndCreator(
524d1e9d0b2SMichael Buch CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
525d1e9d0b2SMichael Buch return (valobj_sp ? new LibCxxUnorderedMapIteratorSyntheticFrontEnd(valobj_sp)
526d1e9d0b2SMichael Buch : nullptr);
527d1e9d0b2SMichael Buch }
528d1e9d0b2SMichael Buch
52933e97e63SEnrico Granata /*
53033e97e63SEnrico Granata (lldb) fr var ibeg --raw --ptr-depth 1 -T
53133e97e63SEnrico Granata (std::__1::__wrap_iter<int *>) ibeg = {
53233e97e63SEnrico Granata (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
53333e97e63SEnrico Granata (int) *__i = 1
53433e97e63SEnrico Granata }
53533e97e63SEnrico Granata }
53633e97e63SEnrico Granata */
53733e97e63SEnrico Granata
53833e97e63SEnrico Granata SyntheticChildrenFrontEnd *
LibCxxVectorIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)539b9c1b51eSKate Stone lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator(
540b9c1b51eSKate Stone CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
54133e97e63SEnrico Granata static ConstString g_item_name;
54233e97e63SEnrico Granata if (!g_item_name)
54333e97e63SEnrico Granata g_item_name.SetCString("__i");
544b9c1b51eSKate Stone return (valobj_sp
545b9c1b51eSKate Stone ? new VectorIteratorSyntheticFrontEnd(valobj_sp, g_item_name)
546b9c1b51eSKate Stone : nullptr);
54733e97e63SEnrico Granata }
54833e97e63SEnrico Granata
549b9c1b51eSKate Stone lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)550b9c1b51eSKate Stone LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
5510ac42fd2SDave Lee : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr) {
55233e97e63SEnrico Granata if (valobj_sp)
55333e97e63SEnrico Granata Update();
55433e97e63SEnrico Granata }
55533e97e63SEnrico Granata
556b9c1b51eSKate Stone size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
CalculateNumChildren()557b9c1b51eSKate Stone CalculateNumChildren() {
55833e97e63SEnrico Granata return (m_cntrl ? 1 : 0);
55933e97e63SEnrico Granata }
56033e97e63SEnrico Granata
56133e97e63SEnrico Granata lldb::ValueObjectSP
GetChildAtIndex(size_t idx)562b9c1b51eSKate Stone lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
563b9c1b51eSKate Stone size_t idx) {
56433e97e63SEnrico Granata if (!m_cntrl)
56533e97e63SEnrico Granata return lldb::ValueObjectSP();
56633e97e63SEnrico Granata
56733e97e63SEnrico Granata ValueObjectSP valobj_sp = m_backend.GetSP();
56833e97e63SEnrico Granata if (!valobj_sp)
56933e97e63SEnrico Granata return lldb::ValueObjectSP();
57033e97e63SEnrico Granata
57133e97e63SEnrico Granata if (idx == 0)
57233e97e63SEnrico Granata return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true);
57333e97e63SEnrico Granata
574b9c1b51eSKate Stone if (idx == 1) {
5750ac42fd2SDave Lee if (auto ptr_sp =
5760ac42fd2SDave Lee valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true)) {
5770ac42fd2SDave Lee Status status;
5780ac42fd2SDave Lee auto value_sp = ptr_sp->Dereference(status);
5790ac42fd2SDave Lee if (status.Success()) {
5800ac42fd2SDave Lee auto value_type_sp =
5810ac42fd2SDave Lee valobj_sp->GetCompilerType().GetTypeTemplateArgument(0);
5820ac42fd2SDave Lee return value_sp->Cast(value_type_sp);
5830ac42fd2SDave Lee }
5840ac42fd2SDave Lee }
5850ac42fd2SDave Lee }
5860ac42fd2SDave Lee
58733e97e63SEnrico Granata return lldb::ValueObjectSP();
58833e97e63SEnrico Granata }
58933e97e63SEnrico Granata
Update()590b9c1b51eSKate Stone bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
591bbd16815SEugene Zelenko m_cntrl = nullptr;
59233e97e63SEnrico Granata
59333e97e63SEnrico Granata ValueObjectSP valobj_sp = m_backend.GetSP();
59433e97e63SEnrico Granata if (!valobj_sp)
59533e97e63SEnrico Granata return false;
59633e97e63SEnrico Granata
59733e97e63SEnrico Granata TargetSP target_sp(valobj_sp->GetTargetSP());
59833e97e63SEnrico Granata if (!target_sp)
59933e97e63SEnrico Granata return false;
60033e97e63SEnrico Granata
601b9c1b51eSKate Stone lldb::ValueObjectSP cntrl_sp(
602b9c1b51eSKate Stone valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"), true));
60333e97e63SEnrico Granata
604b9c1b51eSKate Stone m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular
605b9c1b51eSKate Stone // dependency
60633e97e63SEnrico Granata return false;
60733e97e63SEnrico Granata }
60833e97e63SEnrico Granata
609b9c1b51eSKate Stone bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
MightHaveChildren()610b9c1b51eSKate Stone MightHaveChildren() {
61133e97e63SEnrico Granata return true;
61233e97e63SEnrico Granata }
61333e97e63SEnrico Granata
614b9c1b51eSKate Stone size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
GetIndexOfChildWithName(ConstString name)6150e4c4821SAdrian Prantl GetIndexOfChildWithName(ConstString name) {
61605cfdb0eSRaphael Isemann if (name == "__ptr_")
61733e97e63SEnrico Granata return 0;
6180ac42fd2SDave Lee if (name == "$$dereference$$")
61933e97e63SEnrico Granata return 1;
62033e97e63SEnrico Granata return UINT32_MAX;
62133e97e63SEnrico Granata }
62233e97e63SEnrico Granata
623b9c1b51eSKate Stone lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
624b9c1b51eSKate Stone ~LibcxxSharedPtrSyntheticFrontEnd() = default;
62533e97e63SEnrico Granata
62633e97e63SEnrico Granata SyntheticChildrenFrontEnd *
LibcxxSharedPtrSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)627b9c1b51eSKate Stone lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator(
628b9c1b51eSKate Stone CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
629b9c1b51eSKate Stone return (valobj_sp ? new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)
630b9c1b51eSKate Stone : nullptr);
63133e97e63SEnrico Granata }
63233e97e63SEnrico Granata
633a567d680Sshafik lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)634a567d680Sshafik LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
6353a677b29SDave Lee : SyntheticChildrenFrontEnd(*valobj_sp) {
636a567d680Sshafik if (valobj_sp)
637a567d680Sshafik Update();
638a567d680Sshafik }
639a567d680Sshafik
640a567d680Sshafik lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
641a567d680Sshafik ~LibcxxUniquePtrSyntheticFrontEnd() = default;
642a567d680Sshafik
643a567d680Sshafik SyntheticChildrenFrontEnd *
LibcxxUniquePtrSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)644a567d680Sshafik lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEndCreator(
645a567d680Sshafik CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
646a567d680Sshafik return (valobj_sp ? new LibcxxUniquePtrSyntheticFrontEnd(valobj_sp)
647a567d680Sshafik : nullptr);
648a567d680Sshafik }
649a567d680Sshafik
650a567d680Sshafik size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
CalculateNumChildren()651a567d680Sshafik CalculateNumChildren() {
6523a677b29SDave Lee return (m_value_ptr_sp ? 1 : 0);
653a567d680Sshafik }
654a567d680Sshafik
655a567d680Sshafik lldb::ValueObjectSP
GetChildAtIndex(size_t idx)656a567d680Sshafik lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::GetChildAtIndex(
657a567d680Sshafik size_t idx) {
6583a677b29SDave Lee if (!m_value_ptr_sp)
659a567d680Sshafik return lldb::ValueObjectSP();
660a567d680Sshafik
6613a677b29SDave Lee if (idx == 0)
6623a677b29SDave Lee return m_value_ptr_sp;
663a567d680Sshafik
6643a677b29SDave Lee if (idx == 1) {
6653a677b29SDave Lee Status status;
6663a677b29SDave Lee auto value_sp = m_value_ptr_sp->Dereference(status);
6673a677b29SDave Lee if (status.Success()) {
6683a677b29SDave Lee return value_sp;
6693a677b29SDave Lee }
6703a677b29SDave Lee }
6713a677b29SDave Lee
6723a677b29SDave Lee return lldb::ValueObjectSP();
673a567d680Sshafik }
674a567d680Sshafik
Update()675a567d680Sshafik bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() {
676a567d680Sshafik ValueObjectSP valobj_sp = m_backend.GetSP();
677a567d680Sshafik if (!valobj_sp)
678a567d680Sshafik return false;
679a567d680Sshafik
680a567d680Sshafik ValueObjectSP ptr_sp(
681a567d680Sshafik valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true));
682a567d680Sshafik if (!ptr_sp)
683a567d680Sshafik return false;
684a567d680Sshafik
6853a677b29SDave Lee m_value_ptr_sp = GetValueOfLibCXXCompressedPair(*ptr_sp);
686a567d680Sshafik
687a567d680Sshafik return false;
688a567d680Sshafik }
689a567d680Sshafik
690a567d680Sshafik bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
MightHaveChildren()691a567d680Sshafik MightHaveChildren() {
692a567d680Sshafik return true;
693a567d680Sshafik }
694a567d680Sshafik
695a567d680Sshafik size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
GetIndexOfChildWithName(ConstString name)696a567d680Sshafik GetIndexOfChildWithName(ConstString name) {
697a567d680Sshafik if (name == "__value_")
698a567d680Sshafik return 0;
6993a677b29SDave Lee if (name == "$$dereference$$")
7003a677b29SDave Lee return 1;
701a567d680Sshafik return UINT32_MAX;
702a567d680Sshafik }
703a567d680Sshafik
LibcxxContainerSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & options)704b9c1b51eSKate Stone bool lldb_private::formatters::LibcxxContainerSummaryProvider(
705b9c1b51eSKate Stone ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
706b9c1b51eSKate Stone if (valobj.IsPointerType()) {
70733e97e63SEnrico Granata uint64_t value = valobj.GetValueAsUnsigned(0);
70833e97e63SEnrico Granata if (!value)
70933e97e63SEnrico Granata return false;
71033e97e63SEnrico Granata stream.Printf("0x%016" PRIx64 " ", value);
71133e97e63SEnrico Granata }
712b9c1b51eSKate Stone return FormatEntity::FormatStringRef("size=${svar%#}", stream, nullptr,
713b9c1b51eSKate Stone nullptr, nullptr, &valobj, false, false);
71433e97e63SEnrico Granata }
71533e97e63SEnrico Granata
716f4570ce4SAdrian Prantl /// The field layout in a libc++ string (cap, side, data or data, size, cap).
717d4381153SPavel Labath namespace {
718d4381153SPavel Labath enum class StringLayout { CSD, DSC };
719d4381153SPavel Labath }
72033e97e63SEnrico Granata
72190a94c02SVedant Kumar /// Determine the size in bytes of \p valobj (a libc++ std::string object) and
72290a94c02SVedant Kumar /// extract its data payload. Return the size + payload pair.
7231056c567SPavel Labath // TODO: Support big-endian architectures.
72490a94c02SVedant Kumar static llvm::Optional<std::pair<uint64_t, ValueObjectSP>>
ExtractLibcxxStringInfo(ValueObject & valobj)72590a94c02SVedant Kumar ExtractLibcxxStringInfo(ValueObject &valobj) {
726d4381153SPavel Labath ValueObjectSP valobj_r_sp =
727d4381153SPavel Labath valobj.GetChildMemberWithName(ConstString("__r_"), /*can_create=*/true);
728*a72306e2SPavel Labath if (!valobj_r_sp || !valobj_r_sp->GetError().Success())
72990a94c02SVedant Kumar return {};
73033e97e63SEnrico Granata
731d4381153SPavel Labath // __r_ is a compressed_pair of the actual data and the allocator. The data we
732d4381153SPavel Labath // want is in the first base class.
733d4381153SPavel Labath ValueObjectSP valobj_r_base_sp =
734d4381153SPavel Labath valobj_r_sp->GetChildAtIndex(0, /*can_create=*/true);
735d4381153SPavel Labath if (!valobj_r_base_sp)
73690a94c02SVedant Kumar return {};
73733e97e63SEnrico Granata
738d4381153SPavel Labath ValueObjectSP valobj_rep_sp = valobj_r_base_sp->GetChildMemberWithName(
739d4381153SPavel Labath ConstString("__value_"), /*can_create=*/true);
740d4381153SPavel Labath if (!valobj_rep_sp)
741d4381153SPavel Labath return {};
742d4381153SPavel Labath
743d4381153SPavel Labath ValueObjectSP l = valobj_rep_sp->GetChildMemberWithName(ConstString("__l"),
744d4381153SPavel Labath /*can_create=*/true);
745d4381153SPavel Labath if (!l)
746d4381153SPavel Labath return {};
747d4381153SPavel Labath
748d4381153SPavel Labath StringLayout layout = l->GetIndexOfChildWithName(ConstString("__data_")) == 0
749d4381153SPavel Labath ? StringLayout::DSC
750d4381153SPavel Labath : StringLayout::CSD;
751d4381153SPavel Labath
752b9c1b51eSKate Stone bool short_mode = false; // this means the string is in short-mode and the
753b9c1b51eSKate Stone // data is stored inline
7541056c567SPavel Labath bool using_bitmasks = true; // Whether the class uses bitmasks for the mode
7551056c567SPavel Labath // flag (pre-D123580).
7561056c567SPavel Labath uint64_t size;
75733e97e63SEnrico Granata uint64_t size_mode_value = 0;
75833e97e63SEnrico Granata
759d4381153SPavel Labath ValueObjectSP short_sp = valobj_rep_sp->GetChildMemberWithName(
760d4381153SPavel Labath ConstString("__s"), /*can_create=*/true);
76144a114feSMed Ismail Bennani if (!short_sp)
76244a114feSMed Ismail Bennani return {};
76344a114feSMed Ismail Bennani
764cff509f3SPavel Labath ValueObjectSP is_long =
765cff509f3SPavel Labath short_sp->GetChildMemberWithName(ConstString("__is_long_"), true);
766d4381153SPavel Labath ValueObjectSP size_sp =
767d4381153SPavel Labath short_sp->GetChildAtNamePath({ConstString("__size_")});
768d4381153SPavel Labath if (!size_sp)
769d4381153SPavel Labath return {};
77044a114feSMed Ismail Bennani
771cff509f3SPavel Labath if (is_long) {
7721056c567SPavel Labath using_bitmasks = false;
7731056c567SPavel Labath short_mode = !is_long->GetValueAsUnsigned(/*fail_value=*/0);
774d4381153SPavel Labath size = size_sp->GetValueAsUnsigned(/*fail_value=*/0);
775b9c1b51eSKate Stone } else {
776d4381153SPavel Labath // The string mode is encoded in the size field.
777d4381153SPavel Labath size_mode_value = size_sp->GetValueAsUnsigned(0);
778d4381153SPavel Labath uint8_t mode_mask = layout == StringLayout::DSC ? 0x80 : 1;
779d4381153SPavel Labath short_mode = (size_mode_value & mode_mask) == 0;
78033e97e63SEnrico Granata }
78133e97e63SEnrico Granata
782b9c1b51eSKate Stone if (short_mode) {
783cff509f3SPavel Labath ValueObjectSP location_sp =
784d4381153SPavel Labath short_sp->GetChildMemberWithName(ConstString("__data_"), true);
7851056c567SPavel Labath if (using_bitmasks)
786d4381153SPavel Labath size = (layout == StringLayout::DSC) ? size_mode_value
787b9c1b51eSKate Stone : ((size_mode_value >> 1) % 256);
7887aabad13SVedant Kumar
7897aabad13SVedant Kumar // When the small-string optimization takes place, the data must fit in the
7907aabad13SVedant Kumar // inline string buffer (23 bytes on x86_64/Darwin). If it doesn't, it's
7917aabad13SVedant Kumar // likely that the string isn't initialized and we're reading garbage.
7927aabad13SVedant Kumar ExecutionContext exe_ctx(location_sp->GetExecutionContextRef());
7937aabad13SVedant Kumar const llvm::Optional<uint64_t> max_bytes =
7947aabad13SVedant Kumar location_sp->GetCompilerType().GetByteSize(
7957aabad13SVedant Kumar exe_ctx.GetBestExecutionContextScope());
79690a94c02SVedant Kumar if (!max_bytes || size > *max_bytes || !location_sp)
79790a94c02SVedant Kumar return {};
7987aabad13SVedant Kumar
79990a94c02SVedant Kumar return std::make_pair(size, location_sp);
80090a94c02SVedant Kumar }
80190a94c02SVedant Kumar
80233e97e63SEnrico Granata // we can use the layout_decider object as the data pointer
8031056c567SPavel Labath ValueObjectSP location_sp =
8041056c567SPavel Labath l->GetChildMemberWithName(ConstString("__data_"), /*can_create=*/true);
8051056c567SPavel Labath ValueObjectSP size_vo =
8061056c567SPavel Labath l->GetChildMemberWithName(ConstString("__size_"), /*can_create=*/true);
807cff509f3SPavel Labath ValueObjectSP capacity_vo =
808cff509f3SPavel Labath l->GetChildMemberWithName(ConstString("__cap_"), /*can_create=*/true);
8097aabad13SVedant Kumar if (!size_vo || !location_sp || !capacity_vo)
81090a94c02SVedant Kumar return {};
8111056c567SPavel Labath size = size_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET);
8121056c567SPavel Labath uint64_t capacity = capacity_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET);
813d4381153SPavel Labath if (!using_bitmasks && layout == StringLayout::CSD)
8141056c567SPavel Labath capacity *= 2;
81590a94c02SVedant Kumar if (size == LLDB_INVALID_OFFSET || capacity == LLDB_INVALID_OFFSET ||
81690a94c02SVedant Kumar capacity < size)
81790a94c02SVedant Kumar return {};
81890a94c02SVedant Kumar return std::make_pair(size, location_sp);
81933e97e63SEnrico Granata }
82033e97e63SEnrico Granata
8217244e9c2SBen Jackson static bool
LibcxxWStringSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & summary_options,ValueObjectSP location_sp,size_t size)8227244e9c2SBen Jackson LibcxxWStringSummaryProvider(ValueObject &valobj, Stream &stream,
8237244e9c2SBen Jackson const TypeSummaryOptions &summary_options,
8247244e9c2SBen Jackson ValueObjectSP location_sp, size_t size) {
825b9c1b51eSKate Stone if (size == 0) {
82633e97e63SEnrico Granata stream.Printf("L\"\"");
82733e97e63SEnrico Granata return true;
82833e97e63SEnrico Granata }
82933e97e63SEnrico Granata if (!location_sp)
83033e97e63SEnrico Granata return false;
83133e97e63SEnrico Granata
832b7662929SEnrico Granata StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
833b9c1b51eSKate Stone if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
834b7662929SEnrico Granata const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
835b9c1b51eSKate Stone if (size > max_size) {
836b7662929SEnrico Granata size = max_size;
837b7662929SEnrico Granata options.SetIsTruncated(true);
838b7662929SEnrico Granata }
839b7662929SEnrico Granata }
84090a94c02SVedant Kumar
84190a94c02SVedant Kumar DataExtractor extractor;
8427aabad13SVedant Kumar const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
8437aabad13SVedant Kumar if (bytes_read < size)
8447aabad13SVedant Kumar return false;
84533e97e63SEnrico Granata
84633e97e63SEnrico Granata // std::wstring::size() is measured in 'characters', not bytes
8476e3b0cc2SRaphael Isemann TypeSystemClang *ast_context =
848594308c7SRaphael Isemann ScratchTypeSystemClang::GetForTarget(*valobj.GetTargetSP());
8493031818aSAlex Langford if (!ast_context)
8503031818aSAlex Langford return false;
8513031818aSAlex Langford
8523031818aSAlex Langford auto wchar_t_size =
8533031818aSAlex Langford ast_context->GetBasicType(lldb::eBasicTypeWChar).GetByteSize(nullptr);
854d963a7c3SAdrian Prantl if (!wchar_t_size)
855d963a7c3SAdrian Prantl return false;
85633e97e63SEnrico Granata
85714f44303SJan Kratochvil options.SetData(std::move(extractor));
85833e97e63SEnrico Granata options.SetStream(&stream);
859d54f7fb8SEnrico Granata options.SetPrefixToken("L");
86033e97e63SEnrico Granata options.SetQuote('"');
86133e97e63SEnrico Granata options.SetSourceSize(size);
86233e97e63SEnrico Granata options.SetBinaryZeroIsTerminator(false);
86333e97e63SEnrico Granata
864d963a7c3SAdrian Prantl switch (*wchar_t_size) {
86533e97e63SEnrico Granata case 1:
8667aabad13SVedant Kumar return StringPrinter::ReadBufferAndDumpToStream<
867b9c1b51eSKate Stone lldb_private::formatters::StringPrinter::StringElementType::UTF8>(
868b9c1b51eSKate Stone options);
86933e97e63SEnrico Granata break;
87033e97e63SEnrico Granata
87133e97e63SEnrico Granata case 2:
8727aabad13SVedant Kumar return StringPrinter::ReadBufferAndDumpToStream<
873b9c1b51eSKate Stone lldb_private::formatters::StringPrinter::StringElementType::UTF16>(
874b9c1b51eSKate Stone options);
87533e97e63SEnrico Granata break;
87633e97e63SEnrico Granata
87733e97e63SEnrico Granata case 4:
8787aabad13SVedant Kumar return StringPrinter::ReadBufferAndDumpToStream<
879b9c1b51eSKate Stone lldb_private::formatters::StringPrinter::StringElementType::UTF32>(
880b9c1b51eSKate Stone options);
88133e97e63SEnrico Granata }
8827aabad13SVedant Kumar return false;
88333e97e63SEnrico Granata }
88433e97e63SEnrico Granata
LibcxxWStringSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & summary_options)8857244e9c2SBen Jackson bool lldb_private::formatters::LibcxxWStringSummaryProvider(
8867244e9c2SBen Jackson ValueObject &valobj, Stream &stream,
8877244e9c2SBen Jackson const TypeSummaryOptions &summary_options) {
88890a94c02SVedant Kumar auto string_info = ExtractLibcxxStringInfo(valobj);
88990a94c02SVedant Kumar if (!string_info)
89033e97e63SEnrico Granata return false;
89190a94c02SVedant Kumar uint64_t size;
89290a94c02SVedant Kumar ValueObjectSP location_sp;
89390a94c02SVedant Kumar std::tie(size, location_sp) = *string_info;
89490a94c02SVedant Kumar
8957244e9c2SBen Jackson return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options,
8967244e9c2SBen Jackson location_sp, size);
8977244e9c2SBen Jackson }
8987244e9c2SBen Jackson
8997244e9c2SBen Jackson template <StringPrinter::StringElementType element_type>
9007244e9c2SBen Jackson static bool
LibcxxStringSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & summary_options,std::string prefix_token,ValueObjectSP location_sp,uint64_t size)9017244e9c2SBen Jackson LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream,
9027244e9c2SBen Jackson const TypeSummaryOptions &summary_options,
9037244e9c2SBen Jackson std::string prefix_token, ValueObjectSP location_sp,
9047244e9c2SBen Jackson uint64_t size) {
9057244e9c2SBen Jackson
906b9c1b51eSKate Stone if (size == 0) {
90733e97e63SEnrico Granata stream.Printf("\"\"");
90833e97e63SEnrico Granata return true;
90933e97e63SEnrico Granata }
91033e97e63SEnrico Granata
91133e97e63SEnrico Granata if (!location_sp)
91233e97e63SEnrico Granata return false;
91333e97e63SEnrico Granata
914b7662929SEnrico Granata StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
915b7662929SEnrico Granata
916b9c1b51eSKate Stone if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
917b7662929SEnrico Granata const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
918b9c1b51eSKate Stone if (size > max_size) {
919b7662929SEnrico Granata size = max_size;
920b7662929SEnrico Granata options.SetIsTruncated(true);
921b7662929SEnrico Granata }
922b7662929SEnrico Granata }
92390a94c02SVedant Kumar
92414f44303SJan Kratochvil {
92590a94c02SVedant Kumar DataExtractor extractor;
9267aabad13SVedant Kumar const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
9277aabad13SVedant Kumar if (bytes_read < size)
9287aabad13SVedant Kumar return false;
92933e97e63SEnrico Granata
93014f44303SJan Kratochvil options.SetData(std::move(extractor));
93114f44303SJan Kratochvil }
93233e97e63SEnrico Granata options.SetStream(&stream);
933693fbf5cSShafik Yaghmour if (prefix_token.empty())
934bbd16815SEugene Zelenko options.SetPrefixToken(nullptr);
935693fbf5cSShafik Yaghmour else
936693fbf5cSShafik Yaghmour options.SetPrefixToken(prefix_token);
93733e97e63SEnrico Granata options.SetQuote('"');
93833e97e63SEnrico Granata options.SetSourceSize(size);
93933e97e63SEnrico Granata options.SetBinaryZeroIsTerminator(false);
9407aabad13SVedant Kumar return StringPrinter::ReadBufferAndDumpToStream<element_type>(options);
9417aabad13SVedant Kumar }
94233e97e63SEnrico Granata
9437aabad13SVedant Kumar template <StringPrinter::StringElementType element_type>
9447244e9c2SBen Jackson static bool
LibcxxStringSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & summary_options,std::string prefix_token)9457244e9c2SBen Jackson LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream,
9467244e9c2SBen Jackson const TypeSummaryOptions &summary_options,
9477244e9c2SBen Jackson std::string prefix_token) {
9487244e9c2SBen Jackson auto string_info = ExtractLibcxxStringInfo(valobj);
9497244e9c2SBen Jackson if (!string_info)
9507244e9c2SBen Jackson return false;
9517244e9c2SBen Jackson uint64_t size;
9527244e9c2SBen Jackson ValueObjectSP location_sp;
9537244e9c2SBen Jackson std::tie(size, location_sp) = *string_info;
9547244e9c2SBen Jackson
9557244e9c2SBen Jackson return LibcxxStringSummaryProvider<element_type>(
9567244e9c2SBen Jackson valobj, stream, summary_options, prefix_token, location_sp, size);
9577244e9c2SBen Jackson }
9587244e9c2SBen Jackson template <StringPrinter::StringElementType element_type>
formatStringImpl(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & summary_options,std::string prefix_token)9597aabad13SVedant Kumar static bool formatStringImpl(ValueObject &valobj, Stream &stream,
9607aabad13SVedant Kumar const TypeSummaryOptions &summary_options,
9617aabad13SVedant Kumar std::string prefix_token) {
9627aabad13SVedant Kumar StreamString scratch_stream;
9637aabad13SVedant Kumar const bool success = LibcxxStringSummaryProvider<element_type>(
9647aabad13SVedant Kumar valobj, scratch_stream, summary_options, prefix_token);
9657aabad13SVedant Kumar if (success)
9667aabad13SVedant Kumar stream << scratch_stream.GetData();
9677aabad13SVedant Kumar else
9687aabad13SVedant Kumar stream << "Summary Unavailable";
96933e97e63SEnrico Granata return true;
97033e97e63SEnrico Granata }
971693fbf5cSShafik Yaghmour
LibcxxStringSummaryProviderASCII(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & summary_options)972693fbf5cSShafik Yaghmour bool lldb_private::formatters::LibcxxStringSummaryProviderASCII(
973693fbf5cSShafik Yaghmour ValueObject &valobj, Stream &stream,
974693fbf5cSShafik Yaghmour const TypeSummaryOptions &summary_options) {
9757aabad13SVedant Kumar return formatStringImpl<StringPrinter::StringElementType::ASCII>(
9767aabad13SVedant Kumar valobj, stream, summary_options, "");
977693fbf5cSShafik Yaghmour }
978693fbf5cSShafik Yaghmour
LibcxxStringSummaryProviderUTF16(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & summary_options)979693fbf5cSShafik Yaghmour bool lldb_private::formatters::LibcxxStringSummaryProviderUTF16(
980693fbf5cSShafik Yaghmour ValueObject &valobj, Stream &stream,
981693fbf5cSShafik Yaghmour const TypeSummaryOptions &summary_options) {
9827aabad13SVedant Kumar return formatStringImpl<StringPrinter::StringElementType::UTF16>(
983693fbf5cSShafik Yaghmour valobj, stream, summary_options, "u");
984693fbf5cSShafik Yaghmour }
985693fbf5cSShafik Yaghmour
LibcxxStringSummaryProviderUTF32(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & summary_options)986693fbf5cSShafik Yaghmour bool lldb_private::formatters::LibcxxStringSummaryProviderUTF32(
987693fbf5cSShafik Yaghmour ValueObject &valobj, Stream &stream,
988693fbf5cSShafik Yaghmour const TypeSummaryOptions &summary_options) {
9897aabad13SVedant Kumar return formatStringImpl<StringPrinter::StringElementType::UTF32>(
990693fbf5cSShafik Yaghmour valobj, stream, summary_options, "U");
991693fbf5cSShafik Yaghmour }
9927244e9c2SBen Jackson
9937244e9c2SBen Jackson static std::tuple<bool, ValueObjectSP, size_t>
LibcxxExtractStringViewData(ValueObject & valobj)9947244e9c2SBen Jackson LibcxxExtractStringViewData(ValueObject& valobj) {
9957244e9c2SBen Jackson ConstString g_data_name("__data");
9967244e9c2SBen Jackson ConstString g_size_name("__size");
9977244e9c2SBen Jackson auto dataobj = valobj.GetChildMemberWithName(g_data_name, true);
9987244e9c2SBen Jackson auto sizeobj = valobj.GetChildMemberWithName(g_size_name, true);
9997244e9c2SBen Jackson
10007244e9c2SBen Jackson if (!dataobj || !sizeobj)
10017244e9c2SBen Jackson return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
10027244e9c2SBen Jackson
10037244e9c2SBen Jackson if (!dataobj->GetError().Success() || !sizeobj->GetError().Success())
10047244e9c2SBen Jackson return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
10057244e9c2SBen Jackson
10067244e9c2SBen Jackson bool success{false};
10077244e9c2SBen Jackson uint64_t size = sizeobj->GetValueAsUnsigned(0, &success);
10087244e9c2SBen Jackson if (!success)
10097244e9c2SBen Jackson return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
10107244e9c2SBen Jackson
10117244e9c2SBen Jackson return std::make_tuple(true,dataobj,size);
10127244e9c2SBen Jackson }
10137244e9c2SBen Jackson
10147244e9c2SBen Jackson template <StringPrinter::StringElementType element_type>
formatStringViewImpl(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & summary_options,std::string prefix_token)10157244e9c2SBen Jackson static bool formatStringViewImpl(ValueObject &valobj, Stream &stream,
10167244e9c2SBen Jackson const TypeSummaryOptions &summary_options,
10177244e9c2SBen Jackson std::string prefix_token) {
10187244e9c2SBen Jackson
10197244e9c2SBen Jackson bool success;
10207244e9c2SBen Jackson ValueObjectSP dataobj;
10217244e9c2SBen Jackson size_t size;
10227244e9c2SBen Jackson std::tie(success, dataobj, size) = LibcxxExtractStringViewData(valobj);
10237244e9c2SBen Jackson
10247244e9c2SBen Jackson if (!success) {
10257244e9c2SBen Jackson stream << "Summary Unavailable";
10267244e9c2SBen Jackson return true;
10277244e9c2SBen Jackson }
10287244e9c2SBen Jackson
10297244e9c2SBen Jackson return LibcxxStringSummaryProvider<element_type>(
10307244e9c2SBen Jackson valobj, stream, summary_options, prefix_token, dataobj, size);
10317244e9c2SBen Jackson }
10327244e9c2SBen Jackson
LibcxxStringViewSummaryProviderASCII(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & summary_options)10337244e9c2SBen Jackson bool lldb_private::formatters::LibcxxStringViewSummaryProviderASCII(
10347244e9c2SBen Jackson ValueObject &valobj, Stream &stream,
10357244e9c2SBen Jackson const TypeSummaryOptions &summary_options) {
10367244e9c2SBen Jackson return formatStringViewImpl<StringPrinter::StringElementType::ASCII>(
10377244e9c2SBen Jackson valobj, stream, summary_options, "");
10387244e9c2SBen Jackson }
10397244e9c2SBen Jackson
LibcxxStringViewSummaryProviderUTF16(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & summary_options)10407244e9c2SBen Jackson bool lldb_private::formatters::LibcxxStringViewSummaryProviderUTF16(
10417244e9c2SBen Jackson ValueObject &valobj, Stream &stream,
10427244e9c2SBen Jackson const TypeSummaryOptions &summary_options) {
10437244e9c2SBen Jackson return formatStringViewImpl<StringPrinter::StringElementType::UTF16>(
10447244e9c2SBen Jackson valobj, stream, summary_options, "u");
10457244e9c2SBen Jackson }
10467244e9c2SBen Jackson
LibcxxStringViewSummaryProviderUTF32(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & summary_options)10477244e9c2SBen Jackson bool lldb_private::formatters::LibcxxStringViewSummaryProviderUTF32(
10487244e9c2SBen Jackson ValueObject &valobj, Stream &stream,
10497244e9c2SBen Jackson const TypeSummaryOptions &summary_options) {
10507244e9c2SBen Jackson return formatStringViewImpl<StringPrinter::StringElementType::UTF32>(
10517244e9c2SBen Jackson valobj, stream, summary_options, "U");
10527244e9c2SBen Jackson }
10537244e9c2SBen Jackson
LibcxxWStringViewSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & summary_options)10547244e9c2SBen Jackson bool lldb_private::formatters::LibcxxWStringViewSummaryProvider(
10557244e9c2SBen Jackson ValueObject &valobj, Stream &stream,
10567244e9c2SBen Jackson const TypeSummaryOptions &summary_options) {
10577244e9c2SBen Jackson
10587244e9c2SBen Jackson bool success;
10597244e9c2SBen Jackson ValueObjectSP dataobj;
10607244e9c2SBen Jackson size_t size;
10617244e9c2SBen Jackson std::tie( success, dataobj, size ) = LibcxxExtractStringViewData(valobj);
10627244e9c2SBen Jackson
10637244e9c2SBen Jackson if (!success) {
10647244e9c2SBen Jackson stream << "Summary Unavailable";
10657244e9c2SBen Jackson return true;
10667244e9c2SBen Jackson }
10677244e9c2SBen Jackson
10687244e9c2SBen Jackson
10697244e9c2SBen Jackson return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options,
10707244e9c2SBen Jackson dataobj, size);
10717244e9c2SBen Jackson }
1072