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 uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
428     const ConstString mangled_name, std::set<ConstString> &alternates) {
429   const auto start_size = alternates.size();
430   /// Get a basic set of alternative manglings for the given symbol `name`, by
431   /// making a few basic possible substitutions on basic types, storage duration
432   /// and `const`ness for the given symbol. The output parameter `alternates`
433   /// is filled with a best-guess, non-exhaustive set of different manglings
434   /// for the given name.
435 
436   // Maybe we're looking for a const symbol but the debug info told us it was
437   // non-const...
438   if (!strncmp(mangled_name.GetCString(), "_ZN", 3) &&
439       strncmp(mangled_name.GetCString(), "_ZNK", 4)) {
440     std::string fixed_scratch("_ZNK");
441     fixed_scratch.append(mangled_name.GetCString() + 3);
442     alternates.insert(ConstString(fixed_scratch));
443   }
444 
445   // Maybe we're looking for a static symbol but we thought it was global...
446   if (!strncmp(mangled_name.GetCString(), "_Z", 2) &&
447       strncmp(mangled_name.GetCString(), "_ZL", 3)) {
448     std::string fixed_scratch("_ZL");
449     fixed_scratch.append(mangled_name.GetCString() + 2);
450     alternates.insert(ConstString(fixed_scratch));
451   }
452 
453   TypeSubstitutor TS;
454   // `char` is implementation defined as either `signed` or `unsigned`.  As a
455   // result a char parameter has 3 possible manglings: 'c'-char, 'a'-signed
456   // char, 'h'-unsigned char.  If we're looking for symbols with a signed char
457   // parameter, try finding matches which have the general case 'c'.
458   if (ConstString char_fixup =
459           TS.substitute(mangled_name.GetStringRef(), "a", "c"))
460     alternates.insert(char_fixup);
461 
462   // long long parameter mangling 'x', may actually just be a long 'l' argument
463   if (ConstString long_fixup =
464           TS.substitute(mangled_name.GetStringRef(), "x", "l"))
465     alternates.insert(long_fixup);
466 
467   // unsigned long long parameter mangling 'y', may actually just be unsigned
468   // long 'm' argument
469   if (ConstString ulong_fixup =
470           TS.substitute(mangled_name.GetStringRef(), "y", "m"))
471     alternates.insert(ulong_fixup);
472 
473   if (ConstString ctor_fixup =
474           CtorDtorSubstitutor().substitute(mangled_name.GetStringRef()))
475     alternates.insert(ctor_fixup);
476 
477   return alternates.size() - start_size;
478 }
479 
480 static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
481   if (!cpp_category_sp)
482     return;
483 
484   TypeSummaryImpl::Flags stl_summary_flags;
485   stl_summary_flags.SetCascades(true)
486       .SetSkipPointers(false)
487       .SetSkipReferences(false)
488       .SetDontShowChildren(true)
489       .SetDontShowValue(true)
490       .SetShowMembersOneLiner(false)
491       .SetHideItemNames(false);
492 
493   AddCXXSummary(cpp_category_sp,
494                 lldb_private::formatters::LibcxxStringSummaryProviderASCII,
495                 "std::string summary provider",
496                 ConstString("^std::__[[:alnum:]]+::string$"), stl_summary_flags,
497                 true);
498   AddCXXSummary(cpp_category_sp,
499                 lldb_private::formatters::LibcxxStringSummaryProviderASCII,
500                 "std::string summary provider",
501                 ConstString("^std::__[[:alnum:]]+::basic_string<char, "
502                             "std::__[[:alnum:]]+::char_traits<char>, "
503                             "std::__[[:alnum:]]+::allocator<char> >$"),
504                 stl_summary_flags, true);
505   AddCXXSummary(cpp_category_sp,
506                 lldb_private::formatters::LibcxxStringSummaryProviderASCII,
507                 "std::string summary provider",
508                 ConstString("^std::__[[:alnum:]]+::basic_string<unsigned char, "
509                             "std::__[[:alnum:]]+::char_traits<unsigned char>, "
510                             "std::__[[:alnum:]]+::allocator<unsigned char> >$"),
511                 stl_summary_flags, true);
512 
513   AddCXXSummary(cpp_category_sp,
514                 lldb_private::formatters::LibcxxStringSummaryProviderUTF16,
515                 "std::u16string summary provider",
516                 ConstString(
517                     "^std::__[[:alnum:]]+::basic_string<char16_t, "
518                     "std::__[[:alnum:]]+::char_traits<char16_t>, "
519                     "std::__[[:alnum:]]+::allocator<char16_t> >$"),
520                 stl_summary_flags, true);
521 
522   AddCXXSummary(cpp_category_sp,
523                 lldb_private::formatters::LibcxxStringSummaryProviderUTF32,
524                 "std::u32string summary provider",
525                 ConstString(
526                     "^std::__[[:alnum:]]+::basic_string<char32_t, "
527                     "std::__[[:alnum:]]+::char_traits<char32_t>, "
528                     "std::__[[:alnum:]]+::allocator<char32_t> >$"),
529                 stl_summary_flags, true);
530 
531   AddCXXSummary(cpp_category_sp,
532                 lldb_private::formatters::LibcxxWStringSummaryProvider,
533                 "std::wstring summary provider",
534                 ConstString("^std::__[[:alnum:]]+::wstring$"),
535                 stl_summary_flags, true);
536   AddCXXSummary(cpp_category_sp,
537                 lldb_private::formatters::LibcxxWStringSummaryProvider,
538                 "std::wstring summary provider",
539                 ConstString("^std::__[[:alnum:]]+::basic_string<wchar_t, "
540                             "std::__[[:alnum:]]+::char_traits<wchar_t>, "
541                             "std::__[[:alnum:]]+::allocator<wchar_t> >$"),
542                 stl_summary_flags, true);
543 
544   SyntheticChildren::Flags stl_synth_flags;
545   stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
546       false);
547   SyntheticChildren::Flags stl_deref_flags = stl_synth_flags;
548   stl_deref_flags.SetFrontEndWantsDereference();
549 
550   AddCXXSynthetic(
551       cpp_category_sp,
552       lldb_private::formatters::LibcxxBitsetSyntheticFrontEndCreator,
553       "libc++ std::bitset synthetic children",
554       ConstString("^std::__[[:alnum:]]+::bitset<.+>(( )?&)?$"), stl_deref_flags,
555       true);
556   AddCXXSynthetic(
557       cpp_category_sp,
558       lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator,
559       "libc++ std::vector synthetic children",
560       ConstString("^std::__[[:alnum:]]+::vector<.+>(( )?&)?$"), stl_deref_flags,
561       true);
562   AddCXXSynthetic(
563       cpp_category_sp,
564       lldb_private::formatters::LibcxxStdForwardListSyntheticFrontEndCreator,
565       "libc++ std::forward_list synthetic children",
566       ConstString("^std::__[[:alnum:]]+::forward_list<.+>(( )?&)?$"),
567       stl_synth_flags, true);
568   AddCXXSynthetic(
569       cpp_category_sp,
570       lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator,
571       "libc++ std::list synthetic children",
572       // A POSIX variant of: "^std::__(?!cxx11:)[[:alnum:]]+::list<.+>(( )?&)?$"
573       // so that it does not clash with: "^std::(__cxx11::)?list<.+>(( )?&)?$"
574       ConstString("^std::__([A-Zabd-z0-9]|cx?[A-Za-wyz0-9]|cxx1?[A-Za-z02-9]|"
575                   "cxx11[[:alnum:]])[[:alnum:]]*::list<.+>(( )?&)?$"),
576       stl_deref_flags, true);
577   AddCXXSynthetic(
578       cpp_category_sp,
579       lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
580       "libc++ std::map synthetic children",
581       ConstString("^std::__[[:alnum:]]+::map<.+> >(( )?&)?$"), stl_synth_flags,
582       true);
583   AddCXXSynthetic(
584       cpp_category_sp,
585       lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
586       "libc++ std::set synthetic children",
587       ConstString("^std::__[[:alnum:]]+::set<.+> >(( )?&)?$"), stl_deref_flags,
588       true);
589   AddCXXSynthetic(
590       cpp_category_sp,
591       lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
592       "libc++ std::multiset synthetic children",
593       ConstString("^std::__[[:alnum:]]+::multiset<.+> >(( )?&)?$"),
594       stl_deref_flags, true);
595   AddCXXSynthetic(
596       cpp_category_sp,
597       lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
598       "libc++ std::multimap synthetic children",
599       ConstString("^std::__[[:alnum:]]+::multimap<.+> >(( )?&)?$"),
600       stl_synth_flags, true);
601   AddCXXSynthetic(
602       cpp_category_sp,
603       lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator,
604       "libc++ std::unordered containers synthetic children",
605       ConstString("^(std::__[[:alnum:]]+::)unordered_(multi)?(map|set)<.+> >$"),
606       stl_synth_flags, true);
607   AddCXXSynthetic(
608       cpp_category_sp,
609       lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator,
610       "libc++ std::initializer_list synthetic children",
611       ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags,
612       true);
613   AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator,
614                   "libc++ std::queue synthetic children",
615                   ConstString("^std::__[[:alnum:]]+::queue<.+>(( )?&)?$"),
616                   stl_synth_flags, true);
617   AddCXXSynthetic(cpp_category_sp, LibcxxTupleFrontEndCreator,
618                   "libc++ std::tuple synthetic children",
619                   ConstString("^std::__[[:alnum:]]+::tuple<.*>(( )?&)?$"),
620                   stl_synth_flags, true);
621   AddCXXSynthetic(cpp_category_sp, LibcxxOptionalFrontEndCreator,
622                   "libc++ std::optional synthetic children",
623                   ConstString("^std::__[[:alnum:]]+::optional<.+>(( )?&)?$"),
624                   stl_synth_flags, true);
625   AddCXXSynthetic(cpp_category_sp, LibcxxVariantFrontEndCreator,
626                   "libc++ std::variant synthetic children",
627                   ConstString("^std::__[[:alnum:]]+::variant<.+>(( )?&)?$"),
628                   stl_synth_flags, true);
629   AddCXXSynthetic(
630       cpp_category_sp,
631       lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator,
632       "libc++ std::atomic synthetic children",
633       ConstString("^std::__[[:alnum:]]+::atomic<.+>$"), stl_synth_flags, true);
634 
635   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
636       RegularExpression("^(std::__[[:alnum:]]+::)deque<.+>(( )?&)?$"),
637       SyntheticChildrenSP(new ScriptedSyntheticChildren(
638           stl_synth_flags,
639           "lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));
640 
641   AddCXXSynthetic(
642       cpp_category_sp,
643       lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,
644       "shared_ptr synthetic children",
645       ConstString("^(std::__[[:alnum:]]+::)shared_ptr<.+>(( )?&)?$"),
646       stl_synth_flags, true);
647 
648   ConstString libcxx_std_unique_ptr_regex(
649       "^std::__[[:alnum:]]+::unique_ptr<.+>(( )?&)?$");
650   AddCXXSynthetic(
651       cpp_category_sp,
652       lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEndCreator,
653       "unique_ptr synthetic children", libcxx_std_unique_ptr_regex,
654       stl_synth_flags, true);
655 
656   AddCXXSynthetic(
657       cpp_category_sp,
658       lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,
659       "weak_ptr synthetic children",
660       ConstString("^(std::__[[:alnum:]]+::)weak_ptr<.+>(( )?&)?$"),
661       stl_synth_flags, true);
662   AddCXXSummary(cpp_category_sp,
663                 lldb_private::formatters::LibcxxFunctionSummaryProvider,
664                 "libc++ std::function summary provider",
665                 ConstString("^std::__[[:alnum:]]+::function<.+>$"),
666                 stl_summary_flags, true);
667 
668   stl_summary_flags.SetDontShowChildren(false);
669   stl_summary_flags.SetSkipPointers(false);
670   AddCXXSummary(cpp_category_sp,
671                 lldb_private::formatters::LibcxxContainerSummaryProvider,
672                 "libc++ std::bitset summary provider",
673                 ConstString("^std::__[[:alnum:]]+::bitset<.+>(( )?&)?$"),
674                 stl_summary_flags, true);
675   AddCXXSummary(cpp_category_sp,
676                 lldb_private::formatters::LibcxxContainerSummaryProvider,
677                 "libc++ std::vector summary provider",
678                 ConstString("^std::__[[:alnum:]]+::vector<.+>(( )?&)?$"),
679                 stl_summary_flags, true);
680   AddCXXSummary(cpp_category_sp,
681                 lldb_private::formatters::LibcxxContainerSummaryProvider,
682                 "libc++ std::list summary provider",
683                 ConstString("^std::__[[:alnum:]]+::forward_list<.+>(( )?&)?$"),
684                 stl_summary_flags, true);
685   AddCXXSummary(
686       cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider,
687       "libc++ std::list summary provider",
688       // A POSIX variant of: "^std::__(?!cxx11:)[[:alnum:]]+::list<.+>(( )?&)?$"
689       // so that it does not clash with: "^std::(__cxx11::)?list<.+>(( )?&)?$"
690       ConstString("^std::__([A-Zabd-z0-9]|cx?[A-Za-wyz0-9]|cxx1?[A-Za-z02-9]|"
691                   "cxx11[[:alnum:]])[[:alnum:]]*::list<.+>(( )?&)?$"),
692       stl_summary_flags, true);
693   AddCXXSummary(cpp_category_sp,
694                 lldb_private::formatters::LibcxxContainerSummaryProvider,
695                 "libc++ std::map summary provider",
696                 ConstString("^std::__[[:alnum:]]+::map<.+>(( )?&)?$"),
697                 stl_summary_flags, true);
698   AddCXXSummary(cpp_category_sp,
699                 lldb_private::formatters::LibcxxContainerSummaryProvider,
700                 "libc++ std::deque summary provider",
701                 ConstString("^std::__[[:alnum:]]+::deque<.+>(( )?&)?$"),
702                 stl_summary_flags, true);
703   AddCXXSummary(cpp_category_sp,
704                 lldb_private::formatters::LibcxxContainerSummaryProvider,
705                 "libc++ std::queue summary provider",
706                 ConstString("^std::__[[:alnum:]]+::queue<.+>(( )?&)?$"),
707                 stl_summary_flags, true);
708   AddCXXSummary(cpp_category_sp,
709                 lldb_private::formatters::LibcxxContainerSummaryProvider,
710                 "libc++ std::set summary provider",
711                 ConstString("^std::__[[:alnum:]]+::set<.+>(( )?&)?$"),
712                 stl_summary_flags, true);
713   AddCXXSummary(cpp_category_sp,
714                 lldb_private::formatters::LibcxxContainerSummaryProvider,
715                 "libc++ std::multiset summary provider",
716                 ConstString("^std::__[[:alnum:]]+::multiset<.+>(( )?&)?$"),
717                 stl_summary_flags, true);
718   AddCXXSummary(cpp_category_sp,
719                 lldb_private::formatters::LibcxxContainerSummaryProvider,
720                 "libc++ std::multimap summary provider",
721                 ConstString("^std::__[[:alnum:]]+::multimap<.+>(( )?&)?$"),
722                 stl_summary_flags, true);
723   AddCXXSummary(
724       cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider,
725       "libc++ std::unordered containers summary provider",
726       ConstString("^(std::__[[:alnum:]]+::)unordered_(multi)?(map|set)<.+> >$"),
727       stl_summary_flags, true);
728   AddCXXSummary(cpp_category_sp, LibcxxContainerSummaryProvider,
729                 "libc++ std::tuple summary provider",
730                 ConstString("^std::__[[:alnum:]]+::tuple<.*>(( )?&)?$"),
731                 stl_summary_flags, true);
732   AddCXXSummary(
733       cpp_category_sp, lldb_private::formatters::LibCxxAtomicSummaryProvider,
734       "libc++ std::atomic summary provider",
735       ConstString("^std::__[[:alnum:]]+::atomic<.+>$"), stl_summary_flags,
736       true);
737   AddCXXSummary(cpp_category_sp,
738                 lldb_private::formatters::LibcxxOptionalSummaryProvider,
739                 "libc++ std::optional summary provider",
740                 ConstString("^std::__[[:alnum:]]+::optional<.+>(( )?&)?$"),
741                 stl_summary_flags, true);
742   AddCXXSummary(cpp_category_sp,
743                 lldb_private::formatters::LibcxxVariantSummaryProvider,
744                 "libc++ std::variant summary provider",
745                 ConstString("^std::__[[:alnum:]]+::variant<.+>(( )?&)?$"),
746                 stl_summary_flags, true);
747 
748   stl_summary_flags.SetSkipPointers(true);
749 
750   AddCXXSummary(cpp_category_sp,
751                 lldb_private::formatters::LibcxxSmartPointerSummaryProvider,
752                 "libc++ std::shared_ptr summary provider",
753                 ConstString("^std::__[[:alnum:]]+::shared_ptr<.+>(( )?&)?$"),
754                 stl_summary_flags, true);
755   AddCXXSummary(cpp_category_sp,
756                 lldb_private::formatters::LibcxxSmartPointerSummaryProvider,
757                 "libc++ std::weak_ptr summary provider",
758                 ConstString("^std::__[[:alnum:]]+::weak_ptr<.+>(( )?&)?$"),
759                 stl_summary_flags, true);
760   AddCXXSummary(cpp_category_sp,
761                 lldb_private::formatters::LibcxxUniquePointerSummaryProvider,
762                 "libc++ std::unique_ptr summary provider",
763                 libcxx_std_unique_ptr_regex, stl_summary_flags, true);
764 
765   AddCXXSynthetic(
766       cpp_category_sp,
767       lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator,
768       "std::vector iterator synthetic children",
769       ConstString("^std::__[[:alnum:]]+::__wrap_iter<.+>$"), stl_synth_flags,
770       true);
771 
772   AddCXXSynthetic(
773       cpp_category_sp,
774       lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator,
775       "std::map iterator synthetic children",
776       ConstString("^std::__[[:alnum:]]+::__map_iterator<.+>$"), stl_synth_flags,
777       true);
778 }
779 
780 static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
781   if (!cpp_category_sp)
782     return;
783 
784   TypeSummaryImpl::Flags stl_summary_flags;
785   stl_summary_flags.SetCascades(true)
786       .SetSkipPointers(false)
787       .SetSkipReferences(false)
788       .SetDontShowChildren(true)
789       .SetDontShowValue(true)
790       .SetShowMembersOneLiner(false)
791       .SetHideItemNames(false);
792 
793   lldb::TypeSummaryImplSP std_string_summary_sp(
794       new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p}"));
795 
796   lldb::TypeSummaryImplSP cxx11_string_summary_sp(new CXXFunctionSummaryFormat(
797       stl_summary_flags, LibStdcppStringSummaryProvider,
798       "libstdc++ c++11 std::string summary provider"));
799   lldb::TypeSummaryImplSP cxx11_wstring_summary_sp(new CXXFunctionSummaryFormat(
800       stl_summary_flags, LibStdcppWStringSummaryProvider,
801       "libstdc++ c++11 std::wstring summary provider"));
802 
803   cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::string"),
804                                                     std_string_summary_sp);
805   cpp_category_sp->GetTypeSummariesContainer()->Add(
806       ConstString("std::basic_string<char>"), std_string_summary_sp);
807   cpp_category_sp->GetTypeSummariesContainer()->Add(
808       ConstString("std::basic_string<char,std::char_traits<char>,std::"
809                   "allocator<char> >"),
810       std_string_summary_sp);
811   cpp_category_sp->GetTypeSummariesContainer()->Add(
812       ConstString("std::basic_string<char, std::char_traits<char>, "
813                   "std::allocator<char> >"),
814       std_string_summary_sp);
815 
816   cpp_category_sp->GetTypeSummariesContainer()->Add(
817       ConstString("std::__cxx11::string"), cxx11_string_summary_sp);
818   cpp_category_sp->GetTypeSummariesContainer()->Add(
819       ConstString("std::__cxx11::basic_string<char, std::char_traits<char>, "
820                   "std::allocator<char> >"),
821       cxx11_string_summary_sp);
822   cpp_category_sp->GetTypeSummariesContainer()->Add(
823       ConstString("std::__cxx11::basic_string<unsigned char, std::char_traits<unsigned char>, "
824                   "std::allocator<unsigned char> >"),
825       cxx11_string_summary_sp);
826 
827   // making sure we force-pick the summary for printing wstring (_M_p is a
828   // wchar_t*)
829   lldb::TypeSummaryImplSP std_wstring_summary_sp(
830       new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p%S}"));
831 
832   cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::wstring"),
833                                                     std_wstring_summary_sp);
834   cpp_category_sp->GetTypeSummariesContainer()->Add(
835       ConstString("std::basic_string<wchar_t>"), std_wstring_summary_sp);
836   cpp_category_sp->GetTypeSummariesContainer()->Add(
837       ConstString("std::basic_string<wchar_t,std::char_traits<wchar_t>,std::"
838                   "allocator<wchar_t> >"),
839       std_wstring_summary_sp);
840   cpp_category_sp->GetTypeSummariesContainer()->Add(
841       ConstString("std::basic_string<wchar_t, std::char_traits<wchar_t>, "
842                   "std::allocator<wchar_t> >"),
843       std_wstring_summary_sp);
844 
845   cpp_category_sp->GetTypeSummariesContainer()->Add(
846       ConstString("std::__cxx11::wstring"), cxx11_wstring_summary_sp);
847   cpp_category_sp->GetTypeSummariesContainer()->Add(
848       ConstString("std::__cxx11::basic_string<wchar_t, "
849                   "std::char_traits<wchar_t>, std::allocator<wchar_t> >"),
850       cxx11_wstring_summary_sp);
851 
852   SyntheticChildren::Flags stl_synth_flags;
853   stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
854       false);
855 
856   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
857       RegularExpression("^std::vector<.+>(( )?&)?$"),
858       SyntheticChildrenSP(new ScriptedSyntheticChildren(
859           stl_synth_flags,
860           "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
861   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
862       RegularExpression("^std::map<.+> >(( )?&)?$"),
863       SyntheticChildrenSP(new ScriptedSyntheticChildren(
864           stl_synth_flags,
865           "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider")));
866   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
867       RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"),
868       SyntheticChildrenSP(new ScriptedSyntheticChildren(
869           stl_synth_flags,
870           "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
871   stl_summary_flags.SetDontShowChildren(false);
872   stl_summary_flags.SetSkipPointers(true);
873   cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
874       RegularExpression("^std::vector<.+>(( )?&)?$"),
875       TypeSummaryImplSP(
876           new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
877   cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
878       RegularExpression("^std::map<.+> >(( )?&)?$"),
879       TypeSummaryImplSP(
880           new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
881   cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
882       RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"),
883       TypeSummaryImplSP(
884           new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
885 
886   AddCXXSynthetic(
887       cpp_category_sp,
888       lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator,
889       "std::vector iterator synthetic children",
890       ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
891 
892   AddCXXSynthetic(
893       cpp_category_sp,
894       lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator,
895       "std::map iterator synthetic children",
896       ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
897 
898   AddCXXSynthetic(
899       cpp_category_sp,
900       lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator,
901       "std::unique_ptr synthetic children",
902       ConstString("^std::unique_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
903   AddCXXSynthetic(
904       cpp_category_sp,
905       lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator,
906       "std::shared_ptr synthetic children",
907       ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
908   AddCXXSynthetic(
909       cpp_category_sp,
910       lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator,
911       "std::weak_ptr synthetic children",
912       ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
913   AddCXXSynthetic(
914       cpp_category_sp,
915       lldb_private::formatters::LibStdcppTupleSyntheticFrontEndCreator,
916       "std::tuple synthetic children", ConstString("^std::tuple<.+>(( )?&)?$"),
917       stl_synth_flags, true);
918 
919   AddCXXSummary(cpp_category_sp,
920                 lldb_private::formatters::LibStdcppUniquePointerSummaryProvider,
921                 "libstdc++ std::unique_ptr summary provider",
922                 ConstString("^std::unique_ptr<.+>(( )?&)?$"), stl_summary_flags,
923                 true);
924   AddCXXSummary(cpp_category_sp,
925                 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider,
926                 "libstdc++ std::shared_ptr summary provider",
927                 ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_summary_flags,
928                 true);
929   AddCXXSummary(cpp_category_sp,
930                 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider,
931                 "libstdc++ std::weak_ptr summary provider",
932                 ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_summary_flags,
933                 true);
934 }
935 
936 static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
937   if (!cpp_category_sp)
938     return;
939 
940   TypeSummaryImpl::Flags string_flags;
941   string_flags.SetCascades(true)
942       .SetSkipPointers(true)
943       .SetSkipReferences(false)
944       .SetDontShowChildren(true)
945       .SetDontShowValue(false)
946       .SetShowMembersOneLiner(false)
947       .SetHideItemNames(false);
948 
949   TypeSummaryImpl::Flags string_array_flags;
950   string_array_flags.SetCascades(true)
951       .SetSkipPointers(true)
952       .SetSkipReferences(false)
953       .SetDontShowChildren(true)
954       .SetDontShowValue(true)
955       .SetShowMembersOneLiner(false)
956       .SetHideItemNames(false);
957 
958   // FIXME because of a bug in the FormattersContainer we need to add a summary
959   // for both X* and const X* (<rdar://problem/12717717>)
960   AddCXXSummary(
961       cpp_category_sp, lldb_private::formatters::Char8StringSummaryProvider,
962       "char8_t * summary provider", ConstString("char8_t *"), string_flags);
963   AddCXXSummary(cpp_category_sp,
964                 lldb_private::formatters::Char8StringSummaryProvider,
965                 "char8_t [] summary provider",
966                 ConstString("char8_t \\[[0-9]+\\]"), string_array_flags, true);
967 
968   AddCXXSummary(
969       cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider,
970       "char16_t * summary provider", ConstString("char16_t *"), string_flags);
971   AddCXXSummary(cpp_category_sp,
972                 lldb_private::formatters::Char16StringSummaryProvider,
973                 "char16_t [] summary provider",
974                 ConstString("char16_t \\[[0-9]+\\]"), string_array_flags, true);
975 
976   AddCXXSummary(
977       cpp_category_sp, lldb_private::formatters::Char32StringSummaryProvider,
978       "char32_t * summary provider", ConstString("char32_t *"), string_flags);
979   AddCXXSummary(cpp_category_sp,
980                 lldb_private::formatters::Char32StringSummaryProvider,
981                 "char32_t [] summary provider",
982                 ConstString("char32_t \\[[0-9]+\\]"), string_array_flags, true);
983 
984   AddCXXSummary(
985       cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider,
986       "wchar_t * summary provider", ConstString("wchar_t *"), string_flags);
987   AddCXXSummary(cpp_category_sp,
988                 lldb_private::formatters::WCharStringSummaryProvider,
989                 "wchar_t * summary provider",
990                 ConstString("wchar_t \\[[0-9]+\\]"), string_array_flags, true);
991 
992   AddCXXSummary(
993       cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider,
994       "unichar * summary provider", ConstString("unichar *"), string_flags);
995 
996   TypeSummaryImpl::Flags widechar_flags;
997   widechar_flags.SetDontShowValue(true)
998       .SetSkipPointers(true)
999       .SetSkipReferences(false)
1000       .SetCascades(true)
1001       .SetDontShowChildren(true)
1002       .SetHideItemNames(true)
1003       .SetShowMembersOneLiner(false);
1004 
1005   AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char8SummaryProvider,
1006                 "char8_t summary provider", ConstString("char8_t"),
1007                 widechar_flags);
1008   AddCXXSummary(
1009       cpp_category_sp, lldb_private::formatters::Char16SummaryProvider,
1010       "char16_t summary provider", ConstString("char16_t"), widechar_flags);
1011   AddCXXSummary(
1012       cpp_category_sp, lldb_private::formatters::Char32SummaryProvider,
1013       "char32_t summary provider", ConstString("char32_t"), widechar_flags);
1014   AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharSummaryProvider,
1015                 "wchar_t summary provider", ConstString("wchar_t"),
1016                 widechar_flags);
1017 
1018   AddCXXSummary(
1019       cpp_category_sp, lldb_private::formatters::Char16SummaryProvider,
1020       "unichar summary provider", ConstString("unichar"), widechar_flags);
1021 }
1022 
1023 std::unique_ptr<Language::TypeScavenger> CPlusPlusLanguage::GetTypeScavenger() {
1024   class CPlusPlusTypeScavenger : public Language::ImageListTypeScavenger {
1025   public:
1026     CompilerType AdjustForInclusion(CompilerType &candidate) override {
1027       LanguageType lang_type(candidate.GetMinimumLanguage());
1028       if (!Language::LanguageIsC(lang_type) &&
1029           !Language::LanguageIsCPlusPlus(lang_type))
1030         return CompilerType();
1031       if (candidate.IsTypedefType())
1032         return candidate.GetTypedefedType();
1033       return candidate;
1034     }
1035   };
1036 
1037   return std::unique_ptr<TypeScavenger>(new CPlusPlusTypeScavenger());
1038 }
1039 
1040 lldb::TypeCategoryImplSP CPlusPlusLanguage::GetFormatters() {
1041   static llvm::once_flag g_initialize;
1042   static TypeCategoryImplSP g_category;
1043 
1044   llvm::call_once(g_initialize, [this]() -> void {
1045     DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
1046     if (g_category) {
1047       LoadLibStdcppFormatters(g_category);
1048       LoadLibCxxFormatters(g_category);
1049       LoadSystemFormatters(g_category);
1050     }
1051   });
1052   return g_category;
1053 }
1054 
1055 HardcodedFormatters::HardcodedSummaryFinder
1056 CPlusPlusLanguage::GetHardcodedSummaries() {
1057   static llvm::once_flag g_initialize;
1058   static ConstString g_vectortypes("VectorTypes");
1059   static HardcodedFormatters::HardcodedSummaryFinder g_formatters;
1060 
1061   llvm::call_once(g_initialize, []() -> void {
1062     g_formatters.push_back(
1063         [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
1064            FormatManager &) -> TypeSummaryImpl::SharedPointer {
1065           static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
1066               new CXXFunctionSummaryFormat(
1067                   TypeSummaryImpl::Flags(),
1068                   lldb_private::formatters::CXXFunctionPointerSummaryProvider,
1069                   "Function pointer summary provider"));
1070           if (valobj.GetCompilerType().IsFunctionPointerType()) {
1071             return formatter_sp;
1072           }
1073           return nullptr;
1074         });
1075     g_formatters.push_back(
1076         [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
1077            FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer {
1078           static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
1079               new CXXFunctionSummaryFormat(
1080                   TypeSummaryImpl::Flags()
1081                       .SetCascades(true)
1082                       .SetDontShowChildren(true)
1083                       .SetHideItemNames(true)
1084                       .SetShowMembersOneLiner(true)
1085                       .SetSkipPointers(true)
1086                       .SetSkipReferences(false),
1087                   lldb_private::formatters::VectorTypeSummaryProvider,
1088                   "vector_type pointer summary provider"));
1089           if (valobj.GetCompilerType().IsVectorType()) {
1090             if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
1091               return formatter_sp;
1092           }
1093           return nullptr;
1094         });
1095     g_formatters.push_back(
1096         [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
1097            FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer {
1098           static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
1099               new CXXFunctionSummaryFormat(
1100                   TypeSummaryImpl::Flags()
1101                       .SetCascades(true)
1102                       .SetDontShowChildren(true)
1103                       .SetHideItemNames(true)
1104                       .SetShowMembersOneLiner(true)
1105                       .SetSkipPointers(true)
1106                       .SetSkipReferences(false),
1107                   lldb_private::formatters::BlockPointerSummaryProvider,
1108                   "block pointer summary provider"));
1109           if (valobj.GetCompilerType().IsBlockPointerType()) {
1110             return formatter_sp;
1111           }
1112           return nullptr;
1113         });
1114   });
1115 
1116   return g_formatters;
1117 }
1118 
1119 HardcodedFormatters::HardcodedSyntheticFinder
1120 CPlusPlusLanguage::GetHardcodedSynthetics() {
1121   static llvm::once_flag g_initialize;
1122   static ConstString g_vectortypes("VectorTypes");
1123   static HardcodedFormatters::HardcodedSyntheticFinder g_formatters;
1124 
1125   llvm::call_once(g_initialize, []() -> void {
1126     g_formatters.push_back([](lldb_private::ValueObject &valobj,
1127                               lldb::DynamicValueType,
1128                               FormatManager &
1129                                   fmt_mgr) -> SyntheticChildren::SharedPointer {
1130       static CXXSyntheticChildren::SharedPointer formatter_sp(
1131           new CXXSyntheticChildren(
1132               SyntheticChildren::Flags()
1133                   .SetCascades(true)
1134                   .SetSkipPointers(true)
1135                   .SetSkipReferences(true)
1136                   .SetNonCacheable(true),
1137               "vector_type synthetic children",
1138               lldb_private::formatters::VectorTypeSyntheticFrontEndCreator));
1139       if (valobj.GetCompilerType().IsVectorType()) {
1140         if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
1141           return formatter_sp;
1142       }
1143       return nullptr;
1144     });
1145     g_formatters.push_back([](lldb_private::ValueObject &valobj,
1146                               lldb::DynamicValueType,
1147                               FormatManager &
1148                                   fmt_mgr) -> SyntheticChildren::SharedPointer {
1149       static CXXSyntheticChildren::SharedPointer formatter_sp(
1150           new CXXSyntheticChildren(
1151               SyntheticChildren::Flags()
1152                   .SetCascades(true)
1153                   .SetSkipPointers(true)
1154                   .SetSkipReferences(true)
1155                   .SetNonCacheable(true),
1156               "block pointer synthetic children",
1157               lldb_private::formatters::BlockPointerSyntheticFrontEndCreator));
1158       if (valobj.GetCompilerType().IsBlockPointerType()) {
1159         return formatter_sp;
1160       }
1161       return nullptr;
1162     });
1163 
1164   });
1165 
1166   return g_formatters;
1167 }
1168 
1169 bool CPlusPlusLanguage::IsNilReference(ValueObject &valobj) {
1170   if (!Language::LanguageIsCPlusPlus(valobj.GetObjectRuntimeLanguage()) ||
1171       !valobj.IsPointerType())
1172     return false;
1173   bool canReadValue = true;
1174   bool isZero = valobj.GetValueAsUnsigned(0, &canReadValue) == 0;
1175   return canReadValue && isZero;
1176 }
1177 
1178 bool CPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const {
1179   const auto suffixes = {".cpp", ".cxx", ".c++", ".cc",  ".c",
1180                          ".h",   ".hh",  ".hpp", ".hxx", ".h++"};
1181   for (auto suffix : suffixes) {
1182     if (file_path.endswith_insensitive(suffix))
1183       return true;
1184   }
1185 
1186   // Check if we're in a STL path (where the files usually have no extension
1187   // that we could check for.
1188   return file_path.contains("/usr/include/c++/");
1189 }
1190