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