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