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