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