1 //===-- NSSet.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 "NSSet.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/DataFormatters/FormattersHelpers.h"
18 #include "lldb/Host/Endian.h"
19 #include "lldb/Symbol/ClangASTContext.h"
20 #include "lldb/Target/ObjCLanguageRuntime.h"
21 #include "lldb/Target/Target.h"
22 
23 using namespace lldb;
24 using namespace lldb_private;
25 using namespace lldb_private::formatters;
26 
27 std::map<ConstString, CXXFunctionSummaryFormat::Callback>&
28 NSSet_Additionals::GetAdditionalSummaries ()
29 {
30     static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map;
31     return g_map;
32 }
33 
34 std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>&
35 NSSet_Additionals::GetAdditionalSynthetics ()
36 {
37     static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> g_map;
38     return g_map;
39 }
40 
41 namespace lldb_private {
42     namespace formatters {
43         class NSSetISyntheticFrontEnd : public SyntheticChildrenFrontEnd
44         {
45         private:
46             struct DataDescriptor_32
47             {
48                 uint32_t _used : 26;
49                 uint32_t _szidx : 6;
50             };
51             struct DataDescriptor_64
52             {
53                 uint64_t _used : 58;
54                 uint32_t _szidx : 6;
55             };
56 
57             struct SetItemDescriptor
58             {
59                 lldb::addr_t item_ptr;
60                 lldb::ValueObjectSP valobj_sp;
61             };
62 
63         public:
64             NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
65 
66             virtual size_t
67             CalculateNumChildren ();
68 
69             virtual lldb::ValueObjectSP
70             GetChildAtIndex (size_t idx);
71 
72             virtual bool
73             Update();
74 
75             virtual bool
76             MightHaveChildren ();
77 
78             virtual size_t
79             GetIndexOfChildWithName (const ConstString &name);
80 
81             virtual
82             ~NSSetISyntheticFrontEnd ();
83         private:
84             ExecutionContextRef m_exe_ctx_ref;
85             uint8_t m_ptr_size;
86             DataDescriptor_32 *m_data_32;
87             DataDescriptor_64 *m_data_64;
88             lldb::addr_t m_data_ptr;
89             std::vector<SetItemDescriptor> m_children;
90         };
91 
92         class NSOrderedSetSyntheticFrontEnd : public SyntheticChildrenFrontEnd
93         {
94         private:
95 
96         public:
97             NSOrderedSetSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
98 
99             virtual size_t
100             CalculateNumChildren ();
101 
102             virtual lldb::ValueObjectSP
103             GetChildAtIndex (size_t idx);
104 
105             virtual bool
106             Update();
107 
108             virtual bool
109             MightHaveChildren ();
110 
111             virtual size_t
112             GetIndexOfChildWithName (const ConstString &name);
113 
114             virtual
115             ~NSOrderedSetSyntheticFrontEnd ();
116         private:
117             uint32_t m_count;
118             std::map<uint32_t,lldb::ValueObjectSP> m_children;
119         };
120 
121         class NSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd
122         {
123         private:
124             struct DataDescriptor_32
125             {
126                 uint32_t _used : 26;
127                 uint32_t _size;
128                 uint32_t _mutations;
129                 uint32_t _objs_addr;
130             };
131             struct DataDescriptor_64
132             {
133                 uint64_t _used : 58;
134                 uint64_t _size;
135                 uint64_t _mutations;
136                 uint64_t _objs_addr;
137             };
138             struct SetItemDescriptor
139             {
140                 lldb::addr_t item_ptr;
141                 lldb::ValueObjectSP valobj_sp;
142             };
143         public:
144             NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
145 
146             virtual size_t
147             CalculateNumChildren ();
148 
149             virtual lldb::ValueObjectSP
150             GetChildAtIndex (size_t idx);
151 
152             virtual bool
153             Update();
154 
155             virtual bool
156             MightHaveChildren ();
157 
158             virtual size_t
159             GetIndexOfChildWithName (const ConstString &name);
160 
161             virtual
162             ~NSSetMSyntheticFrontEnd ();
163         private:
164             ExecutionContextRef m_exe_ctx_ref;
165             uint8_t m_ptr_size;
166             DataDescriptor_32 *m_data_32;
167             DataDescriptor_64 *m_data_64;
168             std::vector<SetItemDescriptor> m_children;
169         };
170 
171         class NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
172         {
173         public:
174             NSSetCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
175 
176             virtual size_t
177             CalculateNumChildren ();
178 
179             virtual lldb::ValueObjectSP
180             GetChildAtIndex (size_t idx);
181 
182             virtual bool
183             Update();
184 
185             virtual bool
186             MightHaveChildren ();
187 
188             virtual size_t
189             GetIndexOfChildWithName (const ConstString &name);
190 
191             virtual
192             ~NSSetCodeRunningSyntheticFrontEnd ();
193         };
194     }
195 }
196 
197 template<bool cf_style>
198 bool
199 lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
200 {
201     ProcessSP process_sp = valobj.GetProcessSP();
202     if (!process_sp)
203         return false;
204 
205     ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
206 
207     if (!runtime)
208         return false;
209 
210     ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
211 
212     if (!descriptor.get() || !descriptor->IsValid())
213         return false;
214 
215     uint32_t ptr_size = process_sp->GetAddressByteSize();
216     bool is_64bit = (ptr_size == 8);
217 
218     lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
219 
220     if (!valobj_addr)
221         return false;
222 
223     uint64_t value = 0;
224 
225     ConstString class_name_cs = descriptor->GetClassName();
226     const char* class_name = class_name_cs.GetCString();
227 
228     if (!class_name || !*class_name)
229         return false;
230 
231     if (!strcmp(class_name,"__NSSetI"))
232     {
233         Error error;
234         value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
235         if (error.Fail())
236             return false;
237         value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
238     }
239     else if (!strcmp(class_name,"__NSSetM"))
240     {
241         Error error;
242         value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
243         if (error.Fail())
244             return false;
245         value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
246     }
247     /*else if (!strcmp(class_name,"__NSCFSet"))
248     {
249         Error error;
250         value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error);
251         if (error.Fail())
252             return false;
253         if (is_64bit)
254             value &= ~0x1fff000000000000UL;
255     }
256     else if (!strcmp(class_name,"NSCountedSet"))
257     {
258         Error error;
259         value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
260         if (error.Fail())
261             return false;
262         value = process_sp->ReadUnsignedIntegerFromMemory(value + (is_64bit ? 20 : 12), 4, 0, error);
263         if (error.Fail())
264             return false;
265         if (is_64bit)
266             value &= ~0x1fff000000000000UL;
267     }*/
268     else
269     {
270         auto& map(NSSet_Additionals::GetAdditionalSummaries());
271         auto iter = map.find(class_name_cs), end = map.end();
272         if (iter != end)
273             return iter->second(valobj, stream, options);
274         if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
275             return false;
276     }
277 
278     stream.Printf("%s%" PRIu64 " %s%s",
279                   (cf_style ? "@\"" : ""),
280                   value,
281                   (cf_style ? (value == 1 ? "value" : "values") : (value == 1 ? "object" : "objects")),
282                   (cf_style ? "\"" : ""));
283     return true;
284 }
285 
286 SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreator (CXXSyntheticChildren* synth, lldb::ValueObjectSP valobj_sp)
287 {
288     lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
289     if (!process_sp)
290         return NULL;
291     ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
292     if (!runtime)
293         return NULL;
294 
295     if (!valobj_sp->IsPointerType())
296     {
297         Error error;
298         valobj_sp = valobj_sp->AddressOf(error);
299         if (error.Fail() || !valobj_sp)
300             return NULL;
301     }
302 
303     ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
304 
305     if (!descriptor.get() || !descriptor->IsValid())
306         return NULL;
307 
308     ConstString class_name_cs = descriptor->GetClassName();
309     const char* class_name = class_name_cs.GetCString();
310 
311     if (!class_name || !*class_name)
312         return NULL;
313 
314     if (!strcmp(class_name,"__NSSetI"))
315     {
316         return (new NSSetISyntheticFrontEnd(valobj_sp));
317     }
318     else if (!strcmp(class_name,"__NSSetM"))
319     {
320         return (new NSSetMSyntheticFrontEnd(valobj_sp));
321     }
322     else if ((!strcmp(class_name,"__NSOrderedSetI")) || (!strcmp(class_name,"__NSOrderedSetM")))
323     {
324         return new NSOrderedSetSyntheticFrontEnd(valobj_sp); // this runs code
325     }
326     else
327     {
328         auto& map(NSSet_Additionals::GetAdditionalSynthetics());
329         auto iter = map.find(class_name_cs), end = map.end();
330         if (iter != end)
331             return iter->second(synth, valobj_sp);
332         return /*(new NSSetCodeRunningSyntheticFrontEnd(valobj_sp))*/ NULL;
333     }
334 }
335 
336 lldb_private::formatters::NSSetISyntheticFrontEnd::NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
337 SyntheticChildrenFrontEnd(*valobj_sp.get()),
338 m_exe_ctx_ref(),
339 m_ptr_size(8),
340 m_data_32(NULL),
341 m_data_64(NULL)
342 {
343     if (valobj_sp)
344         Update();
345 }
346 
347 lldb_private::formatters::NSSetISyntheticFrontEnd::~NSSetISyntheticFrontEnd ()
348 {
349     delete m_data_32;
350     m_data_32 = NULL;
351     delete m_data_64;
352     m_data_64 = NULL;
353 }
354 
355 size_t
356 lldb_private::formatters::NSSetISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
357 {
358     const char* item_name = name.GetCString();
359     uint32_t idx = ExtractIndexFromString(item_name);
360     if (idx < UINT32_MAX && idx >= CalculateNumChildren())
361         return UINT32_MAX;
362     return idx;
363 }
364 
365 size_t
366 lldb_private::formatters::NSSetISyntheticFrontEnd::CalculateNumChildren ()
367 {
368     if (!m_data_32 && !m_data_64)
369         return 0;
370     return (m_data_32 ? m_data_32->_used : m_data_64->_used);
371 }
372 
373 bool
374 lldb_private::formatters::NSSetISyntheticFrontEnd::Update()
375 {
376     m_children.clear();
377     delete m_data_32;
378     m_data_32 = NULL;
379     delete m_data_64;
380     m_data_64 = NULL;
381     m_ptr_size = 0;
382     ValueObjectSP valobj_sp = m_backend.GetSP();
383     if (!valobj_sp)
384         return false;
385     if (!valobj_sp)
386         return false;
387     m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
388     Error error;
389     if (valobj_sp->IsPointerType())
390     {
391         valobj_sp = valobj_sp->Dereference(error);
392         if (error.Fail() || !valobj_sp)
393             return false;
394     }
395     error.Clear();
396     lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
397     if (!process_sp)
398         return false;
399     m_ptr_size = process_sp->GetAddressByteSize();
400     uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
401     if (m_ptr_size == 4)
402     {
403         m_data_32 = new DataDescriptor_32();
404         process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
405     }
406     else
407     {
408         m_data_64 = new DataDescriptor_64();
409         process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
410     }
411     if (error.Fail())
412         return false;
413     m_data_ptr = data_location + m_ptr_size;
414     return false;
415 }
416 
417 bool
418 lldb_private::formatters::NSSetISyntheticFrontEnd::MightHaveChildren ()
419 {
420     return true;
421 }
422 
423 lldb::ValueObjectSP
424 lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx)
425 {
426     uint32_t num_children = CalculateNumChildren();
427 
428     if (idx >= num_children)
429         return lldb::ValueObjectSP();
430 
431     ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
432     if (!process_sp)
433         return lldb::ValueObjectSP();
434 
435     if (m_children.empty())
436     {
437         // do the scan phase
438         lldb::addr_t obj_at_idx = 0;
439 
440         uint32_t tries = 0;
441         uint32_t test_idx = 0;
442 
443         while(tries < num_children)
444         {
445             obj_at_idx = m_data_ptr + (test_idx * m_ptr_size);
446             if (!process_sp)
447                 return lldb::ValueObjectSP();
448             Error error;
449             obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error);
450             if (error.Fail())
451                 return lldb::ValueObjectSP();
452 
453             test_idx++;
454 
455             if (!obj_at_idx)
456                 continue;
457             tries++;
458 
459             SetItemDescriptor descriptor = {obj_at_idx,lldb::ValueObjectSP()};
460 
461             m_children.push_back(descriptor);
462         }
463     }
464 
465     if (idx >= m_children.size()) // should never happen
466         return lldb::ValueObjectSP();
467 
468     SetItemDescriptor &set_item = m_children[idx];
469     if (!set_item.valobj_sp)
470     {
471         auto ptr_size = process_sp->GetAddressByteSize();
472         DataBufferHeap buffer(ptr_size,0);
473         switch (ptr_size)
474         {
475             case 0: // architecture has no clue?? - fail
476                 return lldb::ValueObjectSP();
477             case 4:
478                 *((uint32_t*)buffer.GetBytes()) = (uint32_t)set_item.item_ptr;
479                 break;
480             case 8:
481                 *((uint64_t*)buffer.GetBytes()) = (uint64_t)set_item.item_ptr;
482                 break;
483             default:
484                 assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
485         }
486         StreamString idx_name;
487         idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
488 
489         DataExtractor data(buffer.GetBytes(),
490                            buffer.GetByteSize(),
491                            process_sp->GetByteOrder(),
492                            process_sp->GetAddressByteSize());
493 
494         set_item.valobj_sp =
495             CreateValueObjectFromData(idx_name.GetData(),
496                                       data,
497                                       m_exe_ctx_ref,
498                                       m_backend.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
499     }
500     return set_item.valobj_sp;
501 }
502 
503 lldb_private::formatters::NSSetMSyntheticFrontEnd::NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
504 SyntheticChildrenFrontEnd(*valobj_sp.get()),
505 m_exe_ctx_ref(),
506 m_ptr_size(8),
507 m_data_32(NULL),
508 m_data_64(NULL)
509 {
510     if (valobj_sp)
511         Update ();
512 }
513 
514 lldb_private::formatters::NSSetMSyntheticFrontEnd::~NSSetMSyntheticFrontEnd ()
515 {
516     delete m_data_32;
517     m_data_32 = NULL;
518     delete m_data_64;
519     m_data_64 = NULL;
520 }
521 
522 size_t
523 lldb_private::formatters::NSSetMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
524 {
525     const char* item_name = name.GetCString();
526     uint32_t idx = ExtractIndexFromString(item_name);
527     if (idx < UINT32_MAX && idx >= CalculateNumChildren())
528         return UINT32_MAX;
529     return idx;
530 }
531 
532 size_t
533 lldb_private::formatters::NSSetMSyntheticFrontEnd::CalculateNumChildren ()
534 {
535     if (!m_data_32 && !m_data_64)
536         return 0;
537     return (m_data_32 ? m_data_32->_used : m_data_64->_used);
538 }
539 
540 bool
541 lldb_private::formatters::NSSetMSyntheticFrontEnd::Update()
542 {
543     m_children.clear();
544     ValueObjectSP valobj_sp = m_backend.GetSP();
545     m_ptr_size = 0;
546     delete m_data_32;
547     m_data_32 = NULL;
548     delete m_data_64;
549     m_data_64 = NULL;
550     if (!valobj_sp)
551         return false;
552     if (!valobj_sp)
553         return false;
554     m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
555     Error error;
556     if (valobj_sp->IsPointerType())
557     {
558         valobj_sp = valobj_sp->Dereference(error);
559         if (error.Fail() || !valobj_sp)
560             return false;
561     }
562     error.Clear();
563     lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
564     if (!process_sp)
565         return false;
566     m_ptr_size = process_sp->GetAddressByteSize();
567     uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
568     if (m_ptr_size == 4)
569     {
570         m_data_32 = new DataDescriptor_32();
571         process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
572     }
573     else
574     {
575         m_data_64 = new DataDescriptor_64();
576         process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
577     }
578     if (error.Fail())
579         return false;
580     return false;
581 }
582 
583 bool
584 lldb_private::formatters::NSSetMSyntheticFrontEnd::MightHaveChildren ()
585 {
586     return true;
587 }
588 
589 lldb::ValueObjectSP
590 lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
591 {
592     lldb::addr_t m_objs_addr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
593 
594     uint32_t num_children = CalculateNumChildren();
595 
596     if (idx >= num_children)
597         return lldb::ValueObjectSP();
598 
599     ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
600     if (!process_sp)
601         return lldb::ValueObjectSP();
602 
603     if (m_children.empty())
604     {
605         // do the scan phase
606         lldb::addr_t obj_at_idx = 0;
607 
608         uint32_t tries = 0;
609         uint32_t test_idx = 0;
610 
611         while(tries < num_children)
612         {
613             obj_at_idx = m_objs_addr + (test_idx * m_ptr_size);
614             if (!process_sp)
615                 return lldb::ValueObjectSP();
616             Error error;
617             obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error);
618             if (error.Fail())
619                 return lldb::ValueObjectSP();
620 
621             test_idx++;
622 
623             if (!obj_at_idx)
624                 continue;
625             tries++;
626 
627             SetItemDescriptor descriptor = {obj_at_idx,lldb::ValueObjectSP()};
628 
629             m_children.push_back(descriptor);
630         }
631     }
632 
633     if (idx >= m_children.size()) // should never happen
634         return lldb::ValueObjectSP();
635 
636     SetItemDescriptor &set_item = m_children[idx];
637     if (!set_item.valobj_sp)
638     {
639         auto ptr_size = process_sp->GetAddressByteSize();
640         DataBufferHeap buffer(ptr_size,0);
641         switch (ptr_size)
642         {
643             case 0: // architecture has no clue?? - fail
644                 return lldb::ValueObjectSP();
645             case 4:
646                 *((uint32_t*)buffer.GetBytes()) = (uint32_t)set_item.item_ptr;
647                 break;
648             case 8:
649                 *((uint64_t*)buffer.GetBytes()) = (uint64_t)set_item.item_ptr;
650                 break;
651             default:
652                 assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
653         }
654         StreamString idx_name;
655         idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
656 
657         DataExtractor data(buffer.GetBytes(),
658                            buffer.GetByteSize(),
659                            process_sp->GetByteOrder(),
660                            process_sp->GetAddressByteSize());
661 
662         set_item.valobj_sp =
663             CreateValueObjectFromData(idx_name.GetData(),
664                                       data,
665                                       m_exe_ctx_ref,
666                                       m_backend.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
667     }
668     return set_item.valobj_sp;
669 }
670 
671 lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::NSOrderedSetSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
672 SyntheticChildrenFrontEnd(*valobj_sp.get()),
673 m_count(UINT32_MAX),
674 m_children()
675 {}
676 
677 size_t
678 lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::CalculateNumChildren ()
679 {
680     if (m_count != UINT32_MAX)
681         return m_count;
682     uint64_t count_temp;
683     if (ExtractValueFromObjCExpression(m_backend,"unsigned int","count",count_temp))
684         return (m_count = count_temp);
685     return (m_count = 0);
686 }
687 
688 lldb::ValueObjectSP
689 lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::GetChildAtIndex (size_t idx)
690 {
691     auto iter = m_children.find(idx);
692     if (iter == m_children.end())
693     {
694         lldb::ValueObjectSP retval_sp;
695         if (idx <= m_count)
696         {
697             retval_sp = CallSelectorOnObject(m_backend, "id", "objectAtIndex", idx);
698             if (retval_sp)
699             {
700                 StreamString idx_name;
701                 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
702                 retval_sp->SetName(ConstString(idx_name.GetData()));
703             }
704             m_children[idx] = retval_sp;
705         }
706         return retval_sp;
707     }
708     else
709         return iter->second;
710 }
711 
712 bool
713 lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::Update()
714 {
715     return false;
716 }
717 
718 bool
719 lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::MightHaveChildren ()
720 {
721     return true;
722 }
723 
724 size_t
725 lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
726 {
727     const char* item_name = name.GetCString();
728     uint32_t idx = ExtractIndexFromString(item_name);
729     if (idx < UINT32_MAX && idx >= CalculateNumChildren())
730         return UINT32_MAX;
731     return idx;
732 }
733 
734 lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::~NSOrderedSetSyntheticFrontEnd ()
735 {
736 }
737 
738 template bool
739 lldb_private::formatters::NSSetSummaryProvider<true> (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
740 
741 template bool
742 lldb_private::formatters::NSSetSummaryProvider<false> (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
743