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