]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[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       ConstString("^std::__[[:alnum:]]+::list<.+>(( )?&)?$"), stl_deref_flags,
490       true);
491   AddCXXSynthetic(
492       cpp_category_sp,
493       lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
494       "libc++ std::map synthetic children",
495       ConstString("^std::__[[:alnum:]]+::map<.+> >(( )?&)?$"), stl_synth_flags,
496       true);
497   AddCXXSynthetic(
498       cpp_category_sp,
499       lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
500       "libc++ std::set synthetic children",
501       ConstString("^std::__[[:alnum:]]+::set<.+> >(( )?&)?$"), stl_deref_flags,
502       true);
503   AddCXXSynthetic(
504       cpp_category_sp,
505       lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
506       "libc++ std::multiset synthetic children",
507       ConstString("^std::__[[:alnum:]]+::multiset<.+> >(( )?&)?$"),
508       stl_deref_flags, true);
509   AddCXXSynthetic(
510       cpp_category_sp,
511       lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
512       "libc++ std::multimap synthetic children",
513       ConstString("^std::__[[:alnum:]]+::multimap<.+> >(( )?&)?$"),
514       stl_synth_flags, true);
515   AddCXXSynthetic(
516       cpp_category_sp,
517       lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator,
518       "libc++ std::unordered containers synthetic children",
519       ConstString("^(std::__[[:alnum:]]+::)unordered_(multi)?(map|set)<.+> >$"),
520       stl_synth_flags, true);
521   AddCXXSynthetic(
522       cpp_category_sp,
523       lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator,
524       "libc++ std::initializer_list synthetic children",
525       ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags,
526       true);
527   AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator,
528                   "libc++ std::queue synthetic children",
529                   ConstString("^std::__[[:alnum:]]+::queue<.+>(( )?&)?$"),
530                   stl_synth_flags, true);
531   AddCXXSynthetic(cpp_category_sp, LibcxxTupleFrontEndCreator,
532                   "libc++ std::tuple synthetic children",
533                   ConstString("^std::__[[:alnum:]]+::tuple<.*>(( )?&)?$"),
534                   stl_synth_flags, true);
535   AddCXXSynthetic(cpp_category_sp, LibcxxOptionalFrontEndCreator,
536                   "libc++ std::optional synthetic children",
537                   ConstString("^std::__[[:alnum:]]+::optional<.+>(( )?&)?$"),
538                   stl_synth_flags, true);
539   AddCXXSynthetic(cpp_category_sp, LibcxxVariantFrontEndCreator,
540                   "libc++ std::variant synthetic children",
541                   ConstString("^std::__[[:alnum:]]+::variant<.+>(( )?&)?$"),
542                   stl_synth_flags, true);
543   AddCXXSynthetic(
544       cpp_category_sp,
545       lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator,
546       "libc++ std::atomic synthetic children",
547       ConstString("^std::__[[:alnum:]]+::atomic<.+>$"), stl_synth_flags, true);
548
549   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
550       RegularExpressionSP(new RegularExpression(
551           llvm::StringRef("^(std::__[[:alnum:]]+::)deque<.+>(( )?&)?$"))),
552       SyntheticChildrenSP(new ScriptedSyntheticChildren(
553           stl_synth_flags,
554           "lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));
555
556   AddCXXSynthetic(
557       cpp_category_sp,
558       lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,
559       "shared_ptr synthetic children",
560       ConstString("^(std::__[[:alnum:]]+::)shared_ptr<.+>(( )?&)?$"),
561       stl_synth_flags, true);
562   AddCXXSynthetic(
563       cpp_category_sp,
564       lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,
565       "weak_ptr synthetic children",
566       ConstString("^(std::__[[:alnum:]]+::)weak_ptr<.+>(( )?&)?$"),
567       stl_synth_flags, true);
568
569   AddCXXSummary(
570       cpp_category_sp, lldb_private::formatters::LibcxxFunctionSummaryProvider,
571       "libc++ std::function summary provider",
572       ConstString("^std::__[[:alnum:]]+::function<.+>$"), stl_summary_flags,
573       true);
574
575   stl_summary_flags.SetDontShowChildren(false);
576   stl_summary_flags.SetSkipPointers(false);
577   AddCXXSummary(cpp_category_sp,
578                 lldb_private::formatters::LibcxxContainerSummaryProvider,
579                 "libc++ std::bitset summary provider",
580                 ConstString("^std::__[[:alnum:]]+::bitset<.+>(( )?&)?$"),
581                 stl_summary_flags, true);
582   AddCXXSummary(cpp_category_sp,
583                 lldb_private::formatters::LibcxxContainerSummaryProvider,
584                 "libc++ std::vector summary provider",
585                 ConstString("^std::__[[:alnum:]]+::vector<.+>(( )?&)?$"),
586                 stl_summary_flags, true);
587   AddCXXSummary(cpp_category_sp,
588                 lldb_private::formatters::LibcxxContainerSummaryProvider,
589                 "libc++ std::list summary provider",
590                 ConstString("^std::__[[:alnum:]]+::forward_list<.+>(( )?&)?$"),
591                 stl_summary_flags, true);
592   AddCXXSummary(cpp_category_sp,
593                 lldb_private::formatters::LibcxxContainerSummaryProvider,
594                 "libc++ std::list summary provider",
595                 ConstString("^std::__[[: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       RegularExpressionSP(
754           new RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$"))),
755       SyntheticChildrenSP(new ScriptedSyntheticChildren(
756           stl_synth_flags,
757           "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
758   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
759       RegularExpressionSP(
760           new RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$"))),
761       SyntheticChildrenSP(new ScriptedSyntheticChildren(
762           stl_synth_flags,
763           "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider")));
764   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
765       RegularExpressionSP(new RegularExpression(
766           llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$"))),
767       SyntheticChildrenSP(new ScriptedSyntheticChildren(
768           stl_synth_flags,
769           "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
770   stl_summary_flags.SetDontShowChildren(false);
771   stl_summary_flags.SetSkipPointers(true);
772   cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
773       RegularExpressionSP(
774           new RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$"))),
775       TypeSummaryImplSP(
776           new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
777   cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
778       RegularExpressionSP(
779           new RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$"))),
780       TypeSummaryImplSP(
781           new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
782   cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
783       RegularExpressionSP(new RegularExpression(
784           llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$"))),
785       TypeSummaryImplSP(
786           new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
787
788   AddCXXSynthetic(
789       cpp_category_sp,
790       lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator,
791       "std::vector iterator synthetic children",
792       ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
793
794   AddCXXSynthetic(
795       cpp_category_sp,
796       lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator,
797       "std::map iterator synthetic children",
798       ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
799
800   AddCXXSynthetic(
801       cpp_category_sp,
802       lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator,
803       "std::unique_ptr synthetic children",
804       ConstString("^std::unique_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
805   AddCXXSynthetic(
806       cpp_category_sp,
807       lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator,
808       "std::shared_ptr synthetic children",
809       ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
810   AddCXXSynthetic(
811       cpp_category_sp,
812       lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator,
813       "std::weak_ptr synthetic children",
814       ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
815   AddCXXSynthetic(
816       cpp_category_sp,
817       lldb_private::formatters::LibStdcppTupleSyntheticFrontEndCreator,
818       "std::tuple synthetic children", ConstString("^std::tuple<.+>(( )?&)?$"),
819       stl_synth_flags, true);
820
821   AddCXXSummary(cpp_category_sp,
822                 lldb_private::formatters::LibStdcppUniquePointerSummaryProvider,
823                 "libstdc++ std::unique_ptr summary provider",
824                 ConstString("^std::unique_ptr<.+>(( )?&)?$"), stl_summary_flags,
825                 true);
826   AddCXXSummary(cpp_category_sp,
827                 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider,
828                 "libstdc++ std::shared_ptr summary provider",
829                 ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_summary_flags,
830                 true);
831   AddCXXSummary(cpp_category_sp,
832                 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider,
833                 "libstdc++ std::weak_ptr summary provider",
834                 ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_summary_flags,
835                 true);
836 }
837
838 static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
839   if (!cpp_category_sp)
840     return;
841
842   TypeSummaryImpl::Flags string_flags;
843   string_flags.SetCascades(true)
844       .SetSkipPointers(true)
845       .SetSkipReferences(false)
846       .SetDontShowChildren(true)
847       .SetDontShowValue(false)
848       .SetShowMembersOneLiner(false)
849       .SetHideItemNames(false);
850
851   TypeSummaryImpl::Flags string_array_flags;
852   string_array_flags.SetCascades(true)
853       .SetSkipPointers(true)
854       .SetSkipReferences(false)
855       .SetDontShowChildren(true)
856       .SetDontShowValue(true)
857       .SetShowMembersOneLiner(false)
858       .SetHideItemNames(false);
859
860   // FIXME because of a bug in the FormattersContainer we need to add a summary
861   // for both X* and const X* (<rdar://problem/12717717>)
862   AddCXXSummary(
863       cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider,
864       "char16_t * summary provider", ConstString("char16_t *"), string_flags);
865   AddCXXSummary(cpp_category_sp,
866                 lldb_private::formatters::Char16StringSummaryProvider,
867                 "char16_t [] summary provider",
868                 ConstString("char16_t \\[[0-9]+\\]"), string_array_flags, true);
869
870   AddCXXSummary(
871       cpp_category_sp, lldb_private::formatters::Char32StringSummaryProvider,
872       "char32_t * summary provider", ConstString("char32_t *"), string_flags);
873   AddCXXSummary(cpp_category_sp,
874                 lldb_private::formatters::Char32StringSummaryProvider,
875                 "char32_t [] summary provider",
876                 ConstString("char32_t \\[[0-9]+\\]"), string_array_flags, true);
877
878   AddCXXSummary(
879       cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider,
880       "wchar_t * summary provider", ConstString("wchar_t *"), string_flags);
881   AddCXXSummary(cpp_category_sp,
882                 lldb_private::formatters::WCharStringSummaryProvider,
883                 "wchar_t * summary provider",
884                 ConstString("wchar_t \\[[0-9]+\\]"), string_array_flags, true);
885
886   AddCXXSummary(
887       cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider,
888       "unichar * summary provider", ConstString("unichar *"), string_flags);
889
890   TypeSummaryImpl::Flags widechar_flags;
891   widechar_flags.SetDontShowValue(true)
892       .SetSkipPointers(true)
893       .SetSkipReferences(false)
894       .SetCascades(true)
895       .SetDontShowChildren(true)
896       .SetHideItemNames(true)
897       .SetShowMembersOneLiner(false);
898
899   AddCXXSummary(
900       cpp_category_sp, lldb_private::formatters::Char16SummaryProvider,
901       "char16_t summary provider", ConstString("char16_t"), widechar_flags);
902   AddCXXSummary(
903       cpp_category_sp, lldb_private::formatters::Char32SummaryProvider,
904       "char32_t summary provider", ConstString("char32_t"), widechar_flags);
905   AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharSummaryProvider,
906                 "wchar_t summary provider", ConstString("wchar_t"),
907                 widechar_flags);
908
909   AddCXXSummary(
910       cpp_category_sp, lldb_private::formatters::Char16SummaryProvider,
911       "unichar summary provider", ConstString("unichar"), widechar_flags);
912 }
913
914 std::unique_ptr<Language::TypeScavenger> CPlusPlusLanguage::GetTypeScavenger() {
915   class CPlusPlusTypeScavenger : public Language::ImageListTypeScavenger {
916   public:
917     CompilerType AdjustForInclusion(CompilerType &candidate) override {
918       LanguageType lang_type(candidate.GetMinimumLanguage());
919       if (!Language::LanguageIsC(lang_type) &&
920           !Language::LanguageIsCPlusPlus(lang_type))
921         return CompilerType();
922       if (candidate.IsTypedefType())
923         return candidate.GetTypedefedType();
924       return candidate;
925     }
926   };
927
928   return std::unique_ptr<TypeScavenger>(new CPlusPlusTypeScavenger());
929 }
930
931 lldb::TypeCategoryImplSP CPlusPlusLanguage::GetFormatters() {
932   static llvm::once_flag g_initialize;
933   static TypeCategoryImplSP g_category;
934
935   llvm::call_once(g_initialize, [this]() -> void {
936     DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
937     if (g_category) {
938       LoadLibStdcppFormatters(g_category);
939       LoadLibCxxFormatters(g_category);
940       LoadSystemFormatters(g_category);
941     }
942   });
943   return g_category;
944 }
945
946 HardcodedFormatters::HardcodedSummaryFinder
947 CPlusPlusLanguage::GetHardcodedSummaries() {
948   static llvm::once_flag g_initialize;
949   static ConstString g_vectortypes("VectorTypes");
950   static HardcodedFormatters::HardcodedSummaryFinder g_formatters;
951
952   llvm::call_once(g_initialize, []() -> void {
953     g_formatters.push_back(
954         [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
955            FormatManager &) -> TypeSummaryImpl::SharedPointer {
956           static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
957               new CXXFunctionSummaryFormat(
958                   TypeSummaryImpl::Flags(),
959                   lldb_private::formatters::CXXFunctionPointerSummaryProvider,
960                   "Function pointer summary provider"));
961           if (valobj.GetCompilerType().IsFunctionPointerType()) {
962             return formatter_sp;
963           }
964           return nullptr;
965         });
966     g_formatters.push_back(
967         [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
968            FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer {
969           static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
970               new CXXFunctionSummaryFormat(
971                   TypeSummaryImpl::Flags()
972                       .SetCascades(true)
973                       .SetDontShowChildren(true)
974                       .SetHideItemNames(true)
975                       .SetShowMembersOneLiner(true)
976                       .SetSkipPointers(true)
977                       .SetSkipReferences(false),
978                   lldb_private::formatters::VectorTypeSummaryProvider,
979                   "vector_type pointer summary provider"));
980           if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) {
981             if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
982               return formatter_sp;
983           }
984           return nullptr;
985         });
986     g_formatters.push_back(
987         [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
988            FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer {
989           static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
990               new CXXFunctionSummaryFormat(
991                   TypeSummaryImpl::Flags()
992                       .SetCascades(true)
993                       .SetDontShowChildren(true)
994                       .SetHideItemNames(true)
995                       .SetShowMembersOneLiner(true)
996                       .SetSkipPointers(true)
997                       .SetSkipReferences(false),
998                   lldb_private::formatters::BlockPointerSummaryProvider,
999                   "block pointer summary provider"));
1000           if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) {
1001             return formatter_sp;
1002           }
1003           return nullptr;
1004         });
1005   });
1006
1007   return g_formatters;
1008 }
1009
1010 HardcodedFormatters::HardcodedSyntheticFinder
1011 CPlusPlusLanguage::GetHardcodedSynthetics() {
1012   static llvm::once_flag g_initialize;
1013   static ConstString g_vectortypes("VectorTypes");
1014   static HardcodedFormatters::HardcodedSyntheticFinder g_formatters;
1015
1016   llvm::call_once(g_initialize, []() -> void {
1017     g_formatters.push_back([](lldb_private::ValueObject &valobj,
1018                               lldb::DynamicValueType,
1019                               FormatManager &
1020                                   fmt_mgr) -> SyntheticChildren::SharedPointer {
1021       static CXXSyntheticChildren::SharedPointer formatter_sp(
1022           new CXXSyntheticChildren(
1023               SyntheticChildren::Flags()
1024                   .SetCascades(true)
1025                   .SetSkipPointers(true)
1026                   .SetSkipReferences(true)
1027                   .SetNonCacheable(true),
1028               "vector_type synthetic children",
1029               lldb_private::formatters::VectorTypeSyntheticFrontEndCreator));
1030       if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) {
1031         if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
1032           return formatter_sp;
1033       }
1034       return nullptr;
1035     });
1036     g_formatters.push_back([](lldb_private::ValueObject &valobj,
1037                               lldb::DynamicValueType,
1038                               FormatManager &
1039                                   fmt_mgr) -> SyntheticChildren::SharedPointer {
1040       static CXXSyntheticChildren::SharedPointer formatter_sp(
1041           new CXXSyntheticChildren(
1042               SyntheticChildren::Flags()
1043                   .SetCascades(true)
1044                   .SetSkipPointers(true)
1045                   .SetSkipReferences(true)
1046                   .SetNonCacheable(true),
1047               "block pointer synthetic children",
1048               lldb_private::formatters::BlockPointerSyntheticFrontEndCreator));
1049       if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) {
1050         return formatter_sp;
1051       }
1052       return nullptr;
1053     });
1054
1055   });
1056
1057   return g_formatters;
1058 }
1059
1060 bool CPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const {
1061   const auto suffixes = {".cpp", ".cxx", ".c++", ".cc",  ".c",
1062                          ".h",   ".hh",  ".hpp", ".hxx", ".h++"};
1063   for (auto suffix : suffixes) {
1064     if (file_path.endswith_lower(suffix))
1065       return true;
1066   }
1067
1068   // Check if we're in a STL path (where the files usually have no extension
1069   // that we could check for.
1070   return file_path.contains("/usr/include/c++/");
1071 }