xref: /NextBSD/contrib/llvm/tools/lldb/source/DataFormatters/NSArray.cpp (revision 84d351007654069f9643c8e4b4802a7f5f08ee42)
1 //===-- NSArray.cpp ---------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/DataFormatters/CXXFormatterFunctions.h"
11 
12 #include "lldb/Core/DataBufferHeap.h"
13 #include "lldb/Core/Error.h"
14 #include "lldb/Core/Stream.h"
15 #include "lldb/Core/ValueObject.h"
16 #include "lldb/Core/ValueObjectConstResult.h"
17 #include "lldb/Host/Endian.h"
18 #include "lldb/Symbol/ClangASTContext.h"
19 #include "lldb/Target/ObjCLanguageRuntime.h"
20 #include "lldb/Target/Target.h"
21 
22 #include "clang/AST/ASTContext.h"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 using namespace lldb_private::formatters;
27 
28 namespace  lldb_private {
29     namespace formatters {
30         class NSArrayMSyntheticFrontEnd : public SyntheticChildrenFrontEnd
31         {
32         public:
33             NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
34 
35             virtual size_t
36             CalculateNumChildren ();
37 
38             virtual lldb::ValueObjectSP
39             GetChildAtIndex (size_t idx);
40 
41             virtual bool
42             Update() = 0;
43 
44             virtual bool
45             MightHaveChildren ();
46 
47             virtual size_t
48             GetIndexOfChildWithName (const ConstString &name);
49 
50             virtual
~NSArrayMSyntheticFrontEnd()51             ~NSArrayMSyntheticFrontEnd () {}
52 
53         protected:
54             virtual lldb::addr_t
55             GetDataAddress () = 0;
56 
57             virtual uint64_t
58             GetUsedCount () = 0;
59 
60             virtual uint64_t
61             GetOffset () = 0;
62 
63             virtual uint64_t
64             GetSize () = 0;
65 
66             ExecutionContextRef m_exe_ctx_ref;
67             uint8_t m_ptr_size;
68             ClangASTType m_id_type;
69             std::vector<lldb::ValueObjectSP> m_children;
70         };
71 
72         class NSArrayMSyntheticFrontEnd_109 : public NSArrayMSyntheticFrontEnd
73         {
74         private:
75             struct DataDescriptor_32
76             {
77                 uint32_t _used;
78                 uint32_t _priv1 : 2 ;
79                 uint32_t _size : 30;
80                 uint32_t _priv2 : 2;
81                 uint32_t _offset : 30;
82                 uint32_t _priv3;
83                 uint32_t _data;
84             };
85             struct DataDescriptor_64
86             {
87                 uint64_t _used;
88                 uint64_t _priv1 : 2 ;
89                 uint64_t _size : 62;
90                 uint64_t _priv2 : 2;
91                 uint64_t _offset : 62;
92                 uint32_t _priv3;
93                 uint64_t _data;
94             };
95         public:
96             NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp);
97 
98             virtual bool
99             Update();
100 
101             virtual
102             ~NSArrayMSyntheticFrontEnd_109 ();
103 
104         protected:
105             virtual lldb::addr_t
106             GetDataAddress ();
107 
108             virtual uint64_t
109             GetUsedCount ();
110 
111             virtual uint64_t
112             GetOffset ();
113 
114             virtual uint64_t
115             GetSize ();
116 
117         private:
118             DataDescriptor_32 *m_data_32;
119             DataDescriptor_64 *m_data_64;
120         };
121 
122         class NSArrayMSyntheticFrontEnd_1010 : public NSArrayMSyntheticFrontEnd
123         {
124         private:
125             struct DataDescriptor_32
126             {
127                 uint32_t _used;
128                 uint32_t _offset;
129                 uint32_t _size : 28;
130                 uint64_t _priv1 : 4;
131                 uint32_t _priv2;
132                 uint32_t _data;
133             };
134             struct DataDescriptor_64
135             {
136                 uint64_t _used;
137                 uint64_t _offset;
138                 uint64_t _size : 60;
139                 uint64_t _priv1 : 4;
140                 uint32_t _priv2;
141                 uint64_t _data;
142             };
143         public:
144             NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp);
145 
146             virtual bool
147             Update();
148 
149             virtual
150             ~NSArrayMSyntheticFrontEnd_1010 ();
151 
152         protected:
153             virtual lldb::addr_t
154             GetDataAddress ();
155 
156             virtual uint64_t
157             GetUsedCount ();
158 
159             virtual uint64_t
160             GetOffset ();
161 
162             virtual uint64_t
163             GetSize ();
164 
165         private:
166             DataDescriptor_32 *m_data_32;
167             DataDescriptor_64 *m_data_64;
168         };
169 
170         class NSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd
171         {
172         public:
173             NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
174 
175             virtual size_t
176             CalculateNumChildren ();
177 
178             virtual lldb::ValueObjectSP
179             GetChildAtIndex (size_t idx);
180 
181             virtual bool
182             Update();
183 
184             virtual bool
185             MightHaveChildren ();
186 
187             virtual size_t
188             GetIndexOfChildWithName (const ConstString &name);
189 
190             virtual
191             ~NSArrayISyntheticFrontEnd ();
192         private:
193             ExecutionContextRef m_exe_ctx_ref;
194             uint8_t m_ptr_size;
195             uint64_t m_items;
196             lldb::addr_t m_data_ptr;
197             ClangASTType m_id_type;
198             std::vector<lldb::ValueObjectSP> m_children;
199         };
200 
201         class NSArrayCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
202         {
203         public:
204             NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
205 
206             virtual size_t
207             CalculateNumChildren ();
208 
209             virtual lldb::ValueObjectSP
210             GetChildAtIndex (size_t idx);
211 
212             virtual bool
213             Update();
214 
215             virtual bool
216             MightHaveChildren ();
217 
218             virtual size_t
219             GetIndexOfChildWithName (const ConstString &name);
220 
221             virtual
222             ~NSArrayCodeRunningSyntheticFrontEnd ();
223         };
224     }
225 }
226 
227 bool
NSArraySummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & options)228 lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
229 {
230     ProcessSP process_sp = valobj.GetProcessSP();
231     if (!process_sp)
232         return false;
233 
234     ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
235 
236     if (!runtime)
237         return false;
238 
239     ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
240 
241     if (!descriptor.get() || !descriptor->IsValid())
242         return false;
243 
244     uint32_t ptr_size = process_sp->GetAddressByteSize();
245 
246     lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
247 
248     if (!valobj_addr)
249         return false;
250 
251     uint64_t value = 0;
252 
253     const char* class_name = descriptor->GetClassName().GetCString();
254 
255     if (!class_name || !*class_name)
256         return false;
257 
258     if (!strcmp(class_name,"__NSArrayI"))
259     {
260         Error error;
261         value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
262         if (error.Fail())
263             return false;
264     }
265     else if (!strcmp(class_name,"__NSArrayM"))
266     {
267         Error error;
268         value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
269         if (error.Fail())
270             return false;
271     }
272     else if (!strcmp(class_name,"__NSCFArray"))
273     {
274         Error error;
275         value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + 2 * ptr_size, ptr_size, 0, error);
276         if (error.Fail())
277             return false;
278     }
279     else
280     {
281         if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
282             return false;
283     }
284 
285     stream.Printf("@\"%" PRIu64 " object%s\"",
286                   value,
287                   value == 1 ? "" : "s");
288     return true;
289 }
290 
NSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)291 lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
292 SyntheticChildrenFrontEnd(*valobj_sp),
293     m_exe_ctx_ref(),
294     m_ptr_size(8),
295 m_id_type(),
296 m_children()
297 {
298     if (valobj_sp)
299     {
300         clang::ASTContext *ast = valobj_sp->GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext()->getASTContext();
301         if (ast)
302             m_id_type = ClangASTType(ast, ast->ObjCBuiltinIdTy);
303         if (valobj_sp->GetProcessSP())
304             m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize();
305     }
306 }
307 
NSArrayMSyntheticFrontEnd_109(lldb::ValueObjectSP valobj_sp)308 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp) :
309 NSArrayMSyntheticFrontEnd(valobj_sp),
310 m_data_32(NULL),
311 m_data_64(NULL)
312 {
313 }
314 
NSArrayMSyntheticFrontEnd_1010(lldb::ValueObjectSP valobj_sp)315 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp) :
316 NSArrayMSyntheticFrontEnd(valobj_sp),
317 m_data_32(NULL),
318 m_data_64(NULL)
319 {
320 }
321 
322 size_t
CalculateNumChildren()323 lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren ()
324 {
325     return GetUsedCount();
326 }
327 
328 lldb::ValueObjectSP
GetChildAtIndex(size_t idx)329 lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
330 {
331     if (idx >= CalculateNumChildren())
332         return lldb::ValueObjectSP();
333     lldb::addr_t object_at_idx = GetDataAddress();
334     size_t pyhs_idx = idx;
335     pyhs_idx += GetOffset();
336     if (GetSize() <= pyhs_idx)
337         pyhs_idx -= GetSize();
338     object_at_idx += (pyhs_idx * m_ptr_size);
339     StreamString idx_name;
340     idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
341     lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(),
342                                                                  object_at_idx,
343                                                                  m_exe_ctx_ref,
344                                                                  m_id_type);
345     m_children.push_back(retval_sp);
346     return retval_sp;
347 }
348 
349 bool
Update()350 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::Update()
351 {
352     m_children.clear();
353     ValueObjectSP valobj_sp = m_backend.GetSP();
354     m_ptr_size = 0;
355     delete m_data_32;
356     m_data_32 = NULL;
357     delete m_data_64;
358     m_data_64 = NULL;
359     if (!valobj_sp)
360         return false;
361     m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
362     Error error;
363     error.Clear();
364     lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
365     if (!process_sp)
366         return false;
367     m_ptr_size = process_sp->GetAddressByteSize();
368     uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
369     if (m_ptr_size == 4)
370     {
371         m_data_32 = new DataDescriptor_32();
372         process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
373     }
374     else
375     {
376         m_data_64 = new DataDescriptor_64();
377         process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
378     }
379     if (error.Fail())
380         return false;
381     return false;
382 }
383 
384 bool
Update()385 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::Update()
386 {
387     m_children.clear();
388     ValueObjectSP valobj_sp = m_backend.GetSP();
389     m_ptr_size = 0;
390     delete m_data_32;
391     m_data_32 = NULL;
392     delete m_data_64;
393     m_data_64 = NULL;
394     if (!valobj_sp)
395         return false;
396     m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
397     Error error;
398     error.Clear();
399     lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
400     if (!process_sp)
401         return false;
402     m_ptr_size = process_sp->GetAddressByteSize();
403     uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
404     if (m_ptr_size == 4)
405     {
406         m_data_32 = new DataDescriptor_32();
407         process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
408     }
409     else
410     {
411         m_data_64 = new DataDescriptor_64();
412         process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
413     }
414     if (error.Fail())
415         return false;
416     return false;
417 }
418 
419 bool
MightHaveChildren()420 lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren ()
421 {
422     return true;
423 }
424 
425 size_t
GetIndexOfChildWithName(const ConstString & name)426 lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
427 {
428     const char* item_name = name.GetCString();
429     uint32_t idx = ExtractIndexFromString(item_name);
430     if (idx < UINT32_MAX && idx >= CalculateNumChildren())
431         return UINT32_MAX;
432     return idx;
433 }
434 
435 lldb::addr_t
GetDataAddress()436 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetDataAddress ()
437 {
438     if (!m_data_32 && !m_data_64)
439         return LLDB_INVALID_ADDRESS;
440     return m_data_32 ? m_data_32->_data :
441     m_data_64->_data;
442 }
443 
444 uint64_t
GetUsedCount()445 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetUsedCount ()
446 {
447     if (!m_data_32 && !m_data_64)
448         return 0;
449     return m_data_32 ? m_data_32->_used :
450     m_data_64->_used;
451 }
452 
453 uint64_t
GetOffset()454 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetOffset ()
455 {
456     if (!m_data_32 && !m_data_64)
457         return 0;
458     return m_data_32 ? m_data_32->_offset :
459     m_data_64->_offset;
460 }
461 
462 uint64_t
GetSize()463 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetSize ()
464 {
465     if (!m_data_32 && !m_data_64)
466         return 0;
467     return m_data_32 ? m_data_32->_size :
468     m_data_64->_size;
469 }
470 
~NSArrayMSyntheticFrontEnd_109()471 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::~NSArrayMSyntheticFrontEnd_109 ()
472 {
473     delete m_data_32;
474     m_data_32 = NULL;
475     delete m_data_64;
476     m_data_64 = NULL;
477 }
478 
479 lldb::addr_t
GetDataAddress()480 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetDataAddress ()
481 {
482     if (!m_data_32 && !m_data_64)
483         return LLDB_INVALID_ADDRESS;
484     return m_data_32 ? m_data_32->_data :
485     m_data_64->_data;
486 }
487 
488 uint64_t
GetUsedCount()489 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetUsedCount ()
490 {
491     if (!m_data_32 && !m_data_64)
492         return 0;
493     return m_data_32 ? m_data_32->_used :
494     m_data_64->_used;
495 }
496 
497 uint64_t
GetOffset()498 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetOffset ()
499 {
500     if (!m_data_32 && !m_data_64)
501         return 0;
502     return m_data_32 ? m_data_32->_offset :
503     m_data_64->_offset;
504 }
505 
506 uint64_t
GetSize()507 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize ()
508 {
509     if (!m_data_32 && !m_data_64)
510         return 0;
511     return m_data_32 ? m_data_32->_size :
512     m_data_64->_size;
513 }
514 
~NSArrayMSyntheticFrontEnd_1010()515 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::~NSArrayMSyntheticFrontEnd_1010 ()
516 {
517     delete m_data_32;
518     m_data_32 = NULL;
519     delete m_data_64;
520     m_data_64 = NULL;
521 }
522 
NSArrayISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)523 lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
524     SyntheticChildrenFrontEnd (*valobj_sp.get()),
525     m_exe_ctx_ref (),
526     m_ptr_size (8),
527     m_items (0),
528     m_data_ptr (0)
529 {
530     if (valobj_sp)
531     {
532         clang::ASTContext *ast = valobj_sp->GetClangType().GetASTContext();
533         if (ast)
534             m_id_type = ClangASTType(ast, ast->ObjCBuiltinIdTy);
535     }
536 }
537 
~NSArrayISyntheticFrontEnd()538 lldb_private::formatters::NSArrayISyntheticFrontEnd::~NSArrayISyntheticFrontEnd ()
539 {
540 }
541 
542 size_t
GetIndexOfChildWithName(const ConstString & name)543 lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
544 {
545     const char* item_name = name.GetCString();
546     uint32_t idx = ExtractIndexFromString(item_name);
547     if (idx < UINT32_MAX && idx >= CalculateNumChildren())
548         return UINT32_MAX;
549     return idx;
550 }
551 
552 size_t
CalculateNumChildren()553 lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren ()
554 {
555     return m_items;
556 }
557 
558 bool
Update()559 lldb_private::formatters::NSArrayISyntheticFrontEnd::Update()
560 {
561     m_ptr_size = 0;
562     m_items = 0;
563     m_data_ptr = 0;
564     m_children.clear();
565     ValueObjectSP valobj_sp = m_backend.GetSP();
566     if (!valobj_sp)
567         return false;
568     m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
569     Error error;
570     error.Clear();
571     lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
572     if (!process_sp)
573         return false;
574     m_ptr_size = process_sp->GetAddressByteSize();
575     uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
576     m_items = process_sp->ReadPointerFromMemory(data_location, error);
577     if (error.Fail())
578         return false;
579     m_data_ptr = data_location+m_ptr_size;
580     return false;
581 }
582 
583 bool
MightHaveChildren()584 lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren ()
585 {
586     return true;
587 }
588 
589 lldb::ValueObjectSP
GetChildAtIndex(size_t idx)590 lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx)
591 {
592     if (idx >= CalculateNumChildren())
593         return lldb::ValueObjectSP();
594     lldb::addr_t object_at_idx = m_data_ptr;
595     object_at_idx += (idx * m_ptr_size);
596     ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
597     if (!process_sp)
598         return lldb::ValueObjectSP();
599     Error error;
600     if (error.Fail())
601         return lldb::ValueObjectSP();
602     StreamString idx_name;
603     idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
604     lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(),
605                                                                  object_at_idx,
606                                                                  m_exe_ctx_ref,
607                                                                  m_id_type);
608     m_children.push_back(retval_sp);
609     return retval_sp;
610 }
611 
NSArraySyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)612 SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
613 {
614     return nullptr; // Avoid need for AppleObjCRuntime on FreeBSD
615 #if 0
616     if (!valobj_sp)
617         return nullptr;
618 
619     lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
620     if (!process_sp)
621         return NULL;
622     AppleObjCRuntime *runtime = (AppleObjCRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
623     if (!runtime)
624         return NULL;
625 
626     ClangASTType valobj_type(valobj_sp->GetClangType());
627     Flags flags(valobj_type.GetTypeInfo());
628 
629     if (flags.IsClear(eTypeIsPointer))
630     {
631         Error error;
632         valobj_sp = valobj_sp->AddressOf(error);
633         if (error.Fail() || !valobj_sp)
634             return NULL;
635     }
636 
637     ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
638 
639     if (!descriptor.get() || !descriptor->IsValid())
640         return NULL;
641 
642     const char* class_name = descriptor->GetClassName().GetCString();
643 
644     if (!class_name || !*class_name)
645         return NULL;
646 
647     if (!strcmp(class_name,"__NSArrayI"))
648     {
649         return (new NSArrayISyntheticFrontEnd(valobj_sp));
650     }
651     else if (!strcmp(class_name,"__NSArrayM"))
652     {
653         if (runtime->GetFoundationVersion() >= 1100)
654             return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp));
655         else
656             return (new NSArrayMSyntheticFrontEnd_109(valobj_sp));
657     }
658     else
659     {
660         return (new NSArrayCodeRunningSyntheticFrontEnd(valobj_sp));
661     }
662 #endif
663 }
664 
NSArrayCodeRunningSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)665 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
666 SyntheticChildrenFrontEnd(*valobj_sp.get())
667 {}
668 
669 size_t
CalculateNumChildren()670 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
671 {
672     uint64_t count = 0;
673     if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
674         return count;
675     return 0;
676 }
677 
678 lldb::ValueObjectSP
GetChildAtIndex(size_t idx)679 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
680 {
681     StreamString idx_name;
682     idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
683     lldb::ValueObjectSP valobj_sp = CallSelectorOnObject(m_backend,"id","objectAtIndex:",idx);
684     if (valobj_sp)
685         valobj_sp->SetName(ConstString(idx_name.GetData()));
686     return valobj_sp;
687 }
688 
689 bool
Update()690 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::Update()
691 {
692     return false;
693 }
694 
695 bool
MightHaveChildren()696 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::MightHaveChildren ()
697 {
698     return true;
699 }
700 
701 size_t
GetIndexOfChildWithName(const ConstString & name)702 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
703 {
704     return 0;
705 }
706 
~NSArrayCodeRunningSyntheticFrontEnd()707 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::~NSArrayCodeRunningSyntheticFrontEnd ()
708 {}
709