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