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