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