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