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