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<Language::MethodNameVariant>
229 ObjCLanguage::GetMethodNameVariants(ConstString method_name) const {
230   std::vector<Language::MethodNameVariant> variant_names;
231   ObjCLanguage::MethodName objc_method(method_name.GetCString(), false);
232   if (!objc_method.IsValid(false)) {
233     return variant_names;
234   }
235 
236   variant_names.emplace_back(objc_method.GetSelector(),
237                              lldb::eFunctionNameTypeSelector);
238 
239   const bool is_class_method =
240       objc_method.GetType() == MethodName::eTypeClassMethod;
241   const bool is_instance_method =
242       objc_method.GetType() == MethodName::eTypeInstanceMethod;
243   ConstString name_sans_category =
244       objc_method.GetFullNameWithoutCategory(/*empty_if_no_category*/ true);
245 
246   if (is_class_method || is_instance_method) {
247     if (name_sans_category)
248       variant_names.emplace_back(name_sans_category,
249                                  lldb::eFunctionNameTypeFull);
250   } else {
251     StreamString strm;
252 
253     strm.Printf("+%s", objc_method.GetFullName().GetCString());
254     variant_names.emplace_back(ConstString(strm.GetString()),
255                                lldb::eFunctionNameTypeFull);
256     strm.Clear();
257 
258     strm.Printf("-%s", objc_method.GetFullName().GetCString());
259     variant_names.emplace_back(ConstString(strm.GetString()),
260                                lldb::eFunctionNameTypeFull);
261     strm.Clear();
262 
263     if (name_sans_category) {
264       strm.Printf("+%s", name_sans_category.GetCString());
265       variant_names.emplace_back(ConstString(strm.GetString()),
266                                  lldb::eFunctionNameTypeFull);
267       strm.Clear();
268 
269       strm.Printf("-%s", name_sans_category.GetCString());
270       variant_names.emplace_back(ConstString(strm.GetString()),
271                                  lldb::eFunctionNameTypeFull);
272     }
273   }
274 
275   return variant_names;
276 }
277 
278 bool ObjCLanguage::SymbolNameFitsToLanguage(Mangled mangled) const {
279   ConstString demangled_name = mangled.GetDemangledName();
280   if (!demangled_name)
281     return false;
282   return ObjCLanguage::IsPossibleObjCMethodName(demangled_name.GetCString());
283 }
284 
285 static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
286   if (!objc_category_sp)
287     return;
288 
289   TypeSummaryImpl::Flags objc_flags;
290   objc_flags.SetCascades(false)
291       .SetSkipPointers(true)
292       .SetSkipReferences(true)
293       .SetDontShowChildren(true)
294       .SetDontShowValue(true)
295       .SetShowMembersOneLiner(false)
296       .SetHideItemNames(false);
297 
298   lldb::TypeSummaryImplSP ObjC_BOOL_summary(new CXXFunctionSummaryFormat(
299       objc_flags, lldb_private::formatters::ObjCBOOLSummaryProvider, ""));
300   objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL"),
301                                                      ObjC_BOOL_summary);
302   objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL &"),
303                                                      ObjC_BOOL_summary);
304   objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL *"),
305                                                      ObjC_BOOL_summary);
306 
307   // we need to skip pointers here since we are special casing a SEL* when
308   // retrieving its value
309   objc_flags.SetSkipPointers(true);
310   AddCXXSummary(objc_category_sp,
311                 lldb_private::formatters::ObjCSELSummaryProvider<false>,
312                 "SEL summary provider", ConstString("SEL"), objc_flags);
313   AddCXXSummary(
314       objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>,
315       "SEL summary provider", ConstString("struct objc_selector"), objc_flags);
316   AddCXXSummary(
317       objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>,
318       "SEL summary provider", ConstString("objc_selector"), objc_flags);
319   AddCXXSummary(
320       objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<true>,
321       "SEL summary provider", ConstString("objc_selector *"), objc_flags);
322   AddCXXSummary(objc_category_sp,
323                 lldb_private::formatters::ObjCSELSummaryProvider<true>,
324                 "SEL summary provider", ConstString("SEL *"), objc_flags);
325 
326   AddCXXSummary(objc_category_sp,
327                 lldb_private::formatters::ObjCClassSummaryProvider,
328                 "Class summary provider", ConstString("Class"), objc_flags);
329 
330   SyntheticChildren::Flags class_synth_flags;
331   class_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
332       false);
333 
334   AddCXXSynthetic(objc_category_sp,
335                   lldb_private::formatters::ObjCClassSyntheticFrontEndCreator,
336                   "Class synthetic children", ConstString("Class"),
337                   class_synth_flags);
338 
339   objc_flags.SetSkipPointers(false);
340   objc_flags.SetCascades(true);
341   objc_flags.SetSkipReferences(false);
342 
343   AddStringSummary(objc_category_sp, "${var.__FuncPtr%A}",
344                    ConstString("__block_literal_generic"), objc_flags);
345 
346   AddStringSummary(objc_category_sp, "${var.years} years, ${var.months} "
347                                      "months, ${var.days} days, ${var.hours} "
348                                      "hours, ${var.minutes} minutes "
349                                      "${var.seconds} seconds",
350                    ConstString("CFGregorianUnits"), objc_flags);
351   AddStringSummary(objc_category_sp,
352                    "location=${var.location} length=${var.length}",
353                    ConstString("CFRange"), objc_flags);
354 
355   AddStringSummary(objc_category_sp,
356                    "location=${var.location}, length=${var.length}",
357                    ConstString("NSRange"), objc_flags);
358   AddStringSummary(objc_category_sp, "(${var.origin}, ${var.size}), ...",
359                    ConstString("NSRectArray"), objc_flags);
360 
361   AddOneLineSummary(objc_category_sp, ConstString("NSPoint"), objc_flags);
362   AddOneLineSummary(objc_category_sp, ConstString("NSSize"), objc_flags);
363   AddOneLineSummary(objc_category_sp, ConstString("NSRect"), objc_flags);
364 
365   AddOneLineSummary(objc_category_sp, ConstString("CGSize"), objc_flags);
366   AddOneLineSummary(objc_category_sp, ConstString("CGPoint"), objc_flags);
367   AddOneLineSummary(objc_category_sp, ConstString("CGRect"), objc_flags);
368 
369   AddStringSummary(objc_category_sp,
370                    "red=${var.red} green=${var.green} blue=${var.blue}",
371                    ConstString("RGBColor"), objc_flags);
372   AddStringSummary(
373       objc_category_sp,
374       "(t=${var.top}, l=${var.left}, b=${var.bottom}, r=${var.right})",
375       ConstString("Rect"), objc_flags);
376   AddStringSummary(objc_category_sp, "{(v=${var.v}, h=${var.h})}",
377                    ConstString("Point"), objc_flags);
378   AddStringSummary(objc_category_sp,
379                    "${var.month}/${var.day}/${var.year}  ${var.hour} "
380                    ":${var.minute} :${var.second} dayOfWeek:${var.dayOfWeek}",
381                    ConstString("DateTimeRect *"), objc_flags);
382   AddStringSummary(objc_category_sp, "${var.ld.month}/${var.ld.day}/"
383                                      "${var.ld.year} ${var.ld.hour} "
384                                      ":${var.ld.minute} :${var.ld.second} "
385                                      "dayOfWeek:${var.ld.dayOfWeek}",
386                    ConstString("LongDateRect"), objc_flags);
387   AddStringSummary(objc_category_sp, "(x=${var.x}, y=${var.y})",
388                    ConstString("HIPoint"), objc_flags);
389   AddStringSummary(objc_category_sp, "origin=${var.origin} size=${var.size}",
390                    ConstString("HIRect"), objc_flags);
391 
392   TypeSummaryImpl::Flags appkit_flags;
393   appkit_flags.SetCascades(true)
394       .SetSkipPointers(false)
395       .SetSkipReferences(false)
396       .SetDontShowChildren(true)
397       .SetDontShowValue(false)
398       .SetShowMembersOneLiner(false)
399       .SetHideItemNames(false);
400 
401   appkit_flags.SetDontShowChildren(false);
402 
403   AddCXXSummary(
404       objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
405       "NSArray summary provider", ConstString("NSArray"), appkit_flags);
406   AddCXXSummary(
407       objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
408       "NSArray summary provider", ConstString("NSConstantArray"), appkit_flags);
409   AddCXXSummary(
410       objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
411       "NSArray summary provider", ConstString("NSMutableArray"), appkit_flags);
412   AddCXXSummary(
413       objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
414       "NSArray summary provider", ConstString("__NSArrayI"), appkit_flags);
415   AddCXXSummary(
416       objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
417       "NSArray summary provider", ConstString("__NSArray0"), appkit_flags);
418   AddCXXSummary(objc_category_sp,
419                 lldb_private::formatters::NSArraySummaryProvider,
420                 "NSArray summary provider",
421                 ConstString("__NSSingleObjectArrayI"), appkit_flags);
422   AddCXXSummary(
423       objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
424       "NSArray summary provider", ConstString("__NSArrayM"), appkit_flags);
425   AddCXXSummary(
426       objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
427       "NSArray summary provider", ConstString("__NSCFArray"), appkit_flags);
428   AddCXXSummary(
429       objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
430       "NSArray summary provider", ConstString("_NSCallStackArray"), appkit_flags);
431   AddCXXSummary(
432       objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
433       "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags);
434   AddCXXSummary(objc_category_sp,
435                 lldb_private::formatters::NSArraySummaryProvider,
436                 "NSArray summary provider", ConstString("CFMutableArrayRef"),
437                 appkit_flags);
438 
439   AddCXXSummary(objc_category_sp,
440                 lldb_private::formatters::NSDictionarySummaryProvider<false>,
441                 "NSDictionary summary provider", ConstString("NSDictionary"),
442                 appkit_flags);
443   AddCXXSummary(objc_category_sp,
444                 lldb_private::formatters::NSDictionarySummaryProvider<false>,
445                 "NSDictionary summary provider",
446                 ConstString("NSConstantDictionary"), appkit_flags);
447   AddCXXSummary(objc_category_sp,
448                 lldb_private::formatters::NSDictionarySummaryProvider<false>,
449                 "NSDictionary summary provider",
450                 ConstString("NSMutableDictionary"), appkit_flags);
451   AddCXXSummary(objc_category_sp,
452                 lldb_private::formatters::NSDictionarySummaryProvider<false>,
453                 "NSDictionary summary provider",
454                 ConstString("__NSCFDictionary"), appkit_flags);
455   AddCXXSummary(objc_category_sp,
456                 lldb_private::formatters::NSDictionarySummaryProvider<false>,
457                 "NSDictionary summary provider", ConstString("__NSDictionaryI"),
458                 appkit_flags);
459   AddCXXSummary(objc_category_sp,
460                 lldb_private::formatters::NSDictionarySummaryProvider<false>,
461                 "NSDictionary summary provider",
462                 ConstString("__NSSingleEntryDictionaryI"), appkit_flags);
463   AddCXXSummary(objc_category_sp,
464                 lldb_private::formatters::NSDictionarySummaryProvider<false>,
465                 "NSDictionary summary provider", ConstString("__NSDictionaryM"),
466                 appkit_flags);
467   AddCXXSummary(objc_category_sp,
468                 lldb_private::formatters::NSDictionarySummaryProvider<true>,
469                 "NSDictionary summary provider", ConstString("CFDictionaryRef"),
470                 appkit_flags);
471   AddCXXSummary(objc_category_sp,
472                 lldb_private::formatters::NSDictionarySummaryProvider<true>,
473                 "NSDictionary summary provider", ConstString("__CFDictionary"),
474                 appkit_flags);
475   AddCXXSummary(objc_category_sp,
476                 lldb_private::formatters::NSDictionarySummaryProvider<true>,
477                 "NSDictionary summary provider",
478                 ConstString("CFMutableDictionaryRef"), appkit_flags);
479 
480   AddCXXSummary(objc_category_sp,
481                 lldb_private::formatters::NSSetSummaryProvider<false>,
482                 "NSSet summary", ConstString("NSSet"), appkit_flags);
483   AddCXXSummary(
484       objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
485       "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
486   AddCXXSummary(objc_category_sp,
487                 lldb_private::formatters::NSSetSummaryProvider<true>,
488                 "CFSetRef summary", ConstString("CFSetRef"), appkit_flags);
489   AddCXXSummary(
490       objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>,
491       "CFMutableSetRef summary", ConstString("CFMutableSetRef"), appkit_flags);
492   AddCXXSummary(objc_category_sp,
493                 lldb_private::formatters::NSSetSummaryProvider<false>,
494                 "__NSCFSet summary", ConstString("__NSCFSet"), appkit_flags);
495   AddCXXSummary(objc_category_sp,
496                 lldb_private::formatters::NSSetSummaryProvider<false>,
497                 "__CFSet summary", ConstString("__CFSet"), appkit_flags);
498   AddCXXSummary(objc_category_sp,
499                 lldb_private::formatters::NSSetSummaryProvider<false>,
500                 "__NSSetI summary", ConstString("__NSSetI"), appkit_flags);
501   AddCXXSummary(objc_category_sp,
502                 lldb_private::formatters::NSSetSummaryProvider<false>,
503                 "__NSSetM summary", ConstString("__NSSetM"), appkit_flags);
504   AddCXXSummary(
505       objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
506       "NSCountedSet summary", ConstString("NSCountedSet"), appkit_flags);
507   AddCXXSummary(
508       objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
509       "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
510   AddCXXSummary(
511       objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
512       "NSOrderedSet summary", ConstString("NSOrderedSet"), appkit_flags);
513   AddCXXSummary(
514       objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
515       "__NSOrderedSetI summary", ConstString("__NSOrderedSetI"), appkit_flags);
516   AddCXXSummary(
517       objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
518       "__NSOrderedSetM summary", ConstString("__NSOrderedSetM"), appkit_flags);
519 
520   AddCXXSummary(
521       objc_category_sp, lldb_private::formatters::NSError_SummaryProvider,
522       "NSError summary provider", ConstString("NSError"), appkit_flags);
523   AddCXXSummary(
524       objc_category_sp, lldb_private::formatters::NSException_SummaryProvider,
525       "NSException summary provider", ConstString("NSException"), appkit_flags);
526 
527   // AddSummary(appkit_category_sp, "${var.key%@} -> ${var.value%@}",
528   // ConstString("$_lldb_typegen_nspair"), appkit_flags);
529 
530   appkit_flags.SetDontShowChildren(true);
531 
532   AddCXXSynthetic(objc_category_sp,
533                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
534                   "NSArray synthetic children", ConstString("__NSArrayM"),
535                   ScriptedSyntheticChildren::Flags());
536   AddCXXSynthetic(objc_category_sp,
537                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
538                   "NSArray synthetic children", ConstString("__NSArrayI"),
539                   ScriptedSyntheticChildren::Flags());
540   AddCXXSynthetic(objc_category_sp,
541                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
542                   "NSArray synthetic children", ConstString("__NSArray0"),
543                   ScriptedSyntheticChildren::Flags());
544   AddCXXSynthetic(objc_category_sp,
545                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
546                   "NSArray synthetic children",
547                   ConstString("__NSSingleObjectArrayI"),
548                   ScriptedSyntheticChildren::Flags());
549   AddCXXSynthetic(objc_category_sp,
550                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
551                   "NSArray synthetic children", ConstString("NSArray"),
552                   ScriptedSyntheticChildren::Flags());
553   AddCXXSynthetic(objc_category_sp,
554                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
555                   "NSArray synthetic children", ConstString("NSConstantArray"),
556                   ScriptedSyntheticChildren::Flags());
557   AddCXXSynthetic(objc_category_sp,
558                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
559                   "NSArray synthetic children", ConstString("NSMutableArray"),
560                   ScriptedSyntheticChildren::Flags());
561   AddCXXSynthetic(objc_category_sp,
562                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
563                   "NSArray synthetic children", ConstString("__NSCFArray"),
564                   ScriptedSyntheticChildren::Flags());
565   AddCXXSynthetic(objc_category_sp,
566                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
567                   "NSArray synthetic children", ConstString("_NSCallStackArray"),
568                   ScriptedSyntheticChildren::Flags());
569   AddCXXSynthetic(objc_category_sp,
570                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
571                   "NSArray synthetic children",
572                   ConstString("CFMutableArrayRef"),
573                   ScriptedSyntheticChildren::Flags());
574   AddCXXSynthetic(objc_category_sp,
575                   lldb_private::formatters::NSArraySyntheticFrontEndCreator,
576                   "NSArray synthetic children", ConstString("CFArrayRef"),
577                   ScriptedSyntheticChildren::Flags());
578 
579   AddCXXSynthetic(
580       objc_category_sp,
581       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
582       "NSDictionary synthetic children", ConstString("__NSDictionaryM"),
583       ScriptedSyntheticChildren::Flags());
584   AddCXXSynthetic(
585       objc_category_sp,
586       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
587       "NSDictionary synthetic children", ConstString("NSConstantDictionary"),
588       ScriptedSyntheticChildren::Flags());
589   AddCXXSynthetic(
590       objc_category_sp,
591       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
592       "NSDictionary synthetic children", ConstString("__NSDictionaryI"),
593       ScriptedSyntheticChildren::Flags());
594   AddCXXSynthetic(
595       objc_category_sp,
596       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
597       "NSDictionary synthetic children",
598       ConstString("__NSSingleEntryDictionaryI"),
599       ScriptedSyntheticChildren::Flags());
600   AddCXXSynthetic(
601       objc_category_sp,
602       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
603       "NSDictionary synthetic children", ConstString("__NSCFDictionary"),
604       ScriptedSyntheticChildren::Flags());
605   AddCXXSynthetic(
606       objc_category_sp,
607       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
608       "NSDictionary synthetic children", ConstString("NSDictionary"),
609       ScriptedSyntheticChildren::Flags());
610   AddCXXSynthetic(
611       objc_category_sp,
612       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
613       "NSDictionary synthetic children", ConstString("NSMutableDictionary"),
614       ScriptedSyntheticChildren::Flags());
615   AddCXXSynthetic(
616       objc_category_sp,
617       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
618       "NSDictionary synthetic children", ConstString("CFDictionaryRef"),
619       ScriptedSyntheticChildren::Flags());
620   AddCXXSynthetic(
621       objc_category_sp,
622       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
623       "NSDictionary synthetic children", ConstString("CFMutableDictionaryRef"),
624       ScriptedSyntheticChildren::Flags());
625   AddCXXSynthetic(
626       objc_category_sp,
627       lldb_private::formatters::NSDictionarySyntheticFrontEndCreator,
628       "NSDictionary synthetic children", ConstString("__CFDictionary"),
629       ScriptedSyntheticChildren::Flags());
630 
631   AddCXXSynthetic(objc_category_sp,
632                   lldb_private::formatters::NSErrorSyntheticFrontEndCreator,
633                   "NSError synthetic children", ConstString("NSError"),
634                   ScriptedSyntheticChildren::Flags());
635   AddCXXSynthetic(objc_category_sp,
636                   lldb_private::formatters::NSExceptionSyntheticFrontEndCreator,
637                   "NSException synthetic children", ConstString("NSException"),
638                   ScriptedSyntheticChildren::Flags());
639 
640   AddCXXSynthetic(objc_category_sp,
641                   lldb_private::formatters::NSSetSyntheticFrontEndCreator,
642                   "NSSet synthetic children", ConstString("NSSet"),
643                   ScriptedSyntheticChildren::Flags());
644   AddCXXSynthetic(objc_category_sp,
645                   lldb_private::formatters::NSSetSyntheticFrontEndCreator,
646                   "__NSSetI synthetic children", ConstString("__NSSetI"),
647                   ScriptedSyntheticChildren::Flags());
648   AddCXXSynthetic(objc_category_sp,
649                   lldb_private::formatters::NSSetSyntheticFrontEndCreator,
650                   "__NSSetM synthetic children", ConstString("__NSSetM"),
651                   ScriptedSyntheticChildren::Flags());
652   AddCXXSynthetic(objc_category_sp,
653                   lldb_private::formatters::NSSetSyntheticFrontEndCreator,
654                   "__NSCFSet synthetic children", ConstString("__NSCFSet"),
655                   ScriptedSyntheticChildren::Flags());
656   AddCXXSynthetic(objc_category_sp,
657                   lldb_private::formatters::NSSetSyntheticFrontEndCreator,
658                   "CFSetRef synthetic children", ConstString("CFSetRef"),
659                   ScriptedSyntheticChildren::Flags());
660 
661   AddCXXSynthetic(
662       objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator,
663       "NSMutableSet synthetic children", ConstString("NSMutableSet"),
664       ScriptedSyntheticChildren::Flags());
665   AddCXXSynthetic(
666       objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator,
667       "NSOrderedSet synthetic children", ConstString("NSOrderedSet"),
668       ScriptedSyntheticChildren::Flags());
669   AddCXXSynthetic(
670       objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator,
671       "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"),
672       ScriptedSyntheticChildren::Flags());
673   AddCXXSynthetic(
674       objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator,
675       "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"),
676       ScriptedSyntheticChildren::Flags());
677   AddCXXSynthetic(objc_category_sp,
678                   lldb_private::formatters::NSSetSyntheticFrontEndCreator,
679                   "__CFSet synthetic children", ConstString("__CFSet"),
680                   ScriptedSyntheticChildren::Flags());
681 
682   AddCXXSynthetic(objc_category_sp,
683                   lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator,
684                   "NSIndexPath synthetic children", ConstString("NSIndexPath"),
685                   ScriptedSyntheticChildren::Flags());
686 
687   AddCXXSummary(
688       objc_category_sp, lldb_private::formatters::CFBagSummaryProvider,
689       "CFBag summary provider", ConstString("CFBagRef"), appkit_flags);
690   AddCXXSummary(objc_category_sp,
691                 lldb_private::formatters::CFBagSummaryProvider,
692                 "CFBag summary provider", ConstString("__CFBag"), appkit_flags);
693   AddCXXSummary(objc_category_sp,
694                 lldb_private::formatters::CFBagSummaryProvider,
695                 "CFBag summary provider", ConstString("const struct __CFBag"),
696                 appkit_flags);
697   AddCXXSummary(
698       objc_category_sp, lldb_private::formatters::CFBagSummaryProvider,
699       "CFBag summary provider", ConstString("CFMutableBagRef"), appkit_flags);
700 
701   AddCXXSummary(objc_category_sp,
702                 lldb_private::formatters::CFBinaryHeapSummaryProvider,
703                 "CFBinaryHeap summary provider", ConstString("CFBinaryHeapRef"),
704                 appkit_flags);
705   AddCXXSummary(objc_category_sp,
706                 lldb_private::formatters::CFBinaryHeapSummaryProvider,
707                 "CFBinaryHeap summary provider", ConstString("__CFBinaryHeap"),
708                 appkit_flags);
709 
710   AddCXXSummary(
711       objc_category_sp, lldb_private::formatters::NSStringSummaryProvider,
712       "NSString summary provider", ConstString("NSString"), appkit_flags);
713   AddCXXSummary(
714       objc_category_sp, lldb_private::formatters::NSStringSummaryProvider,
715       "NSString summary provider", ConstString("CFStringRef"), appkit_flags);
716   AddCXXSummary(
717       objc_category_sp, lldb_private::formatters::NSStringSummaryProvider,
718       "NSString summary provider", ConstString("__CFString"), appkit_flags);
719   AddCXXSummary(objc_category_sp,
720                 lldb_private::formatters::NSStringSummaryProvider,
721                 "NSString summary provider", ConstString("CFMutableStringRef"),
722                 appkit_flags);
723   AddCXXSummary(objc_category_sp,
724                 lldb_private::formatters::NSStringSummaryProvider,
725                 "NSString summary provider", ConstString("NSMutableString"),
726                 appkit_flags);
727   AddCXXSummary(objc_category_sp,
728                 lldb_private::formatters::NSStringSummaryProvider,
729                 "NSString summary provider",
730                 ConstString("__NSCFConstantString"), appkit_flags);
731   AddCXXSummary(
732       objc_category_sp, lldb_private::formatters::NSStringSummaryProvider,
733       "NSString summary provider", ConstString("__NSCFString"), appkit_flags);
734   AddCXXSummary(objc_category_sp,
735                 lldb_private::formatters::NSStringSummaryProvider,
736                 "NSString summary provider", ConstString("NSCFConstantString"),
737                 appkit_flags);
738   AddCXXSummary(
739       objc_category_sp, lldb_private::formatters::NSStringSummaryProvider,
740       "NSString summary provider", ConstString("NSCFString"), appkit_flags);
741   AddCXXSummary(
742       objc_category_sp, lldb_private::formatters::NSStringSummaryProvider,
743       "NSString summary provider", ConstString("NSPathStore2"), appkit_flags);
744   AddCXXSummary(objc_category_sp,
745                 lldb_private::formatters::NSStringSummaryProvider,
746                 "NSString summary provider",
747                 ConstString("NSTaggedPointerString"), appkit_flags);
748 
749   AddCXXSummary(objc_category_sp,
750                 lldb_private::formatters::NSAttributedStringSummaryProvider,
751                 "NSAttributedString summary provider",
752                 ConstString("NSAttributedString"), appkit_flags);
753   AddCXXSummary(
754       objc_category_sp,
755       lldb_private::formatters::NSMutableAttributedStringSummaryProvider,
756       "NSMutableAttributedString summary provider",
757       ConstString("NSMutableAttributedString"), appkit_flags);
758   AddCXXSummary(
759       objc_category_sp,
760       lldb_private::formatters::NSMutableAttributedStringSummaryProvider,
761       "NSMutableAttributedString summary provider",
762       ConstString("NSConcreteMutableAttributedString"), appkit_flags);
763 
764   AddCXXSummary(
765       objc_category_sp, lldb_private::formatters::NSBundleSummaryProvider,
766       "NSBundle summary provider", ConstString("NSBundle"), appkit_flags);
767 
768   AddCXXSummary(objc_category_sp,
769                 lldb_private::formatters::NSDataSummaryProvider<false>,
770                 "NSData summary provider", ConstString("NSData"), appkit_flags);
771   AddCXXSummary(
772       objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>,
773       "NSData summary provider", ConstString("_NSInlineData"), appkit_flags);
774   AddCXXSummary(
775       objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>,
776       "NSData summary provider", ConstString("NSConcreteData"), appkit_flags);
777   AddCXXSummary(objc_category_sp,
778                 lldb_private::formatters::NSDataSummaryProvider<false>,
779                 "NSData summary provider", ConstString("NSConcreteMutableData"),
780                 appkit_flags);
781   AddCXXSummary(
782       objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>,
783       "NSData summary provider", ConstString("NSMutableData"), appkit_flags);
784   AddCXXSummary(
785       objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>,
786       "NSData summary provider", ConstString("__NSCFData"), appkit_flags);
787   AddCXXSummary(
788       objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>,
789       "NSData summary provider", ConstString("CFDataRef"), appkit_flags);
790   AddCXXSummary(
791       objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>,
792       "NSData summary provider", ConstString("CFMutableDataRef"), appkit_flags);
793 
794   AddCXXSummary(
795       objc_category_sp, lldb_private::formatters::NSMachPortSummaryProvider,
796       "NSMachPort summary provider", ConstString("NSMachPort"), appkit_flags);
797 
798   AddCXXSummary(objc_category_sp,
799                 lldb_private::formatters::NSNotificationSummaryProvider,
800                 "NSNotification summary provider",
801                 ConstString("NSNotification"), appkit_flags);
802   AddCXXSummary(objc_category_sp,
803                 lldb_private::formatters::NSNotificationSummaryProvider,
804                 "NSNotification summary provider",
805                 ConstString("NSConcreteNotification"), appkit_flags);
806 
807   AddCXXSummary(
808       objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider,
809       "NSNumber summary provider", ConstString("NSNumber"), appkit_flags);
810   AddCXXSummary(objc_category_sp,
811                 lldb_private::formatters::NSNumberSummaryProvider,
812                 "NSNumber summary provider",
813                 ConstString("NSConstantIntegerNumber"), appkit_flags);
814   AddCXXSummary(objc_category_sp,
815                 lldb_private::formatters::NSNumberSummaryProvider,
816                 "NSNumber summary provider",
817                 ConstString("NSConstantDoubleNumber"), appkit_flags);
818   AddCXXSummary(objc_category_sp,
819                 lldb_private::formatters::NSNumberSummaryProvider,
820                 "NSNumber summary provider",
821                 ConstString("NSConstantFloatNumber"), appkit_flags);
822   AddCXXSummary(
823       objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider,
824       "CFNumberRef summary provider", ConstString("CFNumberRef"), appkit_flags);
825   AddCXXSummary(
826       objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider,
827       "NSNumber summary provider", ConstString("__NSCFBoolean"), appkit_flags);
828   AddCXXSummary(
829       objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider,
830       "NSNumber summary provider", ConstString("__NSCFNumber"), appkit_flags);
831   AddCXXSummary(
832       objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider,
833       "NSNumber summary provider", ConstString("NSCFBoolean"), appkit_flags);
834   AddCXXSummary(
835       objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider,
836       "NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags);
837   AddCXXSummary(objc_category_sp,
838                 lldb_private::formatters::NSNumberSummaryProvider,
839                 "NSDecimalNumber summary provider",
840                 ConstString("NSDecimalNumber"), appkit_flags);
841 
842   AddCXXSummary(objc_category_sp,
843                 lldb_private::formatters::NSURLSummaryProvider,
844                 "NSURL summary provider", ConstString("NSURL"), appkit_flags);
845   AddCXXSummary(
846       objc_category_sp, lldb_private::formatters::NSURLSummaryProvider,
847       "NSURL summary provider", ConstString("CFURLRef"), appkit_flags);
848 
849   AddCXXSummary(objc_category_sp,
850                 lldb_private::formatters::NSDateSummaryProvider,
851                 "NSDate summary provider", ConstString("NSDate"), appkit_flags);
852   AddCXXSummary(
853       objc_category_sp, lldb_private::formatters::NSDateSummaryProvider,
854       "NSDate summary provider", ConstString("__NSDate"), appkit_flags);
855   AddCXXSummary(
856       objc_category_sp, lldb_private::formatters::NSDateSummaryProvider,
857       "NSDate summary provider", ConstString("__NSTaggedDate"), appkit_flags);
858   AddCXXSummary(
859       objc_category_sp, lldb_private::formatters::NSDateSummaryProvider,
860       "NSDate summary provider", ConstString("NSCalendarDate"), appkit_flags);
861 
862   AddCXXSummary(
863       objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider,
864       "NSTimeZone summary provider", ConstString("NSTimeZone"), appkit_flags);
865   AddCXXSummary(objc_category_sp,
866                 lldb_private::formatters::NSTimeZoneSummaryProvider,
867                 "NSTimeZone summary provider", ConstString("CFTimeZoneRef"),
868                 appkit_flags);
869   AddCXXSummary(
870       objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider,
871       "NSTimeZone summary provider", ConstString("__NSTimeZone"), appkit_flags);
872 
873   // CFAbsoluteTime is actually a double rather than a pointer to an object we
874   // do not care about the numeric value, since it is probably meaningless to
875   // users
876   appkit_flags.SetDontShowValue(true);
877   AddCXXSummary(objc_category_sp,
878                 lldb_private::formatters::CFAbsoluteTimeSummaryProvider,
879                 "CFAbsoluteTime summary provider",
880                 ConstString("CFAbsoluteTime"), appkit_flags);
881   appkit_flags.SetDontShowValue(false);
882 
883   AddCXXSummary(
884       objc_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider,
885       "NSIndexSet summary provider", ConstString("NSIndexSet"), appkit_flags);
886   AddCXXSummary(objc_category_sp,
887                 lldb_private::formatters::NSIndexSetSummaryProvider,
888                 "NSIndexSet summary provider", ConstString("NSMutableIndexSet"),
889                 appkit_flags);
890 
891   AddStringSummary(objc_category_sp,
892                    "@\"${var.month%d}/${var.day%d}/${var.year%d} "
893                    "${var.hour%d}:${var.minute%d}:${var.second}\"",
894                    ConstString("CFGregorianDate"), appkit_flags);
895 
896   AddCXXSummary(objc_category_sp,
897                 lldb_private::formatters::CFBitVectorSummaryProvider,
898                 "CFBitVector summary provider", ConstString("CFBitVectorRef"),
899                 appkit_flags);
900   AddCXXSummary(objc_category_sp,
901                 lldb_private::formatters::CFBitVectorSummaryProvider,
902                 "CFBitVector summary provider",
903                 ConstString("CFMutableBitVectorRef"), appkit_flags);
904   AddCXXSummary(objc_category_sp,
905                 lldb_private::formatters::CFBitVectorSummaryProvider,
906                 "CFBitVector summary provider", ConstString("__CFBitVector"),
907                 appkit_flags);
908   AddCXXSummary(objc_category_sp,
909                 lldb_private::formatters::CFBitVectorSummaryProvider,
910                 "CFBitVector summary provider",
911                 ConstString("__CFMutableBitVector"), appkit_flags);
912 }
913 
914 static void LoadCoreMediaFormatters(TypeCategoryImplSP objc_category_sp) {
915   if (!objc_category_sp)
916     return;
917 
918   TypeSummaryImpl::Flags cm_flags;
919   cm_flags.SetCascades(true)
920       .SetDontShowChildren(false)
921       .SetDontShowValue(false)
922       .SetHideItemNames(false)
923       .SetShowMembersOneLiner(false)
924       .SetSkipPointers(false)
925       .SetSkipReferences(false);
926 
927   AddCXXSummary(objc_category_sp,
928                 lldb_private::formatters::CMTimeSummaryProvider,
929                 "CMTime summary provider", ConstString("CMTime"), cm_flags);
930 }
931 
932 lldb::TypeCategoryImplSP ObjCLanguage::GetFormatters() {
933   static llvm::once_flag g_initialize;
934   static TypeCategoryImplSP g_category;
935 
936   llvm::call_once(g_initialize, [this]() -> void {
937     DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
938     if (g_category) {
939       LoadCoreMediaFormatters(g_category);
940       LoadObjCFormatters(g_category);
941     }
942   });
943   return g_category;
944 }
945 
946 std::vector<ConstString>
947 ObjCLanguage::GetPossibleFormattersMatches(ValueObject &valobj,
948                                            lldb::DynamicValueType use_dynamic) {
949   std::vector<ConstString> result;
950 
951   if (use_dynamic == lldb::eNoDynamicValues)
952     return result;
953 
954   CompilerType compiler_type(valobj.GetCompilerType());
955 
956   const bool check_cpp = false;
957   const bool check_objc = true;
958   bool canBeObjCDynamic =
959       compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc);
960 
961   if (canBeObjCDynamic && ClangUtil::IsClangType(compiler_type)) {
962     do {
963       lldb::ProcessSP process_sp = valobj.GetProcessSP();
964       if (!process_sp)
965         break;
966       ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
967       if (runtime == nullptr)
968         break;
969       ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp(
970           runtime->GetClassDescriptor(valobj));
971       if (!objc_class_sp)
972         break;
973       if (ConstString name = objc_class_sp->GetClassName())
974         result.push_back(name);
975     } while (false);
976   }
977 
978   return result;
979 }
980 
981 std::unique_ptr<Language::TypeScavenger> ObjCLanguage::GetTypeScavenger() {
982   class ObjCScavengerResult : public Language::TypeScavenger::Result {
983   public:
984     ObjCScavengerResult(CompilerType type)
985         : Language::TypeScavenger::Result(), m_compiler_type(type) {}
986 
987     bool IsValid() override { return m_compiler_type.IsValid(); }
988 
989     bool DumpToStream(Stream &stream, bool print_help_if_available) override {
990       if (IsValid()) {
991         m_compiler_type.DumpTypeDescription(&stream);
992         stream.EOL();
993         return true;
994       }
995       return false;
996     }
997 
998   private:
999     CompilerType m_compiler_type;
1000   };
1001 
1002   class ObjCRuntimeScavenger : public Language::TypeScavenger {
1003   protected:
1004     bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
1005                    ResultSet &results) override {
1006       bool result = false;
1007 
1008       if (auto *process = exe_scope->CalculateProcess().get()) {
1009         if (auto *objc_runtime = ObjCLanguageRuntime::Get(*process)) {
1010           if (auto *decl_vendor = objc_runtime->GetDeclVendor()) {
1011             ConstString name(key);
1012             for (const CompilerType &type :
1013                  decl_vendor->FindTypes(name, /*max_matches*/ UINT32_MAX)) {
1014               result = true;
1015               std::unique_ptr<Language::TypeScavenger::Result> result(
1016                   new ObjCScavengerResult(type));
1017               results.insert(std::move(result));
1018             }
1019           }
1020         }
1021       }
1022 
1023       return result;
1024     }
1025 
1026     friend class lldb_private::ObjCLanguage;
1027   };
1028 
1029   class ObjCModulesScavenger : public Language::TypeScavenger {
1030   protected:
1031     bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
1032                    ResultSet &results) override {
1033       bool result = false;
1034 
1035       if (auto *target = exe_scope->CalculateTarget().get()) {
1036         auto *persistent_vars = llvm::cast<ClangPersistentVariables>(
1037             target->GetPersistentExpressionStateForLanguage(
1038                 lldb::eLanguageTypeC));
1039         if (std::shared_ptr<ClangModulesDeclVendor> clang_modules_decl_vendor =
1040                 persistent_vars->GetClangModulesDeclVendor()) {
1041           ConstString key_cs(key);
1042           auto types = clang_modules_decl_vendor->FindTypes(
1043               key_cs, /*max_matches*/ UINT32_MAX);
1044           if (!types.empty()) {
1045             result = true;
1046             std::unique_ptr<Language::TypeScavenger::Result> result(
1047                 new ObjCScavengerResult(types.front()));
1048             results.insert(std::move(result));
1049           }
1050         }
1051       }
1052 
1053       return result;
1054     }
1055 
1056     friend class lldb_private::ObjCLanguage;
1057   };
1058 
1059   class ObjCDebugInfoScavenger : public Language::ImageListTypeScavenger {
1060   public:
1061     CompilerType AdjustForInclusion(CompilerType &candidate) override {
1062       LanguageType lang_type(candidate.GetMinimumLanguage());
1063       if (!Language::LanguageIsObjC(lang_type))
1064         return CompilerType();
1065       if (candidate.IsTypedefType())
1066         return candidate.GetTypedefedType();
1067       return candidate;
1068     }
1069   };
1070 
1071   return std::unique_ptr<TypeScavenger>(
1072       new Language::EitherTypeScavenger<ObjCModulesScavenger,
1073                                         ObjCRuntimeScavenger,
1074                                         ObjCDebugInfoScavenger>());
1075 }
1076 
1077 bool ObjCLanguage::GetFormatterPrefixSuffix(ValueObject &valobj,
1078                                             ConstString type_hint,
1079                                             std::string &prefix,
1080                                             std::string &suffix) {
1081   static ConstString g_CFBag("CFBag");
1082   static ConstString g_CFBinaryHeap("CFBinaryHeap");
1083 
1084   static ConstString g_NSNumberChar("NSNumber:char");
1085   static ConstString g_NSNumberShort("NSNumber:short");
1086   static ConstString g_NSNumberInt("NSNumber:int");
1087   static ConstString g_NSNumberLong("NSNumber:long");
1088   static ConstString g_NSNumberInt128("NSNumber:int128_t");
1089   static ConstString g_NSNumberFloat("NSNumber:float");
1090   static ConstString g_NSNumberDouble("NSNumber:double");
1091 
1092   static ConstString g_NSData("NSData");
1093   static ConstString g_NSArray("NSArray");
1094   static ConstString g_NSString("NSString");
1095   static ConstString g_NSStringStar("NSString*");
1096 
1097   if (type_hint.IsEmpty())
1098     return false;
1099 
1100   prefix.clear();
1101   suffix.clear();
1102 
1103   if (type_hint == g_CFBag || type_hint == g_CFBinaryHeap) {
1104     prefix = "@";
1105     return true;
1106   }
1107 
1108   if (type_hint == g_NSNumberChar) {
1109     prefix = "(char)";
1110     return true;
1111   }
1112   if (type_hint == g_NSNumberShort) {
1113     prefix = "(short)";
1114     return true;
1115   }
1116   if (type_hint == g_NSNumberInt) {
1117     prefix = "(int)";
1118     return true;
1119   }
1120   if (type_hint == g_NSNumberLong) {
1121     prefix = "(long)";
1122     return true;
1123   }
1124   if (type_hint == g_NSNumberInt128) {
1125     prefix = "(int128_t)";
1126     return true;
1127   }
1128   if (type_hint == g_NSNumberFloat) {
1129     prefix = "(float)";
1130     return true;
1131   }
1132   if (type_hint == g_NSNumberDouble) {
1133     prefix = "(double)";
1134     return true;
1135   }
1136 
1137   if (type_hint == g_NSData || type_hint == g_NSArray) {
1138     prefix = "@\"";
1139     suffix = "\"";
1140     return true;
1141   }
1142 
1143   if (type_hint == g_NSString || type_hint == g_NSStringStar) {
1144     prefix = "@";
1145     return true;
1146   }
1147 
1148   return false;
1149 }
1150 
1151 bool ObjCLanguage::IsNilReference(ValueObject &valobj) {
1152   const uint32_t mask = eTypeIsObjC | eTypeIsPointer;
1153   bool isObjCpointer =
1154       (((valobj.GetCompilerType().GetTypeInfo(nullptr)) & mask) == mask);
1155   if (!isObjCpointer)
1156     return false;
1157   bool canReadValue = true;
1158   bool isZero = valobj.GetValueAsUnsigned(0, &canReadValue) == 0;
1159   return canReadValue && isZero;
1160 }
1161 
1162 bool ObjCLanguage::IsSourceFile(llvm::StringRef file_path) const {
1163   const auto suffixes = {".h", ".m", ".M"};
1164   for (auto suffix : suffixes) {
1165     if (file_path.endswith_insensitive(suffix))
1166       return true;
1167   }
1168   return false;
1169 }
1170