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