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