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