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