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