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