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