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