1 //===-- CPlusPlusLanguage.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 "CPlusPlusLanguage.h"
10 
11 #include <cctype>
12 #include <cstring>
13 
14 #include <functional>
15 #include <memory>
16 #include <mutex>
17 #include <set>
18 
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/Demangle/ItaniumDemangle.h"
21 
22 #include "lldb/Core/Mangled.h"
23 #include "lldb/Core/PluginManager.h"
24 #include "lldb/Core/UniqueCStringMap.h"
25 #include "lldb/DataFormatters/CXXFunctionPointer.h"
26 #include "lldb/DataFormatters/DataVisualization.h"
27 #include "lldb/DataFormatters/FormattersHelpers.h"
28 #include "lldb/DataFormatters/VectorType.h"
29 #include "lldb/Utility/ConstString.h"
30 #include "lldb/Utility/Log.h"
31 #include "lldb/Utility/RegularExpression.h"
32 
33 #include "BlockPointer.h"
34 #include "CPlusPlusNameParser.h"
35 #include "CxxStringTypes.h"
36 #include "LibCxx.h"
37 #include "LibCxxAtomic.h"
38 #include "LibCxxVariant.h"
39 #include "LibStdcpp.h"
40 #include "MSVCUndecoratedNameParser.h"
41 
42 using namespace lldb;
43 using namespace lldb_private;
44 using namespace lldb_private::formatters;
45 
46 LLDB_PLUGIN_DEFINE(CPlusPlusLanguage)
47 
48 void CPlusPlusLanguage::Initialize() {
49   PluginManager::RegisterPlugin(GetPluginNameStatic(), "C++ Language",
50                                 CreateInstance);
51 }
52 
53 void CPlusPlusLanguage::Terminate() {
54   PluginManager::UnregisterPlugin(CreateInstance);
55 }
56 
57 lldb_private::ConstString CPlusPlusLanguage::GetPluginNameStatic() {
58   static ConstString g_name("cplusplus");
59   return g_name;
60 }
61 
62 bool CPlusPlusLanguage::SymbolNameFitsToLanguage(Mangled mangled) const {
63   const char *mangled_name = mangled.GetMangledName().GetCString();
64   return mangled_name && CPlusPlusLanguage::IsCPPMangledName(mangled_name);
65 }
66 
67 ConstString CPlusPlusLanguage::GetDemangledFunctionNameWithoutArguments(
68     Mangled mangled) const {
69   const char *mangled_name_cstr = mangled.GetMangledName().GetCString();
70   ConstString demangled_name = mangled.GetDemangledName();
71   if (demangled_name && mangled_name_cstr && mangled_name_cstr[0]) {
72     if (mangled_name_cstr[0] == '_' && mangled_name_cstr[1] == 'Z' &&
73         (mangled_name_cstr[2] != 'T' && // avoid virtual table, VTT structure,
74                                         // typeinfo structure, and typeinfo
75                                         // mangled_name
76          mangled_name_cstr[2] != 'G' && // avoid guard variables
77          mangled_name_cstr[2] != 'Z'))  // named local entities (if we
78                                         // eventually handle eSymbolTypeData,
79                                         // we will want this back)
80     {
81       CPlusPlusLanguage::MethodName cxx_method(demangled_name);
82       if (!cxx_method.GetBasename().empty()) {
83         std::string shortname;
84         if (!cxx_method.GetContext().empty())
85           shortname = cxx_method.GetContext().str() + "::";
86         shortname += cxx_method.GetBasename().str();
87         return ConstString(shortname);
88       }
89     }
90   }
91   if (demangled_name)
92     return demangled_name;
93   return mangled.GetMangledName();
94 }
95 
96 // PluginInterface protocol
97 
98 lldb_private::ConstString CPlusPlusLanguage::GetPluginName() {
99   return GetPluginNameStatic();
100 }
101 
102 // Static Functions
103 
104 Language *CPlusPlusLanguage::CreateInstance(lldb::LanguageType language) {
105   // Use plugin for C++ but not for Objective-C++ (which has its own plugin).
106   if (Language::LanguageIsCPlusPlus(language) &&
107       language != eLanguageTypeObjC_plus_plus)
108     return new CPlusPlusLanguage();
109   return nullptr;
110 }
111 
112 void CPlusPlusLanguage::MethodName::Clear() {
113   m_full.Clear();
114   m_basename = llvm::StringRef();
115   m_context = llvm::StringRef();
116   m_arguments = llvm::StringRef();
117   m_qualifiers = llvm::StringRef();
118   m_parsed = false;
119   m_parse_error = false;
120 }
121 
122 static bool ReverseFindMatchingChars(const llvm::StringRef &s,
123                                      const llvm::StringRef &left_right_chars,
124                                      size_t &left_pos, size_t &right_pos,
125                                      size_t pos = llvm::StringRef::npos) {
126   assert(left_right_chars.size() == 2);
127   left_pos = llvm::StringRef::npos;
128   const char left_char = left_right_chars[0];
129   const char right_char = left_right_chars[1];
130   pos = s.find_last_of(left_right_chars, pos);
131   if (pos == llvm::StringRef::npos || s[pos] == left_char)
132     return false;
133   right_pos = pos;
134   uint32_t depth = 1;
135   while (pos > 0 && depth > 0) {
136     pos = s.find_last_of(left_right_chars, pos);
137     if (pos == llvm::StringRef::npos)
138       return false;
139     if (s[pos] == left_char) {
140       if (--depth == 0) {
141         left_pos = pos;
142         return left_pos < right_pos;
143       }
144     } else if (s[pos] == right_char) {
145       ++depth;
146     }
147   }
148   return false;
149 }
150 
151 static bool IsTrivialBasename(const llvm::StringRef &basename) {
152   // Check that the basename matches with the following regular expression
153   // "^~?([A-Za-z_][A-Za-z_0-9]*)$" We are using a hand written implementation
154   // because it is significantly more efficient then using the general purpose
155   // regular expression library.
156   size_t idx = 0;
157   if (basename.size() > 0 && basename[0] == '~')
158     idx = 1;
159 
160   if (basename.size() <= idx)
161     return false; // Empty string or "~"
162 
163   if (!std::isalpha(basename[idx]) && basename[idx] != '_')
164     return false; // First character (after removing the possible '~'') isn't in
165                   // [A-Za-z_]
166 
167   // Read all characters matching [A-Za-z_0-9]
168   ++idx;
169   while (idx < basename.size()) {
170     if (!std::isalnum(basename[idx]) && basename[idx] != '_')
171       break;
172     ++idx;
173   }
174 
175   // We processed all characters. It is a vaild basename.
176   return idx == basename.size();
177 }
178 
179 bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() {
180   // This method tries to parse simple method definitions which are presumably
181   // most comman in user programs. Definitions that can be parsed by this
182   // function don't have return types and templates in the name.
183   // A::B::C::fun(std::vector<T> &) const
184   size_t arg_start, arg_end;
185   llvm::StringRef full(m_full.GetCString());
186   llvm::StringRef parens("()", 2);
187   if (ReverseFindMatchingChars(full, parens, arg_start, arg_end)) {
188     m_arguments = full.substr(arg_start, arg_end - arg_start + 1);
189     if (arg_end + 1 < full.size())
190       m_qualifiers = full.substr(arg_end + 1).ltrim();
191 
192     if (arg_start == 0)
193       return false;
194     size_t basename_end = arg_start;
195     size_t context_start = 0;
196     size_t context_end = full.rfind(':', basename_end);
197     if (context_end == llvm::StringRef::npos)
198       m_basename = full.substr(0, basename_end);
199     else {
200       if (context_start < context_end)
201         m_context = full.substr(context_start, context_end - 1 - context_start);
202       const size_t basename_begin = context_end + 1;
203       m_basename = full.substr(basename_begin, basename_end - basename_begin);
204     }
205 
206     if (IsTrivialBasename(m_basename)) {
207       return true;
208     } else {
209       // The C++ basename doesn't match our regular expressions so this can't
210       // be a valid C++ method, clear everything out and indicate an error
211       m_context = llvm::StringRef();
212       m_basename = llvm::StringRef();
213       m_arguments = llvm::StringRef();
214       m_qualifiers = llvm::StringRef();
215       return false;
216     }
217   }
218   return false;
219 }
220 
221 void CPlusPlusLanguage::MethodName::Parse() {
222   if (!m_parsed && m_full) {
223     if (TrySimplifiedParse()) {
224       m_parse_error = false;
225     } else {
226       CPlusPlusNameParser parser(m_full.GetStringRef());
227       if (auto function = parser.ParseAsFunctionDefinition()) {
228         m_basename = function.getValue().name.basename;
229         m_context = function.getValue().name.context;
230         m_arguments = function.getValue().arguments;
231         m_qualifiers = function.getValue().qualifiers;
232         m_parse_error = false;
233       } else {
234         m_parse_error = true;
235       }
236     }
237     m_parsed = true;
238   }
239 }
240 
241 llvm::StringRef CPlusPlusLanguage::MethodName::GetBasename() {
242   if (!m_parsed)
243     Parse();
244   return m_basename;
245 }
246 
247 llvm::StringRef CPlusPlusLanguage::MethodName::GetContext() {
248   if (!m_parsed)
249     Parse();
250   return m_context;
251 }
252 
253 llvm::StringRef CPlusPlusLanguage::MethodName::GetArguments() {
254   if (!m_parsed)
255     Parse();
256   return m_arguments;
257 }
258 
259 llvm::StringRef CPlusPlusLanguage::MethodName::GetQualifiers() {
260   if (!m_parsed)
261     Parse();
262   return m_qualifiers;
263 }
264 
265 std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() {
266   if (!m_parsed)
267     Parse();
268   if (m_context.empty())
269     return std::string(m_basename);
270 
271   std::string res;
272   res += m_context;
273   res += "::";
274   res += m_basename;
275   return res;
276 }
277 
278 bool CPlusPlusLanguage::IsCPPMangledName(llvm::StringRef name) {
279   // FIXME!! we should really run through all the known C++ Language plugins
280   // and ask each one if this is a C++ mangled name
281 
282   Mangled::ManglingScheme scheme = Mangled::GetManglingScheme(name);
283 
284   if (scheme == Mangled::eManglingSchemeNone)
285     return false;
286 
287   return true;
288 }
289 
290 bool CPlusPlusLanguage::ExtractContextAndIdentifier(
291     const char *name, llvm::StringRef &context, llvm::StringRef &identifier) {
292   if (MSVCUndecoratedNameParser::IsMSVCUndecoratedName(name))
293     return MSVCUndecoratedNameParser::ExtractContextAndIdentifier(name, context,
294                                                                   identifier);
295 
296   CPlusPlusNameParser parser(name);
297   if (auto full_name = parser.ParseAsFullName()) {
298     identifier = full_name.getValue().basename;
299     context = full_name.getValue().context;
300     return true;
301   }
302   return false;
303 }
304 
305 namespace {
306 class NodeAllocator {
307   llvm::BumpPtrAllocator Alloc;
308 
309 public:
310   void reset() { Alloc.Reset(); }
311 
312   template <typename T, typename... Args> T *makeNode(Args &&... args) {
313     return new (Alloc.Allocate(sizeof(T), alignof(T)))
314         T(std::forward<Args>(args)...);
315   }
316 
317   void *allocateNodeArray(size_t sz) {
318     return Alloc.Allocate(sizeof(llvm::itanium_demangle::Node *) * sz,
319                           alignof(llvm::itanium_demangle::Node *));
320   }
321 };
322 
323 template <typename Derived>
324 class ManglingSubstitutor
325     : public llvm::itanium_demangle::AbstractManglingParser<Derived,
326                                                             NodeAllocator> {
327   using Base =
328       llvm::itanium_demangle::AbstractManglingParser<Derived, NodeAllocator>;
329 
330 public:
331   ManglingSubstitutor() : Base(nullptr, nullptr) {}
332 
333   template<typename... Ts>
334   ConstString substitute(llvm::StringRef Mangled, Ts &&... Vals) {
335     this->getDerived().reset(Mangled, std::forward<Ts>(Vals)...);
336     return substituteImpl(Mangled);
337   }
338 
339 
340 protected:
341   void reset(llvm::StringRef Mangled) {
342     Base::reset(Mangled.begin(), Mangled.end());
343     Written = Mangled.begin();
344     Result.clear();
345     Substituted = false;
346   }
347 
348   ConstString substituteImpl(llvm::StringRef Mangled) {
349     Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
350     if (this->parse() == nullptr) {
351       LLDB_LOG(log, "Failed to substitute mangling in {0}", Mangled);
352       return ConstString();
353     }
354     if (!Substituted)
355       return ConstString();
356 
357     // Append any trailing unmodified input.
358     appendUnchangedInput();
359     LLDB_LOG(log, "Substituted mangling {0} -> {1}", Mangled, Result);
360     return ConstString(Result);
361   }
362 
363   void trySubstitute(llvm::StringRef From, llvm::StringRef To) {
364     if (!llvm::StringRef(currentParserPos(), this->numLeft()).startswith(From))
365       return;
366 
367     // We found a match. Append unmodified input up to this point.
368     appendUnchangedInput();
369 
370     // And then perform the replacement.
371     Result += To;
372     Written += From.size();
373     Substituted = true;
374   }
375 
376 private:
377   /// Input character until which we have constructed the respective output
378   /// already.
379   const char *Written;
380 
381   llvm::SmallString<128> Result;
382 
383   /// Whether we have performed any substitutions.
384   bool Substituted;
385 
386   const char *currentParserPos() const { return this->First; }
387 
388   void appendUnchangedInput() {
389     Result +=
390         llvm::StringRef(Written, std::distance(Written, currentParserPos()));
391     Written = currentParserPos();
392   }
393 
394 };
395 
396 /// Given a mangled function `Mangled`, replace all the primitive function type
397 /// arguments of `Search` with type `Replace`.
398 class TypeSubstitutor : public ManglingSubstitutor<TypeSubstitutor> {
399   llvm::StringRef Search;
400   llvm::StringRef Replace;
401 
402 public:
403   void reset(llvm::StringRef Mangled, llvm::StringRef Search,
404              llvm::StringRef Replace) {
405     ManglingSubstitutor::reset(Mangled);
406     this->Search = Search;
407     this->Replace = Replace;
408   }
409 
410   llvm::itanium_demangle::Node *parseType() {
411     trySubstitute(Search, Replace);
412     return ManglingSubstitutor::parseType();
413   }
414 };
415 
416 class CtorDtorSubstitutor : public ManglingSubstitutor<CtorDtorSubstitutor> {
417 public:
418   llvm::itanium_demangle::Node *
419   parseCtorDtorName(llvm::itanium_demangle::Node *&SoFar, NameState *State) {
420     trySubstitute("C1", "C2");
421     trySubstitute("D1", "D2");
422     return ManglingSubstitutor::parseCtorDtorName(SoFar, State);
423   }
424 };
425 } // namespace
426 
427 std::vector<ConstString> CPlusPlusLanguage::GenerateAlternateFunctionManglings(
428     const ConstString mangled_name) const {
429   std::vector<ConstString> alternates;
430 
431   /// Get a basic set of alternative manglings for the given symbol `name`, by
432   /// making a few basic possible substitutions on basic types, storage duration
433   /// and `const`ness for the given symbol. The output parameter `alternates`
434   /// is filled with a best-guess, non-exhaustive set of different manglings
435   /// for the given name.
436 
437   // Maybe we're looking for a const symbol but the debug info told us it was
438   // non-const...
439   if (!strncmp(mangled_name.GetCString(), "_ZN", 3) &&
440       strncmp(mangled_name.GetCString(), "_ZNK", 4)) {
441     std::string fixed_scratch("_ZNK");
442     fixed_scratch.append(mangled_name.GetCString() + 3);
443     alternates.push_back(ConstString(fixed_scratch));
444   }
445 
446   // Maybe we're looking for a static symbol but we thought it was global...
447   if (!strncmp(mangled_name.GetCString(), "_Z", 2) &&
448       strncmp(mangled_name.GetCString(), "_ZL", 3)) {
449     std::string fixed_scratch("_ZL");
450     fixed_scratch.append(mangled_name.GetCString() + 2);
451     alternates.push_back(ConstString(fixed_scratch));
452   }
453 
454   TypeSubstitutor TS;
455   // `char` is implementation defined as either `signed` or `unsigned`.  As a
456   // result a char parameter has 3 possible manglings: 'c'-char, 'a'-signed
457   // char, 'h'-unsigned char.  If we're looking for symbols with a signed char
458   // parameter, try finding matches which have the general case 'c'.
459   if (ConstString char_fixup =
460           TS.substitute(mangled_name.GetStringRef(), "a", "c"))
461     alternates.push_back(char_fixup);
462 
463   // long long parameter mangling 'x', may actually just be a long 'l' argument
464   if (ConstString long_fixup =
465           TS.substitute(mangled_name.GetStringRef(), "x", "l"))
466     alternates.push_back(long_fixup);
467 
468   // unsigned long long parameter mangling 'y', may actually just be unsigned
469   // long 'm' argument
470   if (ConstString ulong_fixup =
471           TS.substitute(mangled_name.GetStringRef(), "y", "m"))
472     alternates.push_back(ulong_fixup);
473 
474   if (ConstString ctor_fixup =
475           CtorDtorSubstitutor().substitute(mangled_name.GetStringRef()))
476     alternates.push_back(ctor_fixup);
477 
478   return alternates;
479 }
480 
481 static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
482   if (!cpp_category_sp)
483     return;
484 
485   TypeSummaryImpl::Flags stl_summary_flags;
486   stl_summary_flags.SetCascades(true)
487       .SetSkipPointers(false)
488       .SetSkipReferences(false)
489       .SetDontShowChildren(true)
490       .SetDontShowValue(true)
491       .SetShowMembersOneLiner(false)
492       .SetHideItemNames(false);
493 
494   AddCXXSummary(cpp_category_sp,
495                 lldb_private::formatters::LibcxxStringSummaryProviderASCII,
496                 "std::string summary provider",
497                 ConstString("^std::__[[:alnum:]]+::string$"), stl_summary_flags,
498                 true);
499   AddCXXSummary(cpp_category_sp,
500                 lldb_private::formatters::LibcxxStringSummaryProviderASCII,
501                 "std::string summary provider",
502                 ConstString("^std::__[[:alnum:]]+::basic_string<char, "
503                             "std::__[[:alnum:]]+::char_traits<char>, "
504                             "std::__[[:alnum:]]+::allocator<char> >$"),
505                 stl_summary_flags, true);
506   AddCXXSummary(cpp_category_sp,
507                 lldb_private::formatters::LibcxxStringSummaryProviderASCII,
508                 "std::string summary provider",
509                 ConstString("^std::__[[:alnum:]]+::basic_string<unsigned char, "
510                             "std::__[[:alnum:]]+::char_traits<unsigned char>, "
511                             "std::__[[:alnum:]]+::allocator<unsigned char> >$"),
512                 stl_summary_flags, true);
513 
514   AddCXXSummary(cpp_category_sp,
515                 lldb_private::formatters::LibcxxStringSummaryProviderUTF16,
516                 "std::u16string summary provider",
517                 ConstString(
518                     "^std::__[[:alnum:]]+::basic_string<char16_t, "
519                     "std::__[[:alnum:]]+::char_traits<char16_t>, "
520                     "std::__[[:alnum:]]+::allocator<char16_t> >$"),
521                 stl_summary_flags, true);
522 
523   AddCXXSummary(cpp_category_sp,
524                 lldb_private::formatters::LibcxxStringSummaryProviderUTF32,
525                 "std::u32string summary provider",
526                 ConstString(
527                     "^std::__[[:alnum:]]+::basic_string<char32_t, "
528                     "std::__[[:alnum:]]+::char_traits<char32_t>, "
529                     "std::__[[:alnum:]]+::allocator<char32_t> >$"),
530                 stl_summary_flags, true);
531 
532   AddCXXSummary(cpp_category_sp,
533                 lldb_private::formatters::LibcxxWStringSummaryProvider,
534                 "std::wstring summary provider",
535                 ConstString("^std::__[[:alnum:]]+::wstring$"),
536                 stl_summary_flags, true);
537   AddCXXSummary(cpp_category_sp,
538                 lldb_private::formatters::LibcxxWStringSummaryProvider,
539                 "std::wstring summary provider",
540                 ConstString("^std::__[[:alnum:]]+::basic_string<wchar_t, "
541                             "std::__[[:alnum:]]+::char_traits<wchar_t>, "
542                             "std::__[[:alnum:]]+::allocator<wchar_t> >$"),
543                 stl_summary_flags, true);
544 
545   SyntheticChildren::Flags stl_synth_flags;
546   stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
547       false);
548   SyntheticChildren::Flags stl_deref_flags = stl_synth_flags;
549   stl_deref_flags.SetFrontEndWantsDereference();
550 
551   AddCXXSynthetic(
552       cpp_category_sp,
553       lldb_private::formatters::LibcxxBitsetSyntheticFrontEndCreator,
554       "libc++ std::bitset synthetic children",
555       ConstString("^std::__[[:alnum:]]+::bitset<.+>(( )?&)?$"), stl_deref_flags,
556       true);
557   AddCXXSynthetic(
558       cpp_category_sp,
559       lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator,
560       "libc++ std::vector synthetic children",
561       ConstString("^std::__[[:alnum:]]+::vector<.+>(( )?&)?$"), stl_deref_flags,
562       true);
563   AddCXXSynthetic(
564       cpp_category_sp,
565       lldb_private::formatters::LibcxxStdForwardListSyntheticFrontEndCreator,
566       "libc++ std::forward_list synthetic children",
567       ConstString("^std::__[[:alnum:]]+::forward_list<.+>(( )?&)?$"),
568       stl_synth_flags, true);
569   AddCXXSynthetic(
570       cpp_category_sp,
571       lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator,
572       "libc++ std::list synthetic children",
573       // A POSIX variant of: "^std::__(?!cxx11:)[[:alnum:]]+::list<.+>(( )?&)?$"
574       // so that it does not clash with: "^std::(__cxx11::)?list<.+>(( )?&)?$"
575       ConstString("^std::__([A-Zabd-z0-9]|cx?[A-Za-wyz0-9]|cxx1?[A-Za-z02-9]|"
576                   "cxx11[[:alnum:]])[[:alnum:]]*::list<.+>(( )?&)?$"),
577       stl_deref_flags, true);
578   AddCXXSynthetic(
579       cpp_category_sp,
580       lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
581       "libc++ std::map synthetic children",
582       ConstString("^std::__[[:alnum:]]+::map<.+> >(( )?&)?$"), stl_synth_flags,
583       true);
584   AddCXXSynthetic(
585       cpp_category_sp,
586       lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
587       "libc++ std::set synthetic children",
588       ConstString("^std::__[[:alnum:]]+::set<.+> >(( )?&)?$"), stl_deref_flags,
589       true);
590   AddCXXSynthetic(
591       cpp_category_sp,
592       lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
593       "libc++ std::multiset synthetic children",
594       ConstString("^std::__[[:alnum:]]+::multiset<.+> >(( )?&)?$"),
595       stl_deref_flags, true);
596   AddCXXSynthetic(
597       cpp_category_sp,
598       lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
599       "libc++ std::multimap synthetic children",
600       ConstString("^std::__[[:alnum:]]+::multimap<.+> >(( )?&)?$"),
601       stl_synth_flags, true);
602   AddCXXSynthetic(
603       cpp_category_sp,
604       lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator,
605       "libc++ std::unordered containers synthetic children",
606       ConstString("^(std::__[[:alnum:]]+::)unordered_(multi)?(map|set)<.+> >$"),
607       stl_synth_flags, true);
608   AddCXXSynthetic(
609       cpp_category_sp,
610       lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator,
611       "libc++ std::initializer_list synthetic children",
612       ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags,
613       true);
614   AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator,
615                   "libc++ std::queue synthetic children",
616                   ConstString("^std::__[[:alnum:]]+::queue<.+>(( )?&)?$"),
617                   stl_synth_flags, true);
618   AddCXXSynthetic(cpp_category_sp, LibcxxTupleFrontEndCreator,
619                   "libc++ std::tuple synthetic children",
620                   ConstString("^std::__[[:alnum:]]+::tuple<.*>(( )?&)?$"),
621                   stl_synth_flags, true);
622   AddCXXSynthetic(cpp_category_sp, LibcxxOptionalFrontEndCreator,
623                   "libc++ std::optional synthetic children",
624                   ConstString("^std::__[[:alnum:]]+::optional<.+>(( )?&)?$"),
625                   stl_synth_flags, true);
626   AddCXXSynthetic(cpp_category_sp, LibcxxVariantFrontEndCreator,
627                   "libc++ std::variant synthetic children",
628                   ConstString("^std::__[[:alnum:]]+::variant<.+>(( )?&)?$"),
629                   stl_synth_flags, true);
630   AddCXXSynthetic(
631       cpp_category_sp,
632       lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator,
633       "libc++ std::atomic synthetic children",
634       ConstString("^std::__[[:alnum:]]+::atomic<.+>$"), stl_synth_flags, true);
635 
636   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
637       RegularExpression("^(std::__[[:alnum:]]+::)deque<.+>(( )?&)?$"),
638       SyntheticChildrenSP(new ScriptedSyntheticChildren(
639           stl_synth_flags,
640           "lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));
641 
642   AddCXXSynthetic(
643       cpp_category_sp,
644       lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,
645       "shared_ptr synthetic children",
646       ConstString("^(std::__[[:alnum:]]+::)shared_ptr<.+>(( )?&)?$"),
647       stl_synth_flags, true);
648 
649   ConstString libcxx_std_unique_ptr_regex(
650       "^std::__[[:alnum:]]+::unique_ptr<.+>(( )?&)?$");
651   AddCXXSynthetic(
652       cpp_category_sp,
653       lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEndCreator,
654       "unique_ptr synthetic children", libcxx_std_unique_ptr_regex,
655       stl_synth_flags, true);
656 
657   AddCXXSynthetic(
658       cpp_category_sp,
659       lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,
660       "weak_ptr synthetic children",
661       ConstString("^(std::__[[:alnum:]]+::)weak_ptr<.+>(( )?&)?$"),
662       stl_synth_flags, true);
663   AddCXXSummary(cpp_category_sp,
664                 lldb_private::formatters::LibcxxFunctionSummaryProvider,
665                 "libc++ std::function summary provider",
666                 ConstString("^std::__[[:alnum:]]+::function<.+>$"),
667                 stl_summary_flags, true);
668 
669   stl_summary_flags.SetDontShowChildren(false);
670   stl_summary_flags.SetSkipPointers(false);
671   AddCXXSummary(cpp_category_sp,
672                 lldb_private::formatters::LibcxxContainerSummaryProvider,
673                 "libc++ std::bitset summary provider",
674                 ConstString("^std::__[[:alnum:]]+::bitset<.+>(( )?&)?$"),
675                 stl_summary_flags, true);
676   AddCXXSummary(cpp_category_sp,
677                 lldb_private::formatters::LibcxxContainerSummaryProvider,
678                 "libc++ std::vector summary provider",
679                 ConstString("^std::__[[:alnum:]]+::vector<.+>(( )?&)?$"),
680                 stl_summary_flags, true);
681   AddCXXSummary(cpp_category_sp,
682                 lldb_private::formatters::LibcxxContainerSummaryProvider,
683                 "libc++ std::list summary provider",
684                 ConstString("^std::__[[:alnum:]]+::forward_list<.+>(( )?&)?$"),
685                 stl_summary_flags, true);
686   AddCXXSummary(
687       cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider,
688       "libc++ std::list summary provider",
689       // A POSIX variant of: "^std::__(?!cxx11:)[[:alnum:]]+::list<.+>(( )?&)?$"
690       // so that it does not clash with: "^std::(__cxx11::)?list<.+>(( )?&)?$"
691       ConstString("^std::__([A-Zabd-z0-9]|cx?[A-Za-wyz0-9]|cxx1?[A-Za-z02-9]|"
692                   "cxx11[[:alnum:]])[[:alnum:]]*::list<.+>(( )?&)?$"),
693       stl_summary_flags, true);
694   AddCXXSummary(cpp_category_sp,
695                 lldb_private::formatters::LibcxxContainerSummaryProvider,
696                 "libc++ std::map summary provider",
697                 ConstString("^std::__[[:alnum:]]+::map<.+>(( )?&)?$"),
698                 stl_summary_flags, true);
699   AddCXXSummary(cpp_category_sp,
700                 lldb_private::formatters::LibcxxContainerSummaryProvider,
701                 "libc++ std::deque summary provider",
702                 ConstString("^std::__[[:alnum:]]+::deque<.+>(( )?&)?$"),
703                 stl_summary_flags, true);
704   AddCXXSummary(cpp_category_sp,
705                 lldb_private::formatters::LibcxxContainerSummaryProvider,
706                 "libc++ std::queue summary provider",
707                 ConstString("^std::__[[:alnum:]]+::queue<.+>(( )?&)?$"),
708                 stl_summary_flags, true);
709   AddCXXSummary(cpp_category_sp,
710                 lldb_private::formatters::LibcxxContainerSummaryProvider,
711                 "libc++ std::set summary provider",
712                 ConstString("^std::__[[:alnum:]]+::set<.+>(( )?&)?$"),
713                 stl_summary_flags, true);
714   AddCXXSummary(cpp_category_sp,
715                 lldb_private::formatters::LibcxxContainerSummaryProvider,
716                 "libc++ std::multiset summary provider",
717                 ConstString("^std::__[[:alnum:]]+::multiset<.+>(( )?&)?$"),
718                 stl_summary_flags, true);
719   AddCXXSummary(cpp_category_sp,
720                 lldb_private::formatters::LibcxxContainerSummaryProvider,
721                 "libc++ std::multimap summary provider",
722                 ConstString("^std::__[[:alnum:]]+::multimap<.+>(( )?&)?$"),
723                 stl_summary_flags, true);
724   AddCXXSummary(
725       cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider,
726       "libc++ std::unordered containers summary provider",
727       ConstString("^(std::__[[:alnum:]]+::)unordered_(multi)?(map|set)<.+> >$"),
728       stl_summary_flags, true);
729   AddCXXSummary(cpp_category_sp, LibcxxContainerSummaryProvider,
730                 "libc++ std::tuple summary provider",
731                 ConstString("^std::__[[:alnum:]]+::tuple<.*>(( )?&)?$"),
732                 stl_summary_flags, true);
733   AddCXXSummary(
734       cpp_category_sp, lldb_private::formatters::LibCxxAtomicSummaryProvider,
735       "libc++ std::atomic summary provider",
736       ConstString("^std::__[[:alnum:]]+::atomic<.+>$"), stl_summary_flags,
737       true);
738   AddCXXSummary(cpp_category_sp,
739                 lldb_private::formatters::LibcxxOptionalSummaryProvider,
740                 "libc++ std::optional summary provider",
741                 ConstString("^std::__[[:alnum:]]+::optional<.+>(( )?&)?$"),
742                 stl_summary_flags, true);
743   AddCXXSummary(cpp_category_sp,
744                 lldb_private::formatters::LibcxxVariantSummaryProvider,
745                 "libc++ std::variant summary provider",
746                 ConstString("^std::__[[:alnum:]]+::variant<.+>(( )?&)?$"),
747                 stl_summary_flags, true);
748 
749   stl_summary_flags.SetSkipPointers(true);
750 
751   AddCXXSummary(cpp_category_sp,
752                 lldb_private::formatters::LibcxxSmartPointerSummaryProvider,
753                 "libc++ std::shared_ptr summary provider",
754                 ConstString("^std::__[[:alnum:]]+::shared_ptr<.+>(( )?&)?$"),
755                 stl_summary_flags, true);
756   AddCXXSummary(cpp_category_sp,
757                 lldb_private::formatters::LibcxxSmartPointerSummaryProvider,
758                 "libc++ std::weak_ptr summary provider",
759                 ConstString("^std::__[[:alnum:]]+::weak_ptr<.+>(( )?&)?$"),
760                 stl_summary_flags, true);
761   AddCXXSummary(cpp_category_sp,
762                 lldb_private::formatters::LibcxxUniquePointerSummaryProvider,
763                 "libc++ std::unique_ptr summary provider",
764                 libcxx_std_unique_ptr_regex, stl_summary_flags, true);
765 
766   AddCXXSynthetic(
767       cpp_category_sp,
768       lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator,
769       "std::vector iterator synthetic children",
770       ConstString("^std::__[[:alnum:]]+::__wrap_iter<.+>$"), stl_synth_flags,
771       true);
772 
773   AddCXXSynthetic(
774       cpp_category_sp,
775       lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator,
776       "std::map iterator synthetic children",
777       ConstString("^std::__[[:alnum:]]+::__map_iterator<.+>$"), stl_synth_flags,
778       true);
779 }
780 
781 static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
782   if (!cpp_category_sp)
783     return;
784 
785   TypeSummaryImpl::Flags stl_summary_flags;
786   stl_summary_flags.SetCascades(true)
787       .SetSkipPointers(false)
788       .SetSkipReferences(false)
789       .SetDontShowChildren(true)
790       .SetDontShowValue(true)
791       .SetShowMembersOneLiner(false)
792       .SetHideItemNames(false);
793 
794   lldb::TypeSummaryImplSP std_string_summary_sp(
795       new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p}"));
796 
797   lldb::TypeSummaryImplSP cxx11_string_summary_sp(new CXXFunctionSummaryFormat(
798       stl_summary_flags, LibStdcppStringSummaryProvider,
799       "libstdc++ c++11 std::string summary provider"));
800   lldb::TypeSummaryImplSP cxx11_wstring_summary_sp(new CXXFunctionSummaryFormat(
801       stl_summary_flags, LibStdcppWStringSummaryProvider,
802       "libstdc++ c++11 std::wstring summary provider"));
803 
804   cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::string"),
805                                                     std_string_summary_sp);
806   cpp_category_sp->GetTypeSummariesContainer()->Add(
807       ConstString("std::basic_string<char>"), std_string_summary_sp);
808   cpp_category_sp->GetTypeSummariesContainer()->Add(
809       ConstString("std::basic_string<char,std::char_traits<char>,std::"
810                   "allocator<char> >"),
811       std_string_summary_sp);
812   cpp_category_sp->GetTypeSummariesContainer()->Add(
813       ConstString("std::basic_string<char, std::char_traits<char>, "
814                   "std::allocator<char> >"),
815       std_string_summary_sp);
816 
817   cpp_category_sp->GetTypeSummariesContainer()->Add(
818       ConstString("std::__cxx11::string"), cxx11_string_summary_sp);
819   cpp_category_sp->GetTypeSummariesContainer()->Add(
820       ConstString("std::__cxx11::basic_string<char, std::char_traits<char>, "
821                   "std::allocator<char> >"),
822       cxx11_string_summary_sp);
823   cpp_category_sp->GetTypeSummariesContainer()->Add(
824       ConstString("std::__cxx11::basic_string<unsigned char, std::char_traits<unsigned char>, "
825                   "std::allocator<unsigned char> >"),
826       cxx11_string_summary_sp);
827 
828   // making sure we force-pick the summary for printing wstring (_M_p is a
829   // wchar_t*)
830   lldb::TypeSummaryImplSP std_wstring_summary_sp(
831       new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p%S}"));
832 
833   cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::wstring"),
834                                                     std_wstring_summary_sp);
835   cpp_category_sp->GetTypeSummariesContainer()->Add(
836       ConstString("std::basic_string<wchar_t>"), std_wstring_summary_sp);
837   cpp_category_sp->GetTypeSummariesContainer()->Add(
838       ConstString("std::basic_string<wchar_t,std::char_traits<wchar_t>,std::"
839                   "allocator<wchar_t> >"),
840       std_wstring_summary_sp);
841   cpp_category_sp->GetTypeSummariesContainer()->Add(
842       ConstString("std::basic_string<wchar_t, std::char_traits<wchar_t>, "
843                   "std::allocator<wchar_t> >"),
844       std_wstring_summary_sp);
845 
846   cpp_category_sp->GetTypeSummariesContainer()->Add(
847       ConstString("std::__cxx11::wstring"), cxx11_wstring_summary_sp);
848   cpp_category_sp->GetTypeSummariesContainer()->Add(
849       ConstString("std::__cxx11::basic_string<wchar_t, "
850                   "std::char_traits<wchar_t>, std::allocator<wchar_t> >"),
851       cxx11_wstring_summary_sp);
852 
853   SyntheticChildren::Flags stl_synth_flags;
854   stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
855       false);
856 
857   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
858       RegularExpression("^std::vector<.+>(( )?&)?$"),
859       SyntheticChildrenSP(new ScriptedSyntheticChildren(
860           stl_synth_flags,
861           "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
862   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
863       RegularExpression("^std::map<.+> >(( )?&)?$"),
864       SyntheticChildrenSP(new ScriptedSyntheticChildren(
865           stl_synth_flags,
866           "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider")));
867   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
868       RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"),
869       SyntheticChildrenSP(new ScriptedSyntheticChildren(
870           stl_synth_flags,
871           "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
872   stl_summary_flags.SetDontShowChildren(false);
873   stl_summary_flags.SetSkipPointers(true);
874   cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
875       RegularExpression("^std::vector<.+>(( )?&)?$"),
876       TypeSummaryImplSP(
877           new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
878   cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
879       RegularExpression("^std::map<.+> >(( )?&)?$"),
880       TypeSummaryImplSP(
881           new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
882   cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
883       RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"),
884       TypeSummaryImplSP(
885           new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
886 
887   AddCXXSynthetic(
888       cpp_category_sp,
889       lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator,
890       "std::vector iterator synthetic children",
891       ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
892 
893   AddCXXSynthetic(
894       cpp_category_sp,
895       lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator,
896       "std::map iterator synthetic children",
897       ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
898 
899   AddCXXSynthetic(
900       cpp_category_sp,
901       lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator,
902       "std::unique_ptr synthetic children",
903       ConstString("^std::unique_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
904   AddCXXSynthetic(
905       cpp_category_sp,
906       lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator,
907       "std::shared_ptr synthetic children",
908       ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
909   AddCXXSynthetic(
910       cpp_category_sp,
911       lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator,
912       "std::weak_ptr synthetic children",
913       ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
914   AddCXXSynthetic(
915       cpp_category_sp,
916       lldb_private::formatters::LibStdcppTupleSyntheticFrontEndCreator,
917       "std::tuple synthetic children", ConstString("^std::tuple<.+>(( )?&)?$"),
918       stl_synth_flags, true);
919 
920   AddCXXSummary(cpp_category_sp,
921                 lldb_private::formatters::LibStdcppUniquePointerSummaryProvider,
922                 "libstdc++ std::unique_ptr summary provider",
923                 ConstString("^std::unique_ptr<.+>(( )?&)?$"), stl_summary_flags,
924                 true);
925   AddCXXSummary(cpp_category_sp,
926                 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider,
927                 "libstdc++ std::shared_ptr summary provider",
928                 ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_summary_flags,
929                 true);
930   AddCXXSummary(cpp_category_sp,
931                 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider,
932                 "libstdc++ std::weak_ptr summary provider",
933                 ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_summary_flags,
934                 true);
935 }
936 
937 static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
938   if (!cpp_category_sp)
939     return;
940 
941   TypeSummaryImpl::Flags string_flags;
942   string_flags.SetCascades(true)
943       .SetSkipPointers(true)
944       .SetSkipReferences(false)
945       .SetDontShowChildren(true)
946       .SetDontShowValue(false)
947       .SetShowMembersOneLiner(false)
948       .SetHideItemNames(false);
949 
950   TypeSummaryImpl::Flags string_array_flags;
951   string_array_flags.SetCascades(true)
952       .SetSkipPointers(true)
953       .SetSkipReferences(false)
954       .SetDontShowChildren(true)
955       .SetDontShowValue(true)
956       .SetShowMembersOneLiner(false)
957       .SetHideItemNames(false);
958 
959   // FIXME because of a bug in the FormattersContainer we need to add a summary
960   // for both X* and const X* (<rdar://problem/12717717>)
961   AddCXXSummary(
962       cpp_category_sp, lldb_private::formatters::Char8StringSummaryProvider,
963       "char8_t * summary provider", ConstString("char8_t *"), string_flags);
964   AddCXXSummary(cpp_category_sp,
965                 lldb_private::formatters::Char8StringSummaryProvider,
966                 "char8_t [] summary provider",
967                 ConstString("char8_t \\[[0-9]+\\]"), string_array_flags, true);
968 
969   AddCXXSummary(
970       cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider,
971       "char16_t * summary provider", ConstString("char16_t *"), string_flags);
972   AddCXXSummary(cpp_category_sp,
973                 lldb_private::formatters::Char16StringSummaryProvider,
974                 "char16_t [] summary provider",
975                 ConstString("char16_t \\[[0-9]+\\]"), string_array_flags, true);
976 
977   AddCXXSummary(
978       cpp_category_sp, lldb_private::formatters::Char32StringSummaryProvider,
979       "char32_t * summary provider", ConstString("char32_t *"), string_flags);
980   AddCXXSummary(cpp_category_sp,
981                 lldb_private::formatters::Char32StringSummaryProvider,
982                 "char32_t [] summary provider",
983                 ConstString("char32_t \\[[0-9]+\\]"), string_array_flags, true);
984 
985   AddCXXSummary(
986       cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider,
987       "wchar_t * summary provider", ConstString("wchar_t *"), string_flags);
988   AddCXXSummary(cpp_category_sp,
989                 lldb_private::formatters::WCharStringSummaryProvider,
990                 "wchar_t * summary provider",
991                 ConstString("wchar_t \\[[0-9]+\\]"), string_array_flags, true);
992 
993   AddCXXSummary(
994       cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider,
995       "unichar * summary provider", ConstString("unichar *"), string_flags);
996 
997   TypeSummaryImpl::Flags widechar_flags;
998   widechar_flags.SetDontShowValue(true)
999       .SetSkipPointers(true)
1000       .SetSkipReferences(false)
1001       .SetCascades(true)
1002       .SetDontShowChildren(true)
1003       .SetHideItemNames(true)
1004       .SetShowMembersOneLiner(false);
1005 
1006   AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char8SummaryProvider,
1007                 "char8_t summary provider", ConstString("char8_t"),
1008                 widechar_flags);
1009   AddCXXSummary(
1010       cpp_category_sp, lldb_private::formatters::Char16SummaryProvider,
1011       "char16_t summary provider", ConstString("char16_t"), widechar_flags);
1012   AddCXXSummary(
1013       cpp_category_sp, lldb_private::formatters::Char32SummaryProvider,
1014       "char32_t summary provider", ConstString("char32_t"), widechar_flags);
1015   AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharSummaryProvider,
1016                 "wchar_t summary provider", ConstString("wchar_t"),
1017                 widechar_flags);
1018 
1019   AddCXXSummary(
1020       cpp_category_sp, lldb_private::formatters::Char16SummaryProvider,
1021       "unichar summary provider", ConstString("unichar"), widechar_flags);
1022 }
1023 
1024 std::unique_ptr<Language::TypeScavenger> CPlusPlusLanguage::GetTypeScavenger() {
1025   class CPlusPlusTypeScavenger : public Language::ImageListTypeScavenger {
1026   public:
1027     CompilerType AdjustForInclusion(CompilerType &candidate) override {
1028       LanguageType lang_type(candidate.GetMinimumLanguage());
1029       if (!Language::LanguageIsC(lang_type) &&
1030           !Language::LanguageIsCPlusPlus(lang_type))
1031         return CompilerType();
1032       if (candidate.IsTypedefType())
1033         return candidate.GetTypedefedType();
1034       return candidate;
1035     }
1036   };
1037 
1038   return std::unique_ptr<TypeScavenger>(new CPlusPlusTypeScavenger());
1039 }
1040 
1041 lldb::TypeCategoryImplSP CPlusPlusLanguage::GetFormatters() {
1042   static llvm::once_flag g_initialize;
1043   static TypeCategoryImplSP g_category;
1044 
1045   llvm::call_once(g_initialize, [this]() -> void {
1046     DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
1047     if (g_category) {
1048       LoadLibStdcppFormatters(g_category);
1049       LoadLibCxxFormatters(g_category);
1050       LoadSystemFormatters(g_category);
1051     }
1052   });
1053   return g_category;
1054 }
1055 
1056 HardcodedFormatters::HardcodedSummaryFinder
1057 CPlusPlusLanguage::GetHardcodedSummaries() {
1058   static llvm::once_flag g_initialize;
1059   static ConstString g_vectortypes("VectorTypes");
1060   static HardcodedFormatters::HardcodedSummaryFinder g_formatters;
1061 
1062   llvm::call_once(g_initialize, []() -> void {
1063     g_formatters.push_back(
1064         [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
1065            FormatManager &) -> TypeSummaryImpl::SharedPointer {
1066           static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
1067               new CXXFunctionSummaryFormat(
1068                   TypeSummaryImpl::Flags(),
1069                   lldb_private::formatters::CXXFunctionPointerSummaryProvider,
1070                   "Function pointer summary provider"));
1071           if (valobj.GetCompilerType().IsFunctionPointerType()) {
1072             return formatter_sp;
1073           }
1074           return nullptr;
1075         });
1076     g_formatters.push_back(
1077         [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
1078            FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer {
1079           static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
1080               new CXXFunctionSummaryFormat(
1081                   TypeSummaryImpl::Flags()
1082                       .SetCascades(true)
1083                       .SetDontShowChildren(true)
1084                       .SetHideItemNames(true)
1085                       .SetShowMembersOneLiner(true)
1086                       .SetSkipPointers(true)
1087                       .SetSkipReferences(false),
1088                   lldb_private::formatters::VectorTypeSummaryProvider,
1089                   "vector_type pointer summary provider"));
1090           if (valobj.GetCompilerType().IsVectorType()) {
1091             if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
1092               return formatter_sp;
1093           }
1094           return nullptr;
1095         });
1096     g_formatters.push_back(
1097         [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
1098            FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer {
1099           static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
1100               new CXXFunctionSummaryFormat(
1101                   TypeSummaryImpl::Flags()
1102                       .SetCascades(true)
1103                       .SetDontShowChildren(true)
1104                       .SetHideItemNames(true)
1105                       .SetShowMembersOneLiner(true)
1106                       .SetSkipPointers(true)
1107                       .SetSkipReferences(false),
1108                   lldb_private::formatters::BlockPointerSummaryProvider,
1109                   "block pointer summary provider"));
1110           if (valobj.GetCompilerType().IsBlockPointerType()) {
1111             return formatter_sp;
1112           }
1113           return nullptr;
1114         });
1115   });
1116 
1117   return g_formatters;
1118 }
1119 
1120 HardcodedFormatters::HardcodedSyntheticFinder
1121 CPlusPlusLanguage::GetHardcodedSynthetics() {
1122   static llvm::once_flag g_initialize;
1123   static ConstString g_vectortypes("VectorTypes");
1124   static HardcodedFormatters::HardcodedSyntheticFinder g_formatters;
1125 
1126   llvm::call_once(g_initialize, []() -> void {
1127     g_formatters.push_back([](lldb_private::ValueObject &valobj,
1128                               lldb::DynamicValueType,
1129                               FormatManager &
1130                                   fmt_mgr) -> SyntheticChildren::SharedPointer {
1131       static CXXSyntheticChildren::SharedPointer formatter_sp(
1132           new CXXSyntheticChildren(
1133               SyntheticChildren::Flags()
1134                   .SetCascades(true)
1135                   .SetSkipPointers(true)
1136                   .SetSkipReferences(true)
1137                   .SetNonCacheable(true),
1138               "vector_type synthetic children",
1139               lldb_private::formatters::VectorTypeSyntheticFrontEndCreator));
1140       if (valobj.GetCompilerType().IsVectorType()) {
1141         if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
1142           return formatter_sp;
1143       }
1144       return nullptr;
1145     });
1146     g_formatters.push_back([](lldb_private::ValueObject &valobj,
1147                               lldb::DynamicValueType,
1148                               FormatManager &
1149                                   fmt_mgr) -> SyntheticChildren::SharedPointer {
1150       static CXXSyntheticChildren::SharedPointer formatter_sp(
1151           new CXXSyntheticChildren(
1152               SyntheticChildren::Flags()
1153                   .SetCascades(true)
1154                   .SetSkipPointers(true)
1155                   .SetSkipReferences(true)
1156                   .SetNonCacheable(true),
1157               "block pointer synthetic children",
1158               lldb_private::formatters::BlockPointerSyntheticFrontEndCreator));
1159       if (valobj.GetCompilerType().IsBlockPointerType()) {
1160         return formatter_sp;
1161       }
1162       return nullptr;
1163     });
1164 
1165   });
1166 
1167   return g_formatters;
1168 }
1169 
1170 bool CPlusPlusLanguage::IsNilReference(ValueObject &valobj) {
1171   if (!Language::LanguageIsCPlusPlus(valobj.GetObjectRuntimeLanguage()) ||
1172       !valobj.IsPointerType())
1173     return false;
1174   bool canReadValue = true;
1175   bool isZero = valobj.GetValueAsUnsigned(0, &canReadValue) == 0;
1176   return canReadValue && isZero;
1177 }
1178 
1179 bool CPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const {
1180   const auto suffixes = {".cpp", ".cxx", ".c++", ".cc",  ".c",
1181                          ".h",   ".hh",  ".hpp", ".hxx", ".h++"};
1182   for (auto suffix : suffixes) {
1183     if (file_path.endswith_insensitive(suffix))
1184       return true;
1185   }
1186 
1187   // Check if we're in a STL path (where the files usually have no extension
1188   // that we could check for.
1189   return file_path.contains("/usr/include/c++/");
1190 }
1191