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