xref: /llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp (revision 95eae4235d4cfa5cee67ab6c4e686baf8a57e9e5)
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 // C++ Includes
14 #include <cctype>
15 #include <cstring>
16 #include <functional>
17 #include <mutex>
18 
19 // Other libraries and framework includes
20 #include "llvm/ADT/StringRef.h"
21 
22 // Project includes
23 #include "lldb/Core/ConstString.h"
24 #include "lldb/Core/PluginManager.h"
25 #include "lldb/Core/RegularExpression.h"
26 #include "lldb/Core/UniqueCStringMap.h"
27 #include "lldb/DataFormatters/CXXFunctionPointer.h"
28 #include "lldb/DataFormatters/DataVisualization.h"
29 #include "lldb/DataFormatters/FormattersHelpers.h"
30 #include "lldb/DataFormatters/VectorType.h"
31 
32 #include "BlockPointer.h"
33 #include "CxxStringTypes.h"
34 #include "LibCxx.h"
35 #include "LibCxxAtomic.h"
36 #include "LibStdcpp.h"
37 
38 using namespace lldb;
39 using namespace lldb_private;
40 using namespace lldb_private::formatters;
41 
42 void CPlusPlusLanguage::Initialize() {
43   PluginManager::RegisterPlugin(GetPluginNameStatic(), "C++ Language",
44                                 CreateInstance);
45 }
46 
47 void CPlusPlusLanguage::Terminate() {
48   PluginManager::UnregisterPlugin(CreateInstance);
49 }
50 
51 lldb_private::ConstString CPlusPlusLanguage::GetPluginNameStatic() {
52   static ConstString g_name("cplusplus");
53   return g_name;
54 }
55 
56 //------------------------------------------------------------------
57 // PluginInterface protocol
58 //------------------------------------------------------------------
59 
60 lldb_private::ConstString CPlusPlusLanguage::GetPluginName() {
61   return GetPluginNameStatic();
62 }
63 
64 uint32_t CPlusPlusLanguage::GetPluginVersion() { return 1; }
65 
66 //------------------------------------------------------------------
67 // Static Functions
68 //------------------------------------------------------------------
69 
70 Language *CPlusPlusLanguage::CreateInstance(lldb::LanguageType language) {
71   if (Language::LanguageIsCPlusPlus(language))
72     return new CPlusPlusLanguage();
73   return nullptr;
74 }
75 
76 void CPlusPlusLanguage::MethodName::Clear() {
77   m_full.Clear();
78   m_basename = llvm::StringRef();
79   m_context = llvm::StringRef();
80   m_arguments = llvm::StringRef();
81   m_qualifiers = llvm::StringRef();
82   m_type = eTypeInvalid;
83   m_parsed = false;
84   m_parse_error = false;
85 }
86 
87 bool ReverseFindMatchingChars(const llvm::StringRef &s,
88                               const llvm::StringRef &left_right_chars,
89                               size_t &left_pos, size_t &right_pos,
90                               size_t pos = llvm::StringRef::npos) {
91   assert(left_right_chars.size() == 2);
92   left_pos = llvm::StringRef::npos;
93   const char left_char = left_right_chars[0];
94   const char right_char = left_right_chars[1];
95   pos = s.find_last_of(left_right_chars, pos);
96   if (pos == llvm::StringRef::npos || s[pos] == left_char)
97     return false;
98   right_pos = pos;
99   uint32_t depth = 1;
100   while (pos > 0 && depth > 0) {
101     pos = s.find_last_of(left_right_chars, pos);
102     if (pos == llvm::StringRef::npos)
103       return false;
104     if (s[pos] == left_char) {
105       if (--depth == 0) {
106         left_pos = pos;
107         return left_pos < right_pos;
108       }
109     } else if (s[pos] == right_char) {
110       ++depth;
111     }
112   }
113   return false;
114 }
115 
116 static bool IsValidBasename(const llvm::StringRef &basename) {
117   // Check that the basename matches with the following regular expression or is
118   // an operator name:
119   // "^~?([A-Za-z_][A-Za-z_0-9]*)(<.*>)?$"
120   // We are using a hand written implementation because it is significantly more
121   // efficient then
122   // using the general purpose regular expression library.
123   size_t idx = 0;
124   if (basename.size() > 0 && basename[0] == '~')
125     idx = 1;
126 
127   if (basename.size() <= idx)
128     return false; // Empty string or "~"
129 
130   if (!std::isalpha(basename[idx]) && basename[idx] != '_')
131     return false; // First charater (after removing the possible '~'') isn't in
132                   // [A-Za-z_]
133 
134   // Read all characters matching [A-Za-z_0-9]
135   ++idx;
136   while (idx < basename.size()) {
137     if (!std::isalnum(basename[idx]) && basename[idx] != '_')
138       break;
139     ++idx;
140   }
141 
142   // We processed all characters. It is a vaild basename.
143   if (idx == basename.size())
144     return true;
145 
146   // Check for basename with template arguments
147   // TODO: Improve the quality of the validation with validating the template
148   // arguments
149   if (basename[idx] == '<' && basename.back() == '>')
150     return true;
151 
152   // Check if the basename is a vaild C++ operator name
153   if (!basename.startswith("operator"))
154     return false;
155 
156   static RegularExpression g_operator_regex(
157       llvm::StringRef("^(operator)( "
158                       "?)([A-Za-z_][A-Za-z_0-9]*|\\(\\)|"
159                       "\\[\\]|[\\^<>=!\\/"
160                       "*+-]+)(<.*>)?(\\[\\])?$"));
161   std::string basename_str(basename.str());
162   return g_operator_regex.Execute(basename_str, nullptr);
163 }
164 
165 void CPlusPlusLanguage::MethodName::Parse() {
166   if (!m_parsed && m_full) {
167     //        ConstString mangled;
168     //        m_full.GetMangledCounterpart(mangled);
169     //        printf ("\n   parsing = '%s'\n", m_full.GetCString());
170     //        if (mangled)
171     //            printf ("   mangled = '%s'\n", mangled.GetCString());
172     m_parse_error = false;
173     m_parsed = true;
174     llvm::StringRef full(m_full.GetCString());
175 
176     size_t arg_start, arg_end;
177     llvm::StringRef parens("()", 2);
178     if (ReverseFindMatchingChars(full, parens, arg_start, arg_end)) {
179       m_arguments = full.substr(arg_start, arg_end - arg_start + 1);
180       if (arg_end + 1 < full.size())
181         m_qualifiers = full.substr(arg_end + 1);
182       if (arg_start > 0) {
183         size_t basename_end = arg_start;
184         size_t context_start = 0;
185         size_t context_end = llvm::StringRef::npos;
186         if (basename_end > 0 && full[basename_end - 1] == '>') {
187           // TODO: handle template junk...
188           // Templated function
189           size_t template_start, template_end;
190           llvm::StringRef lt_gt("<>", 2);
191           if (ReverseFindMatchingChars(full, lt_gt, template_start,
192                                        template_end, basename_end)) {
193             // Check for templated functions that include return type like:
194             // 'void foo<Int>()'
195             context_start = full.rfind(' ', template_start);
196             if (context_start == llvm::StringRef::npos)
197               context_start = 0;
198             else
199               ++context_start;
200 
201             context_end = full.rfind(':', template_start);
202             if (context_end == llvm::StringRef::npos ||
203                 context_end < context_start)
204               context_end = context_start;
205           } else {
206             context_end = full.rfind(':', basename_end);
207           }
208         } else if (context_end == llvm::StringRef::npos) {
209           context_end = full.rfind(':', basename_end);
210         }
211 
212         if (context_end == llvm::StringRef::npos)
213           m_basename = full.substr(0, basename_end);
214         else {
215           if (context_start < context_end)
216             m_context =
217                 full.substr(context_start, context_end - 1 - context_start);
218           const size_t basename_begin = context_end + 1;
219           m_basename =
220               full.substr(basename_begin, basename_end - basename_begin);
221         }
222         m_type = eTypeUnknownMethod;
223       } else {
224         m_parse_error = true;
225         return;
226       }
227 
228       if (!IsValidBasename(m_basename)) {
229         // The C++ basename doesn't match our regular expressions so this can't
230         // be a valid C++ method, clear everything out and indicate an error
231         m_context = llvm::StringRef();
232         m_basename = llvm::StringRef();
233         m_arguments = llvm::StringRef();
234         m_qualifiers = llvm::StringRef();
235         m_parse_error = true;
236       }
237     } else {
238       m_parse_error = true;
239     }
240   }
241 }
242 
243 llvm::StringRef CPlusPlusLanguage::MethodName::GetBasename() {
244   if (!m_parsed)
245     Parse();
246   return m_basename;
247 }
248 
249 llvm::StringRef CPlusPlusLanguage::MethodName::GetContext() {
250   if (!m_parsed)
251     Parse();
252   return m_context;
253 }
254 
255 llvm::StringRef CPlusPlusLanguage::MethodName::GetArguments() {
256   if (!m_parsed)
257     Parse();
258   return m_arguments;
259 }
260 
261 llvm::StringRef CPlusPlusLanguage::MethodName::GetQualifiers() {
262   if (!m_parsed)
263     Parse();
264   return m_qualifiers;
265 }
266 
267 std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() {
268   if (!m_parsed)
269     Parse();
270   if (m_basename.empty() || m_context.empty())
271     return std::string();
272 
273   std::string res;
274   res += m_context;
275   res += "::";
276   res += m_basename;
277 
278   return res;
279 }
280 
281 bool CPlusPlusLanguage::IsCPPMangledName(const char *name) {
282   // FIXME, we should really run through all the known C++ Language plugins and
283   // ask each one if
284   // this is a C++ mangled name, but we can put that off till there is actually
285   // more than one
286   // we care about.
287 
288   return (name != nullptr && name[0] == '_' && name[1] == 'Z');
289 }
290 
291 bool CPlusPlusLanguage::ExtractContextAndIdentifier(
292     const char *name, llvm::StringRef &context, llvm::StringRef &identifier) {
293   static RegularExpression g_basename_regex(llvm::StringRef(
294       "^(([A-Za-z_][A-Za-z_0-9]*::)*)(~?[A-Za-z_~][A-Za-z_0-9]*)$"));
295   RegularExpression::Match match(4);
296   if (g_basename_regex.Execute(llvm::StringRef::withNullAsEmpty(name),
297                                &match)) {
298     match.GetMatchAtIndex(name, 1, context);
299     match.GetMatchAtIndex(name, 3, identifier);
300     return true;
301   }
302   return false;
303 }
304 
305 class CPPRuntimeEquivalents {
306 public:
307   CPPRuntimeEquivalents() {
308     m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, "
309                               "std::allocator<char> >")
310                       .AsCString(),
311                   ConstString("basic_string<char>"));
312 
313     // these two (with a prefixed std::) occur when c++stdlib string class
314     // occurs as a template argument in some STL container
315     m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, "
316                               "std::allocator<char> >")
317                       .AsCString(),
318                   ConstString("std::basic_string<char>"));
319 
320     m_impl.Sort();
321   }
322 
323   void Add(ConstString &type_name, ConstString &type_equivalent) {
324     m_impl.Insert(type_name.AsCString(), type_equivalent);
325   }
326 
327   uint32_t FindExactMatches(ConstString &type_name,
328                             std::vector<ConstString> &equivalents) {
329     uint32_t count = 0;
330 
331     for (ImplData match = m_impl.FindFirstValueForName(type_name.AsCString());
332          match != nullptr; match = m_impl.FindNextValueForName(match)) {
333       equivalents.push_back(match->value);
334       count++;
335     }
336 
337     return count;
338   }
339 
340   // partial matches can occur when a name with equivalents is a template
341   // argument.
342   // e.g. we may have "class Foo" be a match for "struct Bar". if we have a
343   // typename
344   // such as "class Templatized<class Foo, Anything>" we want this to be
345   // replaced with
346   // "class Templatized<struct Bar, Anything>". Since partial matching is time
347   // consuming
348   // once we get a partial match, we add it to the exact matches list for faster
349   // retrieval
350   uint32_t FindPartialMatches(ConstString &type_name,
351                               std::vector<ConstString> &equivalents) {
352     uint32_t count = 0;
353 
354     const char *type_name_cstr = type_name.AsCString();
355 
356     size_t items_count = m_impl.GetSize();
357 
358     for (size_t item = 0; item < items_count; item++) {
359       const char *key_cstr = m_impl.GetCStringAtIndex(item);
360       if (strstr(type_name_cstr, key_cstr)) {
361         count += AppendReplacements(type_name_cstr, key_cstr, equivalents);
362       }
363     }
364 
365     return count;
366   }
367 
368 private:
369   std::string &replace(std::string &target, std::string &pattern,
370                        std::string &with) {
371     size_t pos;
372     size_t pattern_len = pattern.size();
373 
374     while ((pos = target.find(pattern)) != std::string::npos)
375       target.replace(pos, pattern_len, with);
376 
377     return target;
378   }
379 
380   uint32_t AppendReplacements(const char *original, const char *matching_key,
381                               std::vector<ConstString> &equivalents) {
382     std::string matching_key_str(matching_key);
383     ConstString original_const(original);
384 
385     uint32_t count = 0;
386 
387     for (ImplData match = m_impl.FindFirstValueForName(matching_key);
388          match != nullptr; match = m_impl.FindNextValueForName(match)) {
389       std::string target(original);
390       std::string equiv_class(match->value.AsCString());
391 
392       replace(target, matching_key_str, equiv_class);
393 
394       ConstString target_const(target.c_str());
395 
396 // you will most probably want to leave this off since it might make this map
397 // grow indefinitely
398 #ifdef ENABLE_CPP_EQUIVALENTS_MAP_TO_GROW
399       Add(original_const, target_const);
400 #endif
401       equivalents.push_back(target_const);
402 
403       count++;
404     }
405 
406     return count;
407   }
408 
409   typedef UniqueCStringMap<ConstString> Impl;
410   typedef const Impl::Entry *ImplData;
411   Impl m_impl;
412 };
413 
414 static CPPRuntimeEquivalents &GetEquivalentsMap() {
415   static CPPRuntimeEquivalents g_equivalents_map;
416   return g_equivalents_map;
417 }
418 
419 uint32_t
420 CPlusPlusLanguage::FindEquivalentNames(ConstString type_name,
421                                        std::vector<ConstString> &equivalents) {
422   uint32_t count = GetEquivalentsMap().FindExactMatches(type_name, equivalents);
423 
424   bool might_have_partials =
425       (count == 0) // if we have a full name match just use it
426       && (strchr(type_name.AsCString(), '<') !=
427               nullptr // we should only have partial matches when templates are
428                       // involved, check that we have
429           && strchr(type_name.AsCString(), '>') != nullptr); // angle brackets
430                                                              // in the type_name
431                                                              // before trying to
432                                                              // scan for partial
433                                                              // matches
434 
435   if (might_have_partials)
436     count = GetEquivalentsMap().FindPartialMatches(type_name, equivalents);
437 
438   return count;
439 }
440 
441 static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
442   if (!cpp_category_sp)
443     return;
444 
445   TypeSummaryImpl::Flags stl_summary_flags;
446   stl_summary_flags.SetCascades(true)
447       .SetSkipPointers(false)
448       .SetSkipReferences(false)
449       .SetDontShowChildren(true)
450       .SetDontShowValue(true)
451       .SetShowMembersOneLiner(false)
452       .SetHideItemNames(false);
453 
454 #ifndef LLDB_DISABLE_PYTHON
455   lldb::TypeSummaryImplSP std_string_summary_sp(new CXXFunctionSummaryFormat(
456       stl_summary_flags, lldb_private::formatters::LibcxxStringSummaryProvider,
457       "std::string summary provider"));
458   lldb::TypeSummaryImplSP std_wstring_summary_sp(new CXXFunctionSummaryFormat(
459       stl_summary_flags, lldb_private::formatters::LibcxxWStringSummaryProvider,
460       "std::wstring summary provider"));
461 
462   cpp_category_sp->GetTypeSummariesContainer()->Add(
463       ConstString("std::__1::string"), std_string_summary_sp);
464   cpp_category_sp->GetTypeSummariesContainer()->Add(
465       ConstString("std::__ndk1::string"), std_string_summary_sp);
466   cpp_category_sp->GetTypeSummariesContainer()->Add(
467       ConstString("std::__1::basic_string<char, std::__1::char_traits<char>, "
468                   "std::__1::allocator<char> >"),
469       std_string_summary_sp);
470   cpp_category_sp->GetTypeSummariesContainer()->Add(
471       ConstString("std::__ndk1::basic_string<char, "
472                   "std::__ndk1::char_traits<char>, "
473                   "std::__ndk1::allocator<char> >"),
474       std_string_summary_sp);
475 
476   cpp_category_sp->GetTypeSummariesContainer()->Add(
477       ConstString("std::__1::wstring"), std_wstring_summary_sp);
478   cpp_category_sp->GetTypeSummariesContainer()->Add(
479       ConstString("std::__ndk1::wstring"), std_wstring_summary_sp);
480   cpp_category_sp->GetTypeSummariesContainer()->Add(
481       ConstString("std::__1::basic_string<wchar_t, "
482                   "std::__1::char_traits<wchar_t>, "
483                   "std::__1::allocator<wchar_t> >"),
484       std_wstring_summary_sp);
485   cpp_category_sp->GetTypeSummariesContainer()->Add(
486       ConstString("std::__ndk1::basic_string<wchar_t, "
487                   "std::__ndk1::char_traits<wchar_t>, "
488                   "std::__ndk1::allocator<wchar_t> >"),
489       std_wstring_summary_sp);
490 
491   SyntheticChildren::Flags stl_synth_flags;
492   stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
493       false);
494 
495   AddCXXSynthetic(
496       cpp_category_sp,
497       lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator,
498       "libc++ std::vector<bool> synthetic children",
499       ConstString(
500           "^std::__(ndk)?1::vector<bool, std::__(ndk)?1::allocator<bool> >$"),
501       stl_synth_flags, true);
502   AddCXXSynthetic(
503       cpp_category_sp,
504       lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator,
505       "libc++ std::vector synthetic children",
506       ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_synth_flags,
507       true);
508   AddCXXSynthetic(
509       cpp_category_sp,
510       lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator,
511       "libc++ std::list synthetic children",
512       ConstString("^std::__(ndk)?1::list<.+>(( )?&)?$"), stl_synth_flags, true);
513   AddCXXSynthetic(
514       cpp_category_sp,
515       lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
516       "libc++ std::map synthetic children",
517       ConstString("^std::__(ndk)?1::map<.+> >(( )?&)?$"), stl_synth_flags,
518       true);
519   AddCXXSynthetic(
520       cpp_category_sp,
521       lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator,
522       "libc++ std::vector<bool> synthetic children",
523       ConstString("std::__(ndk)?1::vector<std::__(ndk)?1::allocator<bool> >"),
524       stl_synth_flags);
525   AddCXXSynthetic(
526       cpp_category_sp,
527       lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator,
528       "libc++ std::vector<bool> synthetic children",
529       ConstString(
530           "std::__(ndk)?1::vector<bool, std::__(ndk)?1::allocator<bool> >"),
531       stl_synth_flags);
532   AddCXXSynthetic(
533       cpp_category_sp,
534       lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
535       "libc++ std::set synthetic children",
536       ConstString("^std::__(ndk)?1::set<.+> >(( )?&)?$"), stl_synth_flags,
537       true);
538   AddCXXSynthetic(
539       cpp_category_sp,
540       lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
541       "libc++ std::multiset synthetic children",
542       ConstString("^std::__(ndk)?1::multiset<.+> >(( )?&)?$"), stl_synth_flags,
543       true);
544   AddCXXSynthetic(
545       cpp_category_sp,
546       lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
547       "libc++ std::multimap synthetic children",
548       ConstString("^std::__(ndk)?1::multimap<.+> >(( )?&)?$"), stl_synth_flags,
549       true);
550   AddCXXSynthetic(
551       cpp_category_sp,
552       lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator,
553       "libc++ std::unordered containers synthetic children",
554       ConstString("^(std::__(ndk)?1::)unordered_(multi)?(map|set)<.+> >$"),
555       stl_synth_flags, true);
556   AddCXXSynthetic(
557       cpp_category_sp,
558       lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator,
559       "libc++ std::initializer_list synthetic children",
560       ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags,
561       true);
562   AddCXXSynthetic(
563       cpp_category_sp,
564       lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator,
565       "libc++ std::atomic synthetic children",
566       ConstString("^std::__(ndk)?1::atomic<.+>$"), stl_synth_flags, true);
567 
568   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
569       RegularExpressionSP(new RegularExpression(
570           llvm::StringRef("^(std::__(ndk)?1::)deque<.+>(( )?&)?$"))),
571       SyntheticChildrenSP(new ScriptedSyntheticChildren(
572           stl_synth_flags,
573           "lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));
574 
575   AddCXXSynthetic(
576       cpp_category_sp,
577       lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,
578       "shared_ptr synthetic children",
579       ConstString("^(std::__(ndk)?1::)shared_ptr<.+>(( )?&)?$"),
580       stl_synth_flags, true);
581   AddCXXSynthetic(
582       cpp_category_sp,
583       lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,
584       "weak_ptr synthetic children",
585       ConstString("^(std::__(ndk)?1::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags,
586       true);
587 
588   stl_summary_flags.SetDontShowChildren(false);
589   stl_summary_flags.SetSkipPointers(false);
590   AddCXXSummary(
591       cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider,
592       "libc++ std::vector<bool> summary provider",
593       ConstString(
594           "std::__(ndk)?1::vector<bool, std::__(ndk)?1::allocator<bool> >"),
595       stl_summary_flags, true);
596   AddCXXSummary(cpp_category_sp,
597                 lldb_private::formatters::LibcxxContainerSummaryProvider,
598                 "libc++ std::vector summary provider",
599                 ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"),
600                 stl_summary_flags, true);
601   AddCXXSummary(cpp_category_sp,
602                 lldb_private::formatters::LibcxxContainerSummaryProvider,
603                 "libc++ std::list summary provider",
604                 ConstString("^std::__(ndk)?1::list<.+>(( )?&)?$"),
605                 stl_summary_flags, true);
606   AddCXXSummary(cpp_category_sp,
607                 lldb_private::formatters::LibcxxContainerSummaryProvider,
608                 "libc++ std::map summary provider",
609                 ConstString("^std::__(ndk)?1::map<.+>(( )?&)?$"),
610                 stl_summary_flags, true);
611   AddCXXSummary(cpp_category_sp,
612                 lldb_private::formatters::LibcxxContainerSummaryProvider,
613                 "libc++ std::deque summary provider",
614                 ConstString("^std::__(ndk)?1::deque<.+>(( )?&)?$"),
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(
637       cpp_category_sp, lldb_private::formatters::LibCxxAtomicSummaryProvider,
638       "libc++ std::atomic summary provider",
639       ConstString("^std::__(ndk)?1::atomic<.+>$"), stl_summary_flags, true);
640 
641   stl_summary_flags.SetSkipPointers(true);
642 
643   AddCXXSummary(cpp_category_sp,
644                 lldb_private::formatters::LibcxxSmartPointerSummaryProvider,
645                 "libc++ std::shared_ptr summary provider",
646                 ConstString("^std::__(ndk)?1::shared_ptr<.+>(( )?&)?$"),
647                 stl_summary_flags, true);
648   AddCXXSummary(cpp_category_sp,
649                 lldb_private::formatters::LibcxxSmartPointerSummaryProvider,
650                 "libc++ std::weak_ptr summary provider",
651                 ConstString("^std::__(ndk)?1::weak_ptr<.+>(( )?&)?$"),
652                 stl_summary_flags, true);
653 
654   AddCXXSynthetic(
655       cpp_category_sp,
656       lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator,
657       "std::vector iterator synthetic children",
658       ConstString("^std::__(ndk)?1::__wrap_iter<.+>$"), stl_synth_flags, true);
659 
660   AddCXXSummary(
661       cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider,
662       "libc++ std::vector<bool> summary provider",
663       ConstString(
664           "std::__(ndk)?1::vector<bool, std::__(ndk)?1::allocator<bool> >"),
665       stl_summary_flags);
666   AddCXXSynthetic(
667       cpp_category_sp,
668       lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator,
669       "std::map iterator synthetic children",
670       ConstString("^std::__(ndk)?1::__map_iterator<.+>$"), stl_synth_flags,
671       true);
672 
673   AddCXXSynthetic(
674       cpp_category_sp, lldb_private::formatters::LibcxxFunctionFrontEndCreator,
675       "std::function synthetic value provider",
676       ConstString("^std::__1::function<.+>$"), stl_synth_flags, true);
677 #endif
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 #ifndef LLDB_DISABLE_PYTHON
749 
750   SyntheticChildren::Flags stl_synth_flags;
751   stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
752       false);
753 
754   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
755       RegularExpressionSP(
756           new RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$"))),
757       SyntheticChildrenSP(new ScriptedSyntheticChildren(
758           stl_synth_flags,
759           "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
760   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
761       RegularExpressionSP(
762           new RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$"))),
763       SyntheticChildrenSP(new ScriptedSyntheticChildren(
764           stl_synth_flags,
765           "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider")));
766   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
767       RegularExpressionSP(new RegularExpression(
768           llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$"))),
769       SyntheticChildrenSP(new ScriptedSyntheticChildren(
770           stl_synth_flags,
771           "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
772   stl_summary_flags.SetDontShowChildren(false);
773   stl_summary_flags.SetSkipPointers(true);
774   cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
775       RegularExpressionSP(
776           new RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$"))),
777       TypeSummaryImplSP(
778           new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
779   cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
780       RegularExpressionSP(
781           new RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$"))),
782       TypeSummaryImplSP(
783           new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
784   cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
785       RegularExpressionSP(new RegularExpression(
786           llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$"))),
787       TypeSummaryImplSP(
788           new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
789 
790   AddCXXSynthetic(
791       cpp_category_sp,
792       lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator,
793       "std::vector iterator synthetic children",
794       ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
795 
796   AddCXXSynthetic(
797       cpp_category_sp,
798       lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator,
799       "std::map iterator synthetic children",
800       ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
801 
802   AddCXXSynthetic(
803       cpp_category_sp,
804       lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator,
805       "std::shared_ptr synthetic children",
806       ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
807   AddCXXSynthetic(
808       cpp_category_sp,
809       lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator,
810       "std::weak_ptr synthetic children",
811       ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
812 
813   AddCXXSummary(cpp_category_sp,
814                 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider,
815                 "libstdc++ std::shared_ptr summary provider",
816                 ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_summary_flags,
817                 true);
818   AddCXXSummary(cpp_category_sp,
819                 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider,
820                 "libstdc++ std::weak_ptr summary provider",
821                 ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_summary_flags,
822                 true);
823 #endif
824 }
825 
826 static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
827   if (!cpp_category_sp)
828     return;
829 
830   TypeSummaryImpl::Flags string_flags;
831   string_flags.SetCascades(true)
832       .SetSkipPointers(true)
833       .SetSkipReferences(false)
834       .SetDontShowChildren(true)
835       .SetDontShowValue(false)
836       .SetShowMembersOneLiner(false)
837       .SetHideItemNames(false);
838 
839   TypeSummaryImpl::Flags string_array_flags;
840   string_array_flags.SetCascades(true)
841       .SetSkipPointers(true)
842       .SetSkipReferences(false)
843       .SetDontShowChildren(true)
844       .SetDontShowValue(true)
845       .SetShowMembersOneLiner(false)
846       .SetHideItemNames(false);
847 
848 #ifndef LLDB_DISABLE_PYTHON
849   // FIXME because of a bug in the FormattersContainer we need to add a summary
850   // for both X* and const X* (<rdar://problem/12717717>)
851   AddCXXSummary(
852       cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider,
853       "char16_t * summary provider", ConstString("char16_t *"), string_flags);
854   AddCXXSummary(cpp_category_sp,
855                 lldb_private::formatters::Char16StringSummaryProvider,
856                 "char16_t [] summary provider",
857                 ConstString("char16_t \\[[0-9]+\\]"), string_array_flags, true);
858 
859   AddCXXSummary(
860       cpp_category_sp, lldb_private::formatters::Char32StringSummaryProvider,
861       "char32_t * summary provider", ConstString("char32_t *"), string_flags);
862   AddCXXSummary(cpp_category_sp,
863                 lldb_private::formatters::Char32StringSummaryProvider,
864                 "char32_t [] summary provider",
865                 ConstString("char32_t \\[[0-9]+\\]"), string_array_flags, true);
866 
867   AddCXXSummary(
868       cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider,
869       "wchar_t * summary provider", ConstString("wchar_t *"), string_flags);
870   AddCXXSummary(cpp_category_sp,
871                 lldb_private::formatters::WCharStringSummaryProvider,
872                 "wchar_t * summary provider",
873                 ConstString("wchar_t \\[[0-9]+\\]"), string_array_flags, true);
874 
875   AddCXXSummary(
876       cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider,
877       "unichar * summary provider", ConstString("unichar *"), string_flags);
878 
879   TypeSummaryImpl::Flags widechar_flags;
880   widechar_flags.SetDontShowValue(true)
881       .SetSkipPointers(true)
882       .SetSkipReferences(false)
883       .SetCascades(true)
884       .SetDontShowChildren(true)
885       .SetHideItemNames(true)
886       .SetShowMembersOneLiner(false);
887 
888   AddCXXSummary(
889       cpp_category_sp, lldb_private::formatters::Char16SummaryProvider,
890       "char16_t summary provider", ConstString("char16_t"), widechar_flags);
891   AddCXXSummary(
892       cpp_category_sp, lldb_private::formatters::Char32SummaryProvider,
893       "char32_t summary provider", ConstString("char32_t"), widechar_flags);
894   AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharSummaryProvider,
895                 "wchar_t summary provider", ConstString("wchar_t"),
896                 widechar_flags);
897 
898   AddCXXSummary(
899       cpp_category_sp, lldb_private::formatters::Char16SummaryProvider,
900       "unichar summary provider", ConstString("unichar"), widechar_flags);
901 #endif
902 }
903 
904 lldb::TypeCategoryImplSP CPlusPlusLanguage::GetFormatters() {
905   static std::once_flag g_initialize;
906   static TypeCategoryImplSP g_category;
907 
908   std::call_once(g_initialize, [this]() -> void {
909     DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
910     if (g_category) {
911       LoadLibCxxFormatters(g_category);
912       LoadLibStdcppFormatters(g_category);
913       LoadSystemFormatters(g_category);
914     }
915   });
916   return g_category;
917 }
918 
919 HardcodedFormatters::HardcodedSummaryFinder
920 CPlusPlusLanguage::GetHardcodedSummaries() {
921   static std::once_flag g_initialize;
922   static ConstString g_vectortypes("VectorTypes");
923   static HardcodedFormatters::HardcodedSummaryFinder g_formatters;
924 
925   std::call_once(g_initialize, []() -> void {
926     g_formatters.push_back(
927         [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
928            FormatManager &) -> TypeSummaryImpl::SharedPointer {
929           static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
930               new CXXFunctionSummaryFormat(
931                   TypeSummaryImpl::Flags(),
932                   lldb_private::formatters::CXXFunctionPointerSummaryProvider,
933                   "Function pointer summary provider"));
934           if (valobj.GetCompilerType().IsFunctionPointerType()) {
935             return formatter_sp;
936           }
937           return nullptr;
938         });
939     g_formatters.push_back(
940         [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
941            FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer {
942           static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
943               new CXXFunctionSummaryFormat(
944                   TypeSummaryImpl::Flags()
945                       .SetCascades(true)
946                       .SetDontShowChildren(true)
947                       .SetHideItemNames(true)
948                       .SetShowMembersOneLiner(true)
949                       .SetSkipPointers(true)
950                       .SetSkipReferences(false),
951                   lldb_private::formatters::VectorTypeSummaryProvider,
952                   "vector_type pointer summary provider"));
953           if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) {
954             if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
955               return formatter_sp;
956           }
957           return nullptr;
958         });
959     g_formatters.push_back(
960         [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
961            FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer {
962           static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
963               new CXXFunctionSummaryFormat(
964                   TypeSummaryImpl::Flags()
965                       .SetCascades(true)
966                       .SetDontShowChildren(true)
967                       .SetHideItemNames(true)
968                       .SetShowMembersOneLiner(true)
969                       .SetSkipPointers(true)
970                       .SetSkipReferences(false),
971                   lldb_private::formatters::BlockPointerSummaryProvider,
972                   "block pointer summary provider"));
973           if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) {
974             return formatter_sp;
975           }
976           return nullptr;
977         });
978   });
979 
980   return g_formatters;
981 }
982 
983 HardcodedFormatters::HardcodedSyntheticFinder
984 CPlusPlusLanguage::GetHardcodedSynthetics() {
985   static std::once_flag g_initialize;
986   static ConstString g_vectortypes("VectorTypes");
987   static HardcodedFormatters::HardcodedSyntheticFinder g_formatters;
988 
989   std::call_once(g_initialize, []() -> void {
990     g_formatters.push_back([](lldb_private::ValueObject &valobj,
991                               lldb::DynamicValueType,
992                               FormatManager &
993                                   fmt_mgr) -> SyntheticChildren::SharedPointer {
994       static CXXSyntheticChildren::SharedPointer formatter_sp(
995           new CXXSyntheticChildren(
996               SyntheticChildren::Flags()
997                   .SetCascades(true)
998                   .SetSkipPointers(true)
999                   .SetSkipReferences(true)
1000                   .SetNonCacheable(true),
1001               "vector_type synthetic children",
1002               lldb_private::formatters::VectorTypeSyntheticFrontEndCreator));
1003       if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) {
1004         if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
1005           return formatter_sp;
1006       }
1007       return nullptr;
1008     });
1009     g_formatters.push_back([](lldb_private::ValueObject &valobj,
1010                               lldb::DynamicValueType,
1011                               FormatManager &
1012                                   fmt_mgr) -> SyntheticChildren::SharedPointer {
1013       static CXXSyntheticChildren::SharedPointer formatter_sp(
1014           new CXXSyntheticChildren(
1015               SyntheticChildren::Flags()
1016                   .SetCascades(true)
1017                   .SetSkipPointers(true)
1018                   .SetSkipReferences(true)
1019                   .SetNonCacheable(true),
1020               "block pointer synthetic children",
1021               lldb_private::formatters::BlockPointerSyntheticFrontEndCreator));
1022       if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) {
1023         return formatter_sp;
1024       }
1025       return nullptr;
1026     });
1027 
1028   });
1029 
1030   return g_formatters;
1031 }
1032