6ebd89a4626bd948f390438094ec90cec6101837
[lldb.git] / lldb / source / Plugins / Language / ObjC / ObjCLanguage.cpp
1 //===-- ObjCLanguage.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 // C Includes
11 // C++ Includes
12 #include <mutex>
13
14 // Other libraries and framework includes
15 // Project includes
16 #include "ObjCLanguage.h"
17
18 #include "lldb/Core/PluginManager.h"
19 #include "lldb/Core/ValueObject.h"
20 #include "lldb/DataFormatters/DataVisualization.h"
21 #include "lldb/DataFormatters/FormattersHelpers.h"
22 #include "lldb/Symbol/ClangASTContext.h"
23 #include "lldb/Symbol/CompilerType.h"
24 #include "lldb/Target/ObjCLanguageRuntime.h"
25 #include "lldb/Target/Target.h"
26 #include "lldb/Utility/ConstString.h"
27 #include "lldb/Utility/StreamString.h"
28
29 #include "llvm/Support/Threading.h"
30
31 #include "CF.h"
32 #include "Cocoa.h"
33 #include "CoreMedia.h"
34 #include "NSDictionary.h"
35 #include "NSSet.h"
36 #include "NSString.h"
37
38 using namespace lldb;
39 using namespace lldb_private;
40 using namespace lldb_private::formatters;
41
42 void ObjCLanguage::Initialize() {
43   PluginManager::RegisterPlugin(GetPluginNameStatic(), "Objective-C Language",
44                                 CreateInstance);
45 }
46
47 void ObjCLanguage::Terminate() {
48   PluginManager::UnregisterPlugin(CreateInstance);
49 }
50
51 lldb_private::ConstString ObjCLanguage::GetPluginNameStatic() {
52   static ConstString g_name("objc");
53   return g_name;
54 }
55
56 //------------------------------------------------------------------
57 // PluginInterface protocol
58 //------------------------------------------------------------------
59
60 lldb_private::ConstString ObjCLanguage::GetPluginName() {
61   return GetPluginNameStatic();
62 }
63
64 uint32_t ObjCLanguage::GetPluginVersion() { return 1; }
65
66 //------------------------------------------------------------------
67 // Static Functions
68 //------------------------------------------------------------------
69
70 Language *ObjCLanguage::CreateInstance(lldb::LanguageType language) {
71   switch (language) {
72   case lldb::eLanguageTypeObjC:
73     return new ObjCLanguage();
74   default:
75     return nullptr;
76   }
77 }
78
79 void ObjCLanguage::MethodName::Clear() {
80   m_full.Clear();
81   m_class.Clear();
82   m_category.Clear();
83   m_selector.Clear();
84   m_type = eTypeUnspecified;
85   m_category_is_valid = false;
86 }
87
88 bool ObjCLanguage::MethodName::SetName(llvm::StringRef name, bool strict) {
89   Clear();
90   if (name.empty())
91     return IsValid(strict);
92
93   // If "strict" is true. then the method must be specified with a '+' or '-'
94   // at the beginning. If "strict" is false, then the '+' or '-' can be omitted
95   bool valid_prefix = false;
96
97   if (name.size() > 1 && (name[0] == '+' || name[0] == '-')) {
98     valid_prefix = name[1] == '[';
99     if (name[0] == '+')
100       m_type = eTypeClassMethod;
101     else
102       m_type = eTypeInstanceMethod;
103   } else if (!strict) {
104     // "strict" is false, the name just needs to start with '['
105     valid_prefix = name[0] == '[';
106   }
107
108   if (valid_prefix) {
109     int name_len = name.size();
110     // Objective-C methods must have at least:
111     //      "-[" or "+[" prefix
112     //      One character for a class name
113     //      One character for the space between the class name
114     //      One character for the method name
115     //      "]" suffix
116     if (name_len >= (5 + (strict ? 1 : 0)) && name.back() == ']') {
117       m_full.SetString(name);
118     }
119   }
120   return IsValid(strict);
121 }
122
123 bool ObjCLanguage::MethodName::SetName(const char *name, bool strict) {
124   return SetName(llvm::StringRef(name), strict);
125 }
126
127 const ConstString &ObjCLanguage::MethodName::GetClassName() {
128   if (!m_class) {
129     if (IsValid(false)) {
130       const char *full = m_full.GetCString();
131       const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
132       const char *paren_pos = strchr(class_start, '(');
133       if (paren_pos) {
134         m_class.SetCStringWithLength(class_start, paren_pos - class_start);
135       } else {
136         // No '(' was found in the full name, we can definitively say that our
137         // category was valid (and empty).
138         m_category_is_valid = true;
139         const char *space_pos = strchr(full, ' ');
140         if (space_pos) {
141           m_class.SetCStringWithLength(class_start, space_pos - class_start);
142           if (!m_class_category) {
143             // No category in name, so we can also fill in the m_class_category
144             m_class_category = m_class;
145           }
146         }
147       }
148     }
149   }
150   return m_class;
151 }
152
153 const ConstString &ObjCLanguage::MethodName::GetClassNameWithCategory() {
154   if (!m_class_category) {
155     if (IsValid(false)) {
156       const char *full = m_full.GetCString();
157       const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
158       const char *space_pos = strchr(full, ' ');
159       if (space_pos) {
160         m_class_category.SetCStringWithLength(class_start,
161                                               space_pos - class_start);
162         // If m_class hasn't been filled in and the class with category doesn't
163         // contain a '(', then we can also fill in the m_class
164         if (!m_class && strchr(m_class_category.GetCString(), '(') == nullptr) {
165           m_class = m_class_category;
166           // No '(' was found in the full name, we can definitively say that
167           // our category was valid (and empty).
168           m_category_is_valid = true;
169         }
170       }
171     }
172   }
173   return m_class_category;
174 }
175
176 const ConstString &ObjCLanguage::MethodName::GetSelector() {
177   if (!m_selector) {
178     if (IsValid(false)) {
179       const char *full = m_full.GetCString();
180       const char *space_pos = strchr(full, ' ');
181       if (space_pos) {
182         ++space_pos; // skip the space
183         m_selector.SetCStringWithLength(space_pos, m_full.GetLength() -
184                                                        (space_pos - full) - 1);
185       }
186     }
187   }
188   return m_selector;
189 }
190
191 const ConstString &ObjCLanguage::MethodName::GetCategory() {
192   if (!m_category_is_valid && !m_category) {
193     if (IsValid(false)) {
194       m_category_is_valid = true;
195       const char *full = m_full.GetCString();
196       const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
197       const char *open_paren_pos = strchr(class_start, '(');
198       if (open_paren_pos) {
199         ++open_paren_pos; // Skip the open paren
200         const char *close_paren_pos = strchr(open_paren_pos, ')');
201         if (close_paren_pos)
202           m_category.SetCStringWithLength(open_paren_pos,
203                                           close_paren_pos - open_paren_pos);
204       }
205     }
206   }
207   return m_category;
208 }
209
210 ConstString ObjCLanguage::MethodName::GetFullNameWithoutCategory(
211     bool empty_if_no_category) {
212   if (IsValid(false)) {
213     if (HasCategory()) {
214       StreamString strm;
215       if (m_type == eTypeClassMethod)
216         strm.PutChar('+');
217       else if (m_type == eTypeInstanceMethod)
218         strm.PutChar('-');
219       strm.Printf("[%s %s]", GetClassName().GetCString(),
220                   GetSelector().GetCString());
221       return ConstString(strm.GetString());
222     }
223
224     if (!empty_if_no_category) {
225       // Just return the full name since it doesn't have a category
226       return GetFullName();
227     }
228   }
229   return ConstString();
230 }
231
232 size_t ObjCLanguage::MethodName::GetFullNames(std::vector<ConstString> &names,
233                                               bool append) {
234   if (!append)
235     names.clear();
236   if (IsValid(false)) {
237     StreamString strm;
238     const bool is_class_method = m_type == eTypeClassMethod;
239     const bool is_instance_method = m_type == eTypeInstanceMethod;
240     const ConstString &category = GetCategory();
241     if (is_class_method || is_instance_method) {
242       names.push_back(m_full);
243       if (category) {
244         strm.Printf("%c[%s %s]", is_class_method ? '+' : '-',
245                     GetClassName().GetCString(), GetSelector().GetCString());
246         names.emplace_back(strm.GetString());
247       }
248     } else {
249       const ConstString &class_name = GetClassName();
250       const ConstString &selector = GetSelector();
251       strm.Printf("+[%s %s]", class_name.GetCString(), selector.GetCString());
252       names.emplace_back(strm.GetString());
253       strm.Clear();
254       strm.Printf("-[%s %s]", class_name.GetCString(), selector.GetCString());
255       names.emplace_back(strm.GetString());
256       strm.Clear();
257       if (category) {
258         strm.Printf("+[%s(%s) %s]", class_name.GetCString(),
259                     category.GetCString(), selector.GetCString());
260         names.emplace_back(strm.GetString());
261         strm.Clear();
262         strm.Printf("-[%s(%s) %s]", class_name.GetCString(),
263                     category.GetCString(), selector.GetCString());
264         names.emplace_back(strm.GetString());
265       }
266     }
267   }
268   return names.size();
269 }
270
271 static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
272   if (!objc_category_sp)
273     return;
274
275   TypeSummaryImpl::Flags objc_flags;
276   objc_flags.SetCascades(false)
277       .SetSkipPointers(true)
278       .SetSkipReferences(true)
279       .SetDontShowChildren(true)
280       .SetDontShowValue(true)
281       .SetShowMembersOneLiner(false)
282       .SetHideItemNames(false);
283
284   lldb::TypeSummaryImplSP ObjC_BOOL_summary(new CXXFunctionSummaryFormat(
285       objc_flags, lldb_private::formatters::ObjCBOOLSummaryProvider, ""));
286   objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL"),
287                                                      ObjC_BOOL_summary);
288   objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL &"),
289                                                      ObjC_BOOL_summary);
290   objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL *"),
291                                                      ObjC_BOOL_summary);
292
293 #ifndef LLDB_DISABLE_PYTHON
294   // we need to skip pointers here since we are special casing a SEL* when
295   // retrieving its value
296   objc_flags.SetSkipPointers(true);
297   AddCXXSummary(objc_category_sp,
298                 lldb_private::formatters::ObjCSELSummaryProvider<false>,
299                 "SEL summary provider", ConstString("SEL"), objc_flags);
300   AddCXXSummary(
301       objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>,
302       "SEL summary provider", ConstString("struct objc_selector"), objc_flags);
303   AddCXXSummary(
304       objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>,
305       "SEL summary provider", ConstString("objc_selector"), objc_flags);
306   AddCXXSummary(
307       objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<true>,
308       "SEL summary provider", ConstString("objc_selector *"), objc_flags);
309   AddCXXSummary(objc_category_sp,
310                 lldb_private::formatters::ObjCSELSummaryProvider<true>,
311                 "SEL summary provider", ConstString("SEL *"), objc_flags);
312
313   AddCXXSummary(objc_category_sp,
314                 lldb_private::formatters::ObjCClassSummaryProvider,
315                 "Class summary provider", ConstString("Class"), objc_flags);
316
317   SyntheticChildren::Flags class_synth_flags;
318   class_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
319       false);
320
321   AddCXXSynthetic(objc_category_sp,
322                   lldb_private::formatters::ObjCClassSyntheticFrontEndCreator,
323                   "Class synthetic children", ConstString("Class"),
324                   class_synth_flags);
325 #endif // LLDB_DISABLE_PYTHON
326
327   objc_flags.SetSkipPointers(false);
328   objc_flags.SetCascades(true);
329   objc_flags.SetSkipReferences(false);
330
331   AddStringSummary(objc_category_sp, "${var.__FuncPtr%A}",
332                    ConstString("__block_literal_generic"), objc_flags);
333
334   AddStringSummary(objc_category_sp, "${var.years} years, ${var.months} "
335                                      "months, ${var.days} days, ${var.hours} "
336                                      "hours, ${var.minutes} minutes "
337                                      "${var.seconds} seconds",
338                    ConstString("CFGregorianUnits"), objc_flags);
339   AddStringSummary(objc_category_sp,
340                    "location=${var.location} length=${var.length}",
341                    ConstString("CFRange"), objc_flags);
342
343   AddStringSummary(objc_category_sp,
344                    "location=${var.location}, length=${var.length}",
345                    ConstString("NSRange"), objc_flags);
346   AddStringSummary(objc_category_sp, "(${var.origin}, ${var.size}), ...",
347                    ConstString("NSRectArray"), objc_flags);
348
349   AddOneLineSummary(objc_category_sp, ConstString("NSPoint"), objc_flags);
350   AddOneLineSummary(objc_category_sp, ConstString("NSSize"), objc_flags);
351   AddOneLineSummary(objc_category_sp, ConstString("NSRect"), objc_flags);
352
353   AddOneLineSummary(objc_category_sp, ConstString("CGSize"), objc_flags);
354   AddOneLineSummary(objc_category_sp, ConstString("CGPoint"), objc_flags);
355   AddOneLineSummary(objc_category_sp, ConstString("CGRect"), objc_flags);
356
357   AddStringSummary(objc_category_sp,
358                    "red=${var.red} green=${var.green} blue=${var.blue}",
359                    ConstString("RGBColor"), objc_flags);
360   AddStringSummary(
361       objc_category_sp,
362       "(t=${var.top}, l=${var.left}, b=${var.bottom}, r=${var.right})",
363       ConstString("Rect"), objc_flags);
364   AddStringSummary(objc_category_sp, "{(v=${var.v}, h=${var.h})}",
365                    ConstString("Point"), objc_flags);
366   AddStringSummary(objc_category_sp,
367                    "${var.month}/${var.day}/${var.year}  ${var.hour} "
368                    ":${var.minute} :${var.second} dayOfWeek:${var.dayOfWeek}",
369                    ConstString("DateTimeRect *"), objc_flags);
370   AddStringSummary(objc_category_sp, "${var.ld.month}/${var.ld.day}/"
371                                      "${var.ld.year} ${var.ld.hour} "
372                                      ":${var.ld.minute} :${var.ld.second} "
373                                      "dayOfWeek:${var.ld.dayOfWeek}",
374                    ConstString("LongDateRect"), objc_flags);
375   AddStringSummary(objc_category_sp, "(x=${var.x}, y=${var.y})",
376                    ConstString("HIPoint"), objc_flags);
377   AddStringSummary(objc_category_sp, "origin=${var.origin} size=${var.size}",
378                    ConstString("HIRect"), objc_flags);
379
380   TypeSummaryImpl::Flags appkit_flags;
381   appkit_flags.SetCascades(true)
382       .SetSkipPointers(false)
383       .SetSkipReferences(false)
384       .SetDontShowChildren(true)
385       .SetDontShowValue(false)
386       .SetShowMembersOneLiner(false)
387       .SetHideItemNames(false);
388
389   appkit_flags.SetDontShowChildren(false);
390
391 #ifndef LLDB_DISABLE_PYTHON
392   AddCXXSummary(
393       objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
394       "NSArray summary provider", ConstString("NSArray"), appkit_flags);
395   AddCXXSummary(
396       objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
397       "NSArray summary provider", ConstString("NSMutableArray"), appkit_flags);
398   AddCXXSummary(
399       objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
400       "NSArray summary provider", ConstString("__NSArrayI"), appkit_flags);
401   AddCXXSummary(
402       objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
403       "NSArray summary provider", ConstString("__NSArray0"), appkit_flags);
404   AddCXXSummary(objc_category_sp,
405                 lldb_private::formatters::NSArraySummaryProvider,
406                 "NSArray summary provider",
407                 ConstString("__NSSingleObjectArrayI"), appkit_flags);
408   AddCXXSummary(
409       objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
410       "NSArray summary provider", ConstString("__NSArrayM"), appkit_flags);
411   AddCXXSummary(
412       objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
413       "NSArray summary provider", ConstString("__NSCFArray"), appkit_flags);
414   AddCXXSummary(
415       objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
416       "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags);
417   AddCXXSummary(objc_category_sp,
418                 lldb_private::formatters::NSArraySummaryProvider,
419                 "NSArray summary provider", ConstString("CFMutableArrayRef"),
420                 appkit_flags);
421
422   AddCXXSummary(objc_category_sp,
423                 lldb_private::formatters::NSDictionarySummaryProvider<false>,
424                 "NSDictionary summary provider", ConstString("NSDictionary"),
425                 appkit_flags);
426   AddCXXSummary(objc_category_sp,
427                 lldb_private::formatters::NSDictionarySummaryProvider<false>,
428                 "NSDictionary summary provider",
429                 ConstString("NSMutableDictionary"), appkit_flags);
430   AddCXXSummary(objc_category_sp,
431                 lldb_private::formatters::NSDictionarySummaryProvider<false>,
432                 "NSDictionary summary provider",
433                 ConstString("__NSCFDictionary"), appkit_flags);
434   AddCXXSummary(objc_category_sp,
435                 lldb_private::formatters::NSDictionarySummaryProvider<false>,
436                 "NSDictionary summary provider", ConstString("__NSDictionaryI"),
437                 appkit_flags);
438   AddCXXSummary(objc_category_sp,
439                 lldb_private::formatters::NSDictionarySummaryProvider<false>,
440                 "NSDictionary summary provider",
441                 ConstString("__NSSingleEntryDictionaryI"), appkit_flags);
442   AddCXXSummary(objc_category_sp,
443                 lldb_private::formatters::NSDictionarySummaryProvider<false>,
444                 "NSDictionary summary provider", ConstString("__NSDictionaryM"),
445                 appkit_flags);
446   AddCXXSummary(objc_category_sp,
447                 lldb_private::formatters::NSDictionarySummaryProvider<true>,
448                 "NSDictionary summary provider", ConstString("CFDictionaryRef"),
449                 appkit_flags);
450   AddCXXSummary(objc_category_sp,
451                 lldb_private::formatters::NSDictionarySummaryProvider<true>,
452                 "NSDictionary summary provider",
453                 ConstString("CFMutableDictionaryRef"), appkit_flags);
454
455   AddCXXSummary(objc_category_sp,
456                 lldb_private::formatters::NSSetSummaryProvider<false>,
457                 "NSSet summary", ConstString("NSSet"), appkit_flags);
458   AddCXXSummary(
459       objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
460       "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
461   AddCXXSummary(objc_category_sp,
462                 lldb_private::formatters::NSSetSummaryProvider<true>,
463                 "CFSetRef summary", ConstString("CFSetRef"), appkit_flags);
464   AddCXXSummary(
465       objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>,
466       "CFMutableSetRef summary", ConstString("CFMutableSetRef"), appkit_flags);
467   AddCXXSummary(objc_category_sp,
468                 lldb_private::formatters::NSSetSummaryProvider<false>,
469                 "__NSCFSet summary", ConstString("__NSCFSet"), appkit_flags);
470   AddCXXSummary(objc_category_sp,
471                 lldb_private::formatters::NSSetSummaryProvider<false>,
472                 "__NSSetI summary", ConstString("__NSSetI"), appkit_flags);
473   AddCXXSummary(objc_category_sp,
474                 lldb_private::formatters::NSSetSummaryProvider<false>,
475                 "__NSSetM summary", ConstString("__NSSetM"), appkit_flags);
476   AddCXXSummary(
477       objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
478       "NSCountedSet summary", ConstString("NSCountedSet"), appkit_flags);
479   AddCXXSummary(
480       objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
481       "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
482   AddCXXSummary(
483       objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
484       "NSOrderedSet summary", ConstString("NSOrderedSet"), appkit_flags);
485   AddCXXSummary(
486       objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
487       "__NSOrderedSetI summary", ConstString("__NSOrderedSetI"), appkit_flags);
488   AddCXXSummary(
489       objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
490       "__NSOrderedSetM summary", ConstString("__NSOrderedSetM"), appkit_flags);
491
492   AddCXXSummary(
493       objc_category_sp, lldb_private::formatters::NSError_SummaryProvider,
494       "NSError summary provider", ConstString("NSError"), appkit_flags);
495   AddCXXSummary(
496       objc_category_sp, lldb_private::formatters::NSException_SummaryProvider,
497       "NSException summary provider", ConstString("NSException"), appkit_flags);
498
499   // AddSummary(appkit_category_sp, "${var.key%@} -> ${var.value%@}",
500   // ConstString("$_lldb_typegen_nspair"), appkit_flags);
501
502   appkit_flags.SetDontShowChildren(true);
503
504   AddCXXSynthetic(objc_category_sp,
505                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
506                   "NSArray synthetic children", ConstString("__NSArrayM"),
507                   ScriptedSyntheticChildren::Flags());
508   AddCXXSynthetic(objc_category_sp,
509                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
510                   "NSArray synthetic children", ConstString("__NSArrayI"),
511                   ScriptedSyntheticChildren::Flags());
512   AddCXXSynthetic(objc_category_sp,
513                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
514                   "NSArray synthetic children", ConstString("__NSArray0"),
515                   ScriptedSyntheticChildren::Flags());
516   AddCXXSynthetic(objc_category_sp,
517                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
518                   "NSArray synthetic children",
519                   ConstString("__NSSingleObjectArrayI"),
520                   ScriptedSyntheticChildren::Flags());
521   AddCXXSynthetic(objc_category_sp,
522                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
523                   "NSArray synthetic children", ConstString("NSArray"),
524                   ScriptedSyntheticChildren::Flags());
525   AddCXXSynthetic(objc_category_sp,
526                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
527                   "NSArray synthetic children", ConstString("NSMutableArray"),
528                   ScriptedSyntheticChildren::Flags());
529   AddCXXSynthetic(objc_category_sp,
530                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
531                   "NSArray synthetic children", ConstString("__NSCFArray"),
532                   ScriptedSyntheticChildren::Flags());
533   AddCXXSynthetic(objc_category_sp,
534                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
535                   "NSArray synthetic children",
536                   ConstString("CFMutableArrayRef"),
537                   ScriptedSyntheticChildren::Flags());
538   AddCXXSynthetic(objc_category_sp,
539                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
540                   "NSArray synthetic children", ConstString("CFArrayRef"),
541                   ScriptedSyntheticChildren::Flags());
542
543   AddCXXSynthetic(
544       objc_category_sp,
545       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
546       "NSDictionary synthetic children", ConstString("__NSDictionaryM"),
547       ScriptedSyntheticChildren::Flags());
548   AddCXXSynthetic(
549       objc_category_sp,
550       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
551       "NSDictionary synthetic children", ConstString("__NSDictionaryI"),
552       ScriptedSyntheticChildren::Flags());
553   AddCXXSynthetic(
554       objc_category_sp,
555       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
556       "NSDictionary synthetic children",
557       ConstString("__NSSingleEntryDictionaryI"),
558       ScriptedSyntheticChildren::Flags());
559   AddCXXSynthetic(
560       objc_category_sp,
561       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
562       "NSDictionary synthetic children", ConstString("__NSCFDictionary"),
563       ScriptedSyntheticChildren::Flags());
564   AddCXXSynthetic(
565       objc_category_sp,
566       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
567       "NSDictionary synthetic children", ConstString("NSDictionary"),
568       ScriptedSyntheticChildren::Flags());
569   AddCXXSynthetic(
570       objc_category_sp,
571       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
572       "NSDictionary synthetic children", ConstString("NSMutableDictionary"),
573       ScriptedSyntheticChildren::Flags());
574   AddCXXSynthetic(
575       objc_category_sp,
576       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
577       "NSDictionary synthetic children", ConstString("CFDictionaryRef"),
578       ScriptedSyntheticChildren::Flags());
579   AddCXXSynthetic(
580       objc_category_sp,
581       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
582       "NSDictionary synthetic children", ConstString("CFMutableDictionaryRef"),
583       ScriptedSyntheticChildren::Flags());
584
585   AddCXXSynthetic(objc_category_sp,
586                   lldb_private::formatters::NSErrorSyntheticFrontEndCreator,
587                   "NSError synthetic children", ConstString("NSError"),
588                   ScriptedSyntheticChildren::Flags());
589   AddCXXSynthetic(objc_category_sp,
590                   lldb_private::formatters::NSExceptionSyntheticFrontEndCreator,
591                   "NSException synthetic children", ConstString("NSException"),
592                   ScriptedSyntheticChildren::Flags());
593
594   AddCXXSynthetic(objc_category_sp,
595                   lldb_private::formatters::NSSetSyntheticFrontEndCreator,
596                   "NSSet synthetic children", ConstString("NSSet"),
597                   ScriptedSyntheticChildren::Flags());
598   AddCXXSynthetic(objc_category_sp,
599                   lldb_private::formatters::NSSetSyntheticFrontEndCreator,
600                   "__NSSetI synthetic children", ConstString("__NSSetI"),
601                   ScriptedSyntheticChildren::Flags());
602   AddCXXSynthetic(objc_category_sp,
603                   lldb_private::formatters::NSSetSyntheticFrontEndCreator,
604                   "__NSSetM synthetic children", ConstString("__NSSetM"),
605                   ScriptedSyntheticChildren::Flags());
606   AddCXXSynthetic(
607       objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator,
608       "NSMutableSet synthetic children", ConstString("NSMutableSet"),
609       ScriptedSyntheticChildren::Flags());
610   AddCXXSynthetic(
611       objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator,
612       "NSOrderedSet synthetic children", ConstString("NSOrderedSet"),
613       ScriptedSyntheticChildren::Flags());
614   AddCXXSynthetic(
615       objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator,
616       "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"),
617       ScriptedSyntheticChildren::Flags());
618   AddCXXSynthetic(
619       objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator,
620       "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"),
621       ScriptedSyntheticChildren::Flags());
622
623   AddCXXSynthetic(objc_category_sp,
624                   lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator,
625                   "NSIndexPath synthetic children", ConstString("NSIndexPath"),
626                   ScriptedSyntheticChildren::Flags());
627
628   AddCXXSummary(
629       objc_category_sp, lldb_private::formatters::CFBagSummaryProvider,
630       "CFBag summary provider", ConstString("CFBagRef"), appkit_flags);
631   AddCXXSummary(objc_category_sp,
632                 lldb_private::formatters::CFBagSummaryProvider,
633                 "CFBag summary provider", ConstString("__CFBag"), appkit_flags);
634   AddCXXSummary(objc_category_sp,
635                 lldb_private::formatters::CFBagSummaryProvider,
636                 "CFBag summary provider", ConstString("const struct __CFBag"),
637                 appkit_flags);
638   AddCXXSummary(
639       objc_category_sp, lldb_private::formatters::CFBagSummaryProvider,
640       "CFBag summary provider", ConstString("CFMutableBagRef"), appkit_flags);
641
642   AddCXXSummary(objc_category_sp,
643                 lldb_private::formatters::CFBinaryHeapSummaryProvider,
644                 "CFBinaryHeap summary provider", ConstString("CFBinaryHeapRef"),
645                 appkit_flags);
646   AddCXXSummary(objc_category_sp,
647                 lldb_private::formatters::CFBinaryHeapSummaryProvider,
648                 "CFBinaryHeap summary provider", ConstString("__CFBinaryHeap"),
649                 appkit_flags);
650
651   AddCXXSummary(
652       objc_category_sp, lldb_private::formatters::NSStringSummaryProvider,
653       "NSString summary provider", ConstString("NSString"), appkit_flags);
654   AddCXXSummary(
655       objc_category_sp, lldb_private::formatters::NSStringSummaryProvider,
656       "NSString summary provider", ConstString("CFStringRef"), appkit_flags);
657   AddCXXSummary(
658       objc_category_sp, lldb_private::formatters::NSStringSummaryProvider,
659       "NSString summary provider", ConstString("__CFString"), appkit_flags);
660   AddCXXSummary(objc_category_sp,
661                 lldb_private::formatters::NSStringSummaryProvider,
662                 "NSString summary provider", ConstString("CFMutableStringRef"),
663                 appkit_flags);
664   AddCXXSummary(objc_category_sp,
665                 lldb_private::formatters::NSStringSummaryProvider,
666                 "NSString summary provider", ConstString("NSMutableString"),
667                 appkit_flags);
668   AddCXXSummary(objc_category_sp,
669                 lldb_private::formatters::NSStringSummaryProvider,
670                 "NSString summary provider",
671                 ConstString("__NSCFConstantString"), appkit_flags);
672   AddCXXSummary(
673       objc_category_sp, lldb_private::formatters::NSStringSummaryProvider,
674       "NSString summary provider", ConstString("__NSCFString"), appkit_flags);
675   AddCXXSummary(objc_category_sp,
676                 lldb_private::formatters::NSStringSummaryProvider,
677                 "NSString summary provider", ConstString("NSCFConstantString"),
678                 appkit_flags);
679   AddCXXSummary(
680       objc_category_sp, lldb_private::formatters::NSStringSummaryProvider,
681       "NSString summary provider", ConstString("NSCFString"), appkit_flags);
682   AddCXXSummary(
683       objc_category_sp, lldb_private::formatters::NSStringSummaryProvider,
684       "NSString summary provider", ConstString("NSPathStore2"), appkit_flags);
685   AddCXXSummary(objc_category_sp,
686                 lldb_private::formatters::NSStringSummaryProvider,
687                 "NSString summary provider",
688                 ConstString("NSTaggedPointerString"), appkit_flags);
689
690   AddCXXSummary(objc_category_sp,
691                 lldb_private::formatters::NSAttributedStringSummaryProvider,
692                 "NSAttributedString summary provider",
693                 ConstString("NSAttributedString"), appkit_flags);
694   AddCXXSummary(
695       objc_category_sp,
696       lldb_private::formatters::NSMutableAttributedStringSummaryProvider,
697       "NSMutableAttributedString summary provider",
698       ConstString("NSMutableAttributedString"), appkit_flags);
699   AddCXXSummary(
700       objc_category_sp,
701       lldb_private::formatters::NSMutableAttributedStringSummaryProvider,
702       "NSMutableAttributedString summary provider",
703       ConstString("NSConcreteMutableAttributedString"), appkit_flags);
704
705   AddCXXSummary(
706       objc_category_sp, lldb_private::formatters::NSBundleSummaryProvider,
707       "NSBundle summary provider", ConstString("NSBundle"), appkit_flags);
708
709   AddCXXSummary(objc_category_sp,
710                 lldb_private::formatters::NSDataSummaryProvider<false>,
711                 "NSData summary provider", ConstString("NSData"), appkit_flags);
712   AddCXXSummary(
713       objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>,
714       "NSData summary provider", ConstString("_NSInlineData"), appkit_flags);
715   AddCXXSummary(
716       objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>,
717       "NSData summary provider", ConstString("NSConcreteData"), appkit_flags);
718   AddCXXSummary(objc_category_sp,
719                 lldb_private::formatters::NSDataSummaryProvider<false>,
720                 "NSData summary provider", ConstString("NSConcreteMutableData"),
721                 appkit_flags);
722   AddCXXSummary(
723       objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>,
724       "NSData summary provider", ConstString("NSMutableData"), appkit_flags);
725   AddCXXSummary(
726       objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>,
727       "NSData summary provider", ConstString("__NSCFData"), appkit_flags);
728   AddCXXSummary(
729       objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>,
730       "NSData summary provider", ConstString("CFDataRef"), appkit_flags);
731   AddCXXSummary(
732       objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>,
733       "NSData summary provider", ConstString("CFMutableDataRef"), appkit_flags);
734
735   AddCXXSummary(
736       objc_category_sp, lldb_private::formatters::NSMachPortSummaryProvider,
737       "NSMachPort summary provider", ConstString("NSMachPort"), appkit_flags);
738
739   AddCXXSummary(objc_category_sp,
740                 lldb_private::formatters::NSNotificationSummaryProvider,
741                 "NSNotification summary provider",
742                 ConstString("NSNotification"), appkit_flags);
743   AddCXXSummary(objc_category_sp,
744                 lldb_private::formatters::NSNotificationSummaryProvider,
745                 "NSNotification summary provider",
746                 ConstString("NSConcreteNotification"), appkit_flags);
747
748   AddCXXSummary(
749       objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider,
750       "NSNumber summary provider", ConstString("NSNumber"), appkit_flags);
751   AddCXXSummary(
752       objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider,
753       "CFNumberRef summary provider", ConstString("CFNumberRef"), appkit_flags);
754   AddCXXSummary(
755       objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider,
756       "NSNumber summary provider", ConstString("__NSCFBoolean"), appkit_flags);
757   AddCXXSummary(
758       objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider,
759       "NSNumber summary provider", ConstString("__NSCFNumber"), appkit_flags);
760   AddCXXSummary(
761       objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider,
762       "NSNumber summary provider", ConstString("NSCFBoolean"), appkit_flags);
763   AddCXXSummary(
764       objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider,
765       "NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags);
766
767   AddCXXSummary(objc_category_sp,
768                 lldb_private::formatters::NSURLSummaryProvider,
769                 "NSURL summary provider", ConstString("NSURL"), appkit_flags);
770   AddCXXSummary(
771       objc_category_sp, lldb_private::formatters::NSURLSummaryProvider,
772       "NSURL summary provider", ConstString("CFURLRef"), appkit_flags);
773
774   AddCXXSummary(objc_category_sp,
775                 lldb_private::formatters::NSDateSummaryProvider,
776                 "NSDate summary provider", ConstString("NSDate"), appkit_flags);
777   AddCXXSummary(
778       objc_category_sp, lldb_private::formatters::NSDateSummaryProvider,
779       "NSDate summary provider", ConstString("__NSDate"), appkit_flags);
780   AddCXXSummary(
781       objc_category_sp, lldb_private::formatters::NSDateSummaryProvider,
782       "NSDate summary provider", ConstString("__NSTaggedDate"), appkit_flags);
783   AddCXXSummary(
784       objc_category_sp, lldb_private::formatters::NSDateSummaryProvider,
785       "NSDate summary provider", ConstString("NSCalendarDate"), appkit_flags);
786
787   AddCXXSummary(
788       objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider,
789       "NSTimeZone summary provider", ConstString("NSTimeZone"), appkit_flags);
790   AddCXXSummary(objc_category_sp,
791                 lldb_private::formatters::NSTimeZoneSummaryProvider,
792                 "NSTimeZone summary provider", ConstString("CFTimeZoneRef"),
793                 appkit_flags);
794   AddCXXSummary(
795       objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider,
796       "NSTimeZone summary provider", ConstString("__NSTimeZone"), appkit_flags);
797
798   // CFAbsoluteTime is actually a double rather than a pointer to an object we
799   // do not care about the numeric value, since it is probably meaningless to
800   // users
801   appkit_flags.SetDontShowValue(true);
802   AddCXXSummary(objc_category_sp,
803                 lldb_private::formatters::CFAbsoluteTimeSummaryProvider,
804                 "CFAbsoluteTime summary provider",
805                 ConstString("CFAbsoluteTime"), appkit_flags);
806   appkit_flags.SetDontShowValue(false);
807
808   AddCXXSummary(
809       objc_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider,
810       "NSIndexSet summary provider", ConstString("NSIndexSet"), appkit_flags);
811   AddCXXSummary(objc_category_sp,
812                 lldb_private::formatters::NSIndexSetSummaryProvider,
813                 "NSIndexSet summary provider", ConstString("NSMutableIndexSet"),
814                 appkit_flags);
815
816   AddStringSummary(objc_category_sp,
817                    "@\"${var.month%d}/${var.day%d}/${var.year%d} "
818                    "${var.hour%d}:${var.minute%d}:${var.second}\"",
819                    ConstString("CFGregorianDate"), appkit_flags);
820
821   AddCXXSummary(objc_category_sp,
822                 lldb_private::formatters::CFBitVectorSummaryProvider,
823                 "CFBitVector summary provider", ConstString("CFBitVectorRef"),
824                 appkit_flags);
825   AddCXXSummary(objc_category_sp,
826                 lldb_private::formatters::CFBitVectorSummaryProvider,
827                 "CFBitVector summary provider",
828                 ConstString("CFMutableBitVectorRef"), appkit_flags);
829   AddCXXSummary(objc_category_sp,
830                 lldb_private::formatters::CFBitVectorSummaryProvider,
831                 "CFBitVector summary provider", ConstString("__CFBitVector"),
832                 appkit_flags);
833   AddCXXSummary(objc_category_sp,
834                 lldb_private::formatters::CFBitVectorSummaryProvider,
835                 "CFBitVector summary provider",
836                 ConstString("__CFMutableBitVector"), appkit_flags);
837 #endif // LLDB_DISABLE_PYTHON
838 }
839
840 static void LoadCoreMediaFormatters(TypeCategoryImplSP objc_category_sp) {
841   if (!objc_category_sp)
842     return;
843
844   TypeSummaryImpl::Flags cm_flags;
845   cm_flags.SetCascades(true)
846       .SetDontShowChildren(false)
847       .SetDontShowValue(false)
848       .SetHideItemNames(false)
849       .SetShowMembersOneLiner(false)
850       .SetSkipPointers(false)
851       .SetSkipReferences(false);
852
853 #ifndef LLDB_DISABLE_PYTHON
854   AddCXXSummary(objc_category_sp,
855                 lldb_private::formatters::CMTimeSummaryProvider,
856                 "CMTime summary provider", ConstString("CMTime"), cm_flags);
857 #endif // LLDB_DISABLE_PYTHON
858 }
859
860 lldb::TypeCategoryImplSP ObjCLanguage::GetFormatters() {
861   static llvm::once_flag g_initialize;
862   static TypeCategoryImplSP g_category;
863
864   llvm::call_once(g_initialize, [this]() -> void {
865     DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
866     if (g_category) {
867       LoadCoreMediaFormatters(g_category);
868       LoadObjCFormatters(g_category);
869     }
870   });
871   return g_category;
872 }
873
874 std::vector<ConstString>
875 ObjCLanguage::GetPossibleFormattersMatches(ValueObject &valobj,
876                                            lldb::DynamicValueType use_dynamic) {
877   std::vector<ConstString> result;
878
879   if (use_dynamic == lldb::eNoDynamicValues)
880     return result;
881
882   CompilerType compiler_type(valobj.GetCompilerType());
883
884   const bool check_cpp = false;
885   const bool check_objc = true;
886   bool canBeObjCDynamic =
887       compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc);
888
889   if (canBeObjCDynamic) {
890     do {
891       lldb::ProcessSP process_sp = valobj.GetProcessSP();
892       if (!process_sp)
893         break;
894       ObjCLanguageRuntime *runtime = process_sp->GetObjCLanguageRuntime();
895       if (runtime == nullptr)
896         break;
897       ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp(
898           runtime->GetClassDescriptor(valobj));
899       if (!objc_class_sp)
900         break;
901       if (ConstString name = objc_class_sp->GetClassName())
902         result.push_back(name);
903     } while (false);
904   }
905
906   return result;
907 }
908
909 std::unique_ptr<Language::TypeScavenger> ObjCLanguage::GetTypeScavenger() {
910   class ObjCScavengerResult : public Language::TypeScavenger::Result {
911   public:
912     ObjCScavengerResult(CompilerType type)
913         : Language::TypeScavenger::Result(), m_compiler_type(type) {}
914
915     bool IsValid() override { return m_compiler_type.IsValid(); }
916
917     bool DumpToStream(Stream &stream, bool print_help_if_available) override {
918       if (IsValid()) {
919         m_compiler_type.DumpTypeDescription(&stream);
920         stream.EOL();
921         return true;
922       }
923       return false;
924     }
925
926   private:
927     CompilerType m_compiler_type;
928   };
929
930   class ObjCRuntimeScavenger : public Language::TypeScavenger {
931   protected:
932     bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
933                    ResultSet &results) override {
934       bool result = false;
935
936       Process *process = exe_scope->CalculateProcess().get();
937       if (process) {
938         const bool create_on_demand = false;
939         auto objc_runtime = process->GetObjCLanguageRuntime(create_on_demand);
940         if (objc_runtime) {
941           auto decl_vendor = objc_runtime->GetDeclVendor();
942           if (decl_vendor) {
943             std::vector<clang::NamedDecl *> decls;
944             ConstString name(key);
945             decl_vendor->FindDecls(name, true, UINT32_MAX, decls);
946             for (auto decl : decls) {
947               if (decl) {
948                 if (CompilerType candidate =
949                         ClangASTContext::GetTypeForDecl(decl)) {
950                   result = true;
951                   std::unique_ptr<Language::TypeScavenger::Result> result(
952                       new ObjCScavengerResult(candidate));
953                   results.insert(std::move(result));
954                 }
955               }
956             }
957           }
958         }
959       }
960
961       return result;
962     }
963
964     friend class lldb_private::ObjCLanguage;
965   };
966
967   class ObjCModulesScavenger : public Language::TypeScavenger {
968   protected:
969     bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
970                    ResultSet &results) override {
971       bool result = false;
972
973       Target *target = exe_scope->CalculateTarget().get();
974       if (target) {
975         if (auto clang_modules_decl_vendor =
976                 target->GetClangModulesDeclVendor()) {
977           std::vector<clang::NamedDecl *> decls;
978           ConstString key_cs(key);
979
980           if (clang_modules_decl_vendor->FindDecls(key_cs, false, UINT32_MAX,
981                                                    decls) > 0 &&
982               !decls.empty()) {
983             CompilerType module_type =
984                 ClangASTContext::GetTypeForDecl(decls.front());
985             result = true;
986             std::unique_ptr<Language::TypeScavenger::Result> result(
987                 new ObjCScavengerResult(module_type));
988             results.insert(std::move(result));
989           }
990         }
991       }
992
993       return result;
994     }
995
996     friend class lldb_private::ObjCLanguage;
997   };
998   
999   class ObjCDebugInfoScavenger : public Language::ImageListTypeScavenger {
1000   public:
1001     virtual CompilerType AdjustForInclusion(CompilerType &candidate) override {
1002       LanguageType lang_type(candidate.GetMinimumLanguage());
1003       if (!Language::LanguageIsObjC(lang_type))
1004         return CompilerType();
1005       if (candidate.IsTypedefType())
1006         return candidate.GetTypedefedType();
1007       return candidate;
1008     }
1009   };
1010
1011   return std::unique_ptr<TypeScavenger>(
1012       new Language::EitherTypeScavenger<ObjCModulesScavenger,
1013                                         ObjCRuntimeScavenger,
1014                                         ObjCDebugInfoScavenger>());
1015 }
1016
1017 bool ObjCLanguage::GetFormatterPrefixSuffix(ValueObject &valobj,
1018                                             ConstString type_hint,
1019                                             std::string &prefix,
1020                                             std::string &suffix) {
1021   static ConstString g_CFBag("CFBag");
1022   static ConstString g_CFBinaryHeap("CFBinaryHeap");
1023
1024   static ConstString g_NSNumberChar("NSNumber:char");
1025   static ConstString g_NSNumberShort("NSNumber:short");
1026   static ConstString g_NSNumberInt("NSNumber:int");
1027   static ConstString g_NSNumberLong("NSNumber:long");
1028   static ConstString g_NSNumberInt128("NSNumber:int128_t");
1029   static ConstString g_NSNumberFloat("NSNumber:float");
1030   static ConstString g_NSNumberDouble("NSNumber:double");
1031
1032   static ConstString g_NSData("NSData");
1033   static ConstString g_NSArray("NSArray");
1034   static ConstString g_NSString("NSString");
1035   static ConstString g_NSStringStar("NSString*");
1036
1037   if (type_hint.IsEmpty())
1038     return false;
1039
1040   prefix.clear();
1041   suffix.clear();
1042
1043   if (type_hint == g_CFBag || type_hint == g_CFBinaryHeap) {
1044     prefix = "@";
1045     return true;
1046   }
1047
1048   if (type_hint == g_NSNumberChar) {
1049     prefix = "(char)";
1050     return true;
1051   }
1052   if (type_hint == g_NSNumberShort) {
1053     prefix = "(short)";
1054     return true;
1055   }
1056   if (type_hint == g_NSNumberInt) {
1057     prefix = "(int)";
1058     return true;
1059   }
1060   if (type_hint == g_NSNumberLong) {
1061     prefix = "(long)";
1062     return true;
1063   }
1064   if (type_hint == g_NSNumberInt128) {
1065     prefix = "(int128_t)";
1066     return true;
1067   }
1068   if (type_hint == g_NSNumberFloat) {
1069     prefix = "(float)";
1070     return true;
1071   }
1072   if (type_hint == g_NSNumberDouble) {
1073     prefix = "(double)";
1074     return true;
1075   }
1076
1077   if (type_hint == g_NSData || type_hint == g_NSArray) {
1078     prefix = "@\"";
1079     suffix = "\"";
1080     return true;
1081   }
1082
1083   if (type_hint == g_NSString || type_hint == g_NSStringStar) {
1084     prefix = "@";
1085     return true;
1086   }
1087
1088   return false;
1089 }
1090
1091 bool ObjCLanguage::IsNilReference(ValueObject &valobj) {
1092   const uint32_t mask = eTypeIsObjC | eTypeIsPointer;
1093   bool isObjCpointer =
1094       (((valobj.GetCompilerType().GetTypeInfo(nullptr)) & mask) == mask);
1095   if (!isObjCpointer)
1096     return false;
1097   bool canReadValue = true;
1098   bool isZero = valobj.GetValueAsUnsigned(0, &canReadValue) == 0;
1099   return canReadValue && isZero;
1100 }