1 //===-- CPlusPlusLanguage.cpp -----------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "CPlusPlusLanguage.h"
22 // Other libraries and framework includes
23 #include "llvm/ADT/StringRef.h"
26 #include "lldb/Core/PluginManager.h"
27 #include "lldb/Core/UniqueCStringMap.h"
28 #include "lldb/DataFormatters/CXXFunctionPointer.h"
29 #include "lldb/DataFormatters/DataVisualization.h"
30 #include "lldb/DataFormatters/FormattersHelpers.h"
31 #include "lldb/DataFormatters/VectorType.h"
32 #include "lldb/Utility/ConstString.h"
33 #include "lldb/Utility/FastDemangle.h"
34 #include "lldb/Utility/Log.h"
35 #include "lldb/Utility/RegularExpression.h"
37 #include "BlockPointer.h"
38 #include "CPlusPlusNameParser.h"
39 #include "CxxStringTypes.h"
41 #include "LibCxxAtomic.h"
42 #include "LibStdcpp.h"
45 using namespace lldb_private;
46 using namespace lldb_private::formatters;
48 void CPlusPlusLanguage::Initialize() {
49 PluginManager::RegisterPlugin(GetPluginNameStatic(), "C++ Language",
53 void CPlusPlusLanguage::Terminate() {
54 PluginManager::UnregisterPlugin(CreateInstance);
57 lldb_private::ConstString CPlusPlusLanguage::GetPluginNameStatic() {
58 static ConstString g_name("cplusplus");
62 //------------------------------------------------------------------
63 // PluginInterface protocol
64 //------------------------------------------------------------------
66 lldb_private::ConstString CPlusPlusLanguage::GetPluginName() {
67 return GetPluginNameStatic();
70 uint32_t CPlusPlusLanguage::GetPluginVersion() { return 1; }
72 //------------------------------------------------------------------
74 //------------------------------------------------------------------
76 Language *CPlusPlusLanguage::CreateInstance(lldb::LanguageType language) {
77 if (Language::LanguageIsCPlusPlus(language))
78 return new CPlusPlusLanguage();
82 void CPlusPlusLanguage::MethodName::Clear() {
84 m_basename = llvm::StringRef();
85 m_context = llvm::StringRef();
86 m_arguments = llvm::StringRef();
87 m_qualifiers = llvm::StringRef();
89 m_parse_error = false;
92 static bool ReverseFindMatchingChars(const llvm::StringRef &s,
93 const llvm::StringRef &left_right_chars,
94 size_t &left_pos, size_t &right_pos,
95 size_t pos = llvm::StringRef::npos) {
96 assert(left_right_chars.size() == 2);
97 left_pos = llvm::StringRef::npos;
98 const char left_char = left_right_chars[0];
99 const char right_char = left_right_chars[1];
100 pos = s.find_last_of(left_right_chars, pos);
101 if (pos == llvm::StringRef::npos || s[pos] == left_char)
105 while (pos > 0 && depth > 0) {
106 pos = s.find_last_of(left_right_chars, pos);
107 if (pos == llvm::StringRef::npos)
109 if (s[pos] == left_char) {
112 return left_pos < right_pos;
114 } else if (s[pos] == right_char) {
121 static bool IsTrivialBasename(const llvm::StringRef &basename) {
122 // Check that the basename matches with the following regular expression
123 // "^~?([A-Za-z_][A-Za-z_0-9]*)$" We are using a hand written implementation
124 // because it is significantly more efficient then using the general purpose
125 // regular expression library.
127 if (basename.size() > 0 && basename[0] == '~')
130 if (basename.size() <= idx)
131 return false; // Empty string or "~"
133 if (!std::isalpha(basename[idx]) && basename[idx] != '_')
134 return false; // First charater (after removing the possible '~'') isn't in
137 // Read all characters matching [A-Za-z_0-9]
139 while (idx < basename.size()) {
140 if (!std::isalnum(basename[idx]) && basename[idx] != '_')
145 // We processed all characters. It is a vaild basename.
146 if (idx == basename.size())
152 bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() {
153 // This method tries to parse simple method definitions which are presumably
154 // most comman in user programs. Definitions that can be parsed by this
155 // function don't have return types and templates in the name.
156 // A::B::C::fun(std::vector<T> &) const
157 size_t arg_start, arg_end;
158 llvm::StringRef full(m_full.GetCString());
159 llvm::StringRef parens("()", 2);
160 if (ReverseFindMatchingChars(full, parens, arg_start, arg_end)) {
161 m_arguments = full.substr(arg_start, arg_end - arg_start + 1);
162 if (arg_end + 1 < full.size())
163 m_qualifiers = full.substr(arg_end + 1).ltrim();
167 size_t basename_end = arg_start;
168 size_t context_start = 0;
169 size_t context_end = full.rfind(':', basename_end);
170 if (context_end == llvm::StringRef::npos)
171 m_basename = full.substr(0, basename_end);
173 if (context_start < context_end)
174 m_context = full.substr(context_start, context_end - 1 - context_start);
175 const size_t basename_begin = context_end + 1;
176 m_basename = full.substr(basename_begin, basename_end - basename_begin);
179 if (IsTrivialBasename(m_basename)) {
182 // The C++ basename doesn't match our regular expressions so this can't
183 // be a valid C++ method, clear everything out and indicate an error
184 m_context = llvm::StringRef();
185 m_basename = llvm::StringRef();
186 m_arguments = llvm::StringRef();
187 m_qualifiers = llvm::StringRef();
194 void CPlusPlusLanguage::MethodName::Parse() {
195 if (!m_parsed && m_full) {
196 if (TrySimplifiedParse()) {
197 m_parse_error = false;
199 CPlusPlusNameParser parser(m_full.GetStringRef());
200 if (auto function = parser.ParseAsFunctionDefinition()) {
201 m_basename = function.getValue().name.basename;
202 m_context = function.getValue().name.context;
203 m_arguments = function.getValue().arguments;
204 m_qualifiers = function.getValue().qualifiers;
205 m_parse_error = false;
207 m_parse_error = true;
214 llvm::StringRef CPlusPlusLanguage::MethodName::GetBasename() {
220 llvm::StringRef CPlusPlusLanguage::MethodName::GetContext() {
226 llvm::StringRef CPlusPlusLanguage::MethodName::GetArguments() {
232 llvm::StringRef CPlusPlusLanguage::MethodName::GetQualifiers() {
238 std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() {
241 if (m_context.empty())
251 bool CPlusPlusLanguage::IsCPPMangledName(const char *name) {
252 // FIXME!! we should really run through all the known C++ Language plugins
253 // and ask each one if this is a C++ mangled name
258 // MSVC style mangling
262 return (name[0] != '\0' && name[0] == '_' && name[1] == 'Z');
265 bool CPlusPlusLanguage::ExtractContextAndIdentifier(
266 const char *name, llvm::StringRef &context, llvm::StringRef &identifier) {
267 CPlusPlusNameParser parser(name);
268 if (auto full_name = parser.ParseAsFullName()) {
269 identifier = full_name.getValue().basename;
270 context = full_name.getValue().context;
276 /// Given a mangled function `mangled`, replace all the primitive function type
277 /// arguments of `search` with type `replace`.
278 static ConstString SubsPrimitiveParmItanium(llvm::StringRef mangled,
279 llvm::StringRef search,
280 llvm::StringRef replace) {
281 Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
283 const size_t max_len =
284 mangled.size() + mangled.count(search) * replace.size() + 1;
286 // Make a temporary buffer to fix up the mangled parameter types and copy the
288 std::string output_buf;
289 output_buf.reserve(max_len);
290 output_buf.insert(0, mangled.str());
291 ptrdiff_t replaced_offset = 0;
293 auto swap_parms_hook = [&](const char *parsee) {
294 if (!parsee || !*parsee)
297 // Check whether we've found a substitutee
298 llvm::StringRef s(parsee);
299 if (s.startswith(search)) {
300 // account for the case where a replacement is of a different length to
302 replaced_offset += replace.size() - search.size();
304 ptrdiff_t replace_idx = (mangled.size() - s.size()) + replaced_offset;
305 output_buf.erase(replace_idx, search.size());
306 output_buf.insert(replace_idx, replace.str());
310 // FastDemangle will call our hook for each instance of a primitive type,
311 // allowing us to perform substitution
312 char *const demangled =
313 FastDemangle(mangled.str().c_str(), mangled.size(), swap_parms_hook);
316 log->Printf("substituted mangling for %s:{%s} %s:{%s}\n",
317 mangled.str().c_str(), demangled, output_buf.c_str(),
318 FastDemangle(output_buf.c_str()));
319 // FastDemangle malloc'd this string.
322 return output_buf == mangled ? ConstString() : ConstString(output_buf);
325 uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
326 const ConstString mangled_name, std::set<ConstString> &alternates) {
327 const auto start_size = alternates.size();
328 /// Get a basic set of alternative manglings for the given symbol `name`, by
329 /// making a few basic possible substitutions on basic types, storage duration
330 /// and `const`ness for the given symbol. The output parameter `alternates`
331 /// is filled with a best-guess, non-exhaustive set of different manglings
332 /// for the given name.
334 // Maybe we're looking for a const symbol but the debug info told us it was
336 if (!strncmp(mangled_name.GetCString(), "_ZN", 3) &&
337 strncmp(mangled_name.GetCString(), "_ZNK", 4)) {
338 std::string fixed_scratch("_ZNK");
339 fixed_scratch.append(mangled_name.GetCString() + 3);
340 alternates.insert(ConstString(fixed_scratch));
343 // Maybe we're looking for a static symbol but we thought it was global...
344 if (!strncmp(mangled_name.GetCString(), "_Z", 2) &&
345 strncmp(mangled_name.GetCString(), "_ZL", 3)) {
346 std::string fixed_scratch("_ZL");
347 fixed_scratch.append(mangled_name.GetCString() + 2);
348 alternates.insert(ConstString(fixed_scratch));
351 // `char` is implementation defined as either `signed` or `unsigned`. As a
352 // result a char parameter has 3 possible manglings: 'c'-char, 'a'-signed
353 // char, 'h'-unsigned char. If we're looking for symbols with a signed char
354 // parameter, try finding matches which have the general case 'c'.
355 if (ConstString char_fixup =
356 SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "a", "c"))
357 alternates.insert(char_fixup);
359 // long long parameter mangling 'x', may actually just be a long 'l' argument
360 if (ConstString long_fixup =
361 SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "x", "l"))
362 alternates.insert(long_fixup);
364 // unsigned long long parameter mangling 'y', may actually just be unsigned
366 if (ConstString ulong_fixup =
367 SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "y", "m"))
368 alternates.insert(ulong_fixup);
370 return alternates.size() - start_size;
373 static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
374 if (!cpp_category_sp)
377 TypeSummaryImpl::Flags stl_summary_flags;
378 stl_summary_flags.SetCascades(true)
379 .SetSkipPointers(false)
380 .SetSkipReferences(false)
381 .SetDontShowChildren(true)
382 .SetDontShowValue(true)
383 .SetShowMembersOneLiner(false)
384 .SetHideItemNames(false);
386 #ifndef LLDB_DISABLE_PYTHON
387 lldb::TypeSummaryImplSP std_string_summary_sp(new CXXFunctionSummaryFormat(
388 stl_summary_flags, lldb_private::formatters::LibcxxStringSummaryProvider,
389 "std::string summary provider"));
390 lldb::TypeSummaryImplSP std_wstring_summary_sp(new CXXFunctionSummaryFormat(
391 stl_summary_flags, lldb_private::formatters::LibcxxWStringSummaryProvider,
392 "std::wstring summary provider"));
394 cpp_category_sp->GetTypeSummariesContainer()->Add(
395 ConstString("std::__1::string"), std_string_summary_sp);
396 cpp_category_sp->GetTypeSummariesContainer()->Add(
397 ConstString("std::__ndk1::string"), std_string_summary_sp);
398 cpp_category_sp->GetTypeSummariesContainer()->Add(
399 ConstString("std::__1::basic_string<char, std::__1::char_traits<char>, "
400 "std::__1::allocator<char> >"),
401 std_string_summary_sp);
402 cpp_category_sp->GetTypeSummariesContainer()->Add(
403 ConstString("std::__ndk1::basic_string<char, "
404 "std::__ndk1::char_traits<char>, "
405 "std::__ndk1::allocator<char> >"),
406 std_string_summary_sp);
408 cpp_category_sp->GetTypeSummariesContainer()->Add(
409 ConstString("std::__1::wstring"), std_wstring_summary_sp);
410 cpp_category_sp->GetTypeSummariesContainer()->Add(
411 ConstString("std::__ndk1::wstring"), std_wstring_summary_sp);
412 cpp_category_sp->GetTypeSummariesContainer()->Add(
413 ConstString("std::__1::basic_string<wchar_t, "
414 "std::__1::char_traits<wchar_t>, "
415 "std::__1::allocator<wchar_t> >"),
416 std_wstring_summary_sp);
417 cpp_category_sp->GetTypeSummariesContainer()->Add(
418 ConstString("std::__ndk1::basic_string<wchar_t, "
419 "std::__ndk1::char_traits<wchar_t>, "
420 "std::__ndk1::allocator<wchar_t> >"),
421 std_wstring_summary_sp);
423 SyntheticChildren::Flags stl_synth_flags;
424 stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
426 SyntheticChildren::Flags stl_deref_flags = stl_synth_flags;
427 stl_deref_flags.SetFrontEndWantsDereference();
431 lldb_private::formatters::LibcxxBitsetSyntheticFrontEndCreator,
432 "libc++ std::bitset synthetic children",
433 ConstString("^std::__(ndk)?1::bitset<.+>(( )?&)?$"), stl_deref_flags,
437 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator,
438 "libc++ std::vector synthetic children",
439 ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_deref_flags,
443 lldb_private::formatters::LibcxxStdForwardListSyntheticFrontEndCreator,
444 "libc++ std::forward_list synthetic children",
445 ConstString("^std::__(ndk)?1::forward_list<.+>(( )?&)?$"),
446 stl_synth_flags, true);
449 lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator,
450 "libc++ std::list synthetic children",
451 ConstString("^std::__(ndk)?1::list<.+>(( )?&)?$"), stl_synth_flags, true);
454 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
455 "libc++ std::map synthetic children",
456 ConstString("^std::__(ndk)?1::map<.+> >(( )?&)?$"), stl_synth_flags,
460 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
461 "libc++ std::set synthetic children",
462 ConstString("^std::__(ndk)?1::set<.+> >(( )?&)?$"), stl_deref_flags,
466 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
467 "libc++ std::multiset synthetic children",
468 ConstString("^std::__(ndk)?1::multiset<.+> >(( )?&)?$"), stl_deref_flags,
472 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
473 "libc++ std::multimap synthetic children",
474 ConstString("^std::__(ndk)?1::multimap<.+> >(( )?&)?$"), stl_synth_flags,
478 lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator,
479 "libc++ std::unordered containers synthetic children",
480 ConstString("^(std::__(ndk)?1::)unordered_(multi)?(map|set)<.+> >$"),
481 stl_synth_flags, true);
484 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator,
485 "libc++ std::initializer_list synthetic children",
486 ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags,
488 AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator,
489 "libc++ std::queue synthetic children",
490 ConstString("^std::__(ndk)?1::queue<.+>(( )?&)?$"),
491 stl_synth_flags, true);
492 AddCXXSynthetic(cpp_category_sp, LibcxxTupleFrontEndCreator,
493 "libc++ std::tuple synthetic children",
494 ConstString("^std::__(ndk)?1::tuple<.*>(( )?&)?$"), stl_synth_flags,
498 lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator,
499 "libc++ std::atomic synthetic children",
500 ConstString("^std::__(ndk)?1::atomic<.+>$"), stl_synth_flags, true);
502 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
503 RegularExpressionSP(new RegularExpression(
504 llvm::StringRef("^(std::__(ndk)?1::)deque<.+>(( )?&)?$"))),
505 SyntheticChildrenSP(new ScriptedSyntheticChildren(
507 "lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));
511 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,
512 "shared_ptr synthetic children",
513 ConstString("^(std::__(ndk)?1::)shared_ptr<.+>(( )?&)?$"),
514 stl_synth_flags, true);
517 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,
518 "weak_ptr synthetic children",
519 ConstString("^(std::__(ndk)?1::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags,
522 stl_summary_flags.SetDontShowChildren(false);
523 stl_summary_flags.SetSkipPointers(false);
524 AddCXXSummary(cpp_category_sp,
525 lldb_private::formatters::LibcxxContainerSummaryProvider,
526 "libc++ std::bitset summary provider",
527 ConstString("^std::__(ndk)?1::bitset<.+>(( )?&)?$"),
528 stl_summary_flags, true);
529 AddCXXSummary(cpp_category_sp,
530 lldb_private::formatters::LibcxxContainerSummaryProvider,
531 "libc++ std::vector summary provider",
532 ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"),
533 stl_summary_flags, true);
534 AddCXXSummary(cpp_category_sp,
535 lldb_private::formatters::LibcxxContainerSummaryProvider,
536 "libc++ std::list summary provider",
537 ConstString("^std::__(ndk)?1::forward_list<.+>(( )?&)?$"),
538 stl_summary_flags, true);
539 AddCXXSummary(cpp_category_sp,
540 lldb_private::formatters::LibcxxContainerSummaryProvider,
541 "libc++ std::list summary provider",
542 ConstString("^std::__(ndk)?1::list<.+>(( )?&)?$"),
543 stl_summary_flags, true);
544 AddCXXSummary(cpp_category_sp,
545 lldb_private::formatters::LibcxxContainerSummaryProvider,
546 "libc++ std::map summary provider",
547 ConstString("^std::__(ndk)?1::map<.+>(( )?&)?$"),
548 stl_summary_flags, true);
549 AddCXXSummary(cpp_category_sp,
550 lldb_private::formatters::LibcxxContainerSummaryProvider,
551 "libc++ std::deque summary provider",
552 ConstString("^std::__(ndk)?1::deque<.+>(( )?&)?$"),
553 stl_summary_flags, true);
554 AddCXXSummary(cpp_category_sp,
555 lldb_private::formatters::LibcxxContainerSummaryProvider,
556 "libc++ std::queue summary provider",
557 ConstString("^std::__(ndk)?1::queue<.+>(( )?&)?$"),
558 stl_summary_flags, true);
559 AddCXXSummary(cpp_category_sp,
560 lldb_private::formatters::LibcxxContainerSummaryProvider,
561 "libc++ std::set summary provider",
562 ConstString("^std::__(ndk)?1::set<.+>(( )?&)?$"),
563 stl_summary_flags, true);
564 AddCXXSummary(cpp_category_sp,
565 lldb_private::formatters::LibcxxContainerSummaryProvider,
566 "libc++ std::multiset summary provider",
567 ConstString("^std::__(ndk)?1::multiset<.+>(( )?&)?$"),
568 stl_summary_flags, true);
569 AddCXXSummary(cpp_category_sp,
570 lldb_private::formatters::LibcxxContainerSummaryProvider,
571 "libc++ std::multimap summary provider",
572 ConstString("^std::__(ndk)?1::multimap<.+>(( )?&)?$"),
573 stl_summary_flags, true);
575 cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider,
576 "libc++ std::unordered containers summary provider",
577 ConstString("^(std::__(ndk)?1::)unordered_(multi)?(map|set)<.+> >$"),
578 stl_summary_flags, true);
579 AddCXXSummary(cpp_category_sp, LibcxxContainerSummaryProvider,
580 "libc++ std::tuple summary provider",
581 ConstString("^std::__(ndk)?1::tuple<.*>(( )?&)?$"), stl_summary_flags,
584 cpp_category_sp, lldb_private::formatters::LibCxxAtomicSummaryProvider,
585 "libc++ std::atomic summary provider",
586 ConstString("^std::__(ndk)?1::atomic<.+>$"), stl_summary_flags, true);
588 stl_summary_flags.SetSkipPointers(true);
590 AddCXXSummary(cpp_category_sp,
591 lldb_private::formatters::LibcxxSmartPointerSummaryProvider,
592 "libc++ std::shared_ptr summary provider",
593 ConstString("^std::__(ndk)?1::shared_ptr<.+>(( )?&)?$"),
594 stl_summary_flags, true);
595 AddCXXSummary(cpp_category_sp,
596 lldb_private::formatters::LibcxxSmartPointerSummaryProvider,
597 "libc++ std::weak_ptr summary provider",
598 ConstString("^std::__(ndk)?1::weak_ptr<.+>(( )?&)?$"),
599 stl_summary_flags, true);
603 lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator,
604 "std::vector iterator synthetic children",
605 ConstString("^std::__(ndk)?1::__wrap_iter<.+>$"), stl_synth_flags, true);
609 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator,
610 "std::map iterator synthetic children",
611 ConstString("^std::__(ndk)?1::__map_iterator<.+>$"), stl_synth_flags,
615 cpp_category_sp, lldb_private::formatters::LibcxxFunctionFrontEndCreator,
616 "std::function synthetic value provider",
617 ConstString("^std::__(ndk)?1::function<.+>$"), stl_synth_flags, true);
621 static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
622 if (!cpp_category_sp)
625 TypeSummaryImpl::Flags stl_summary_flags;
626 stl_summary_flags.SetCascades(true)
627 .SetSkipPointers(false)
628 .SetSkipReferences(false)
629 .SetDontShowChildren(true)
630 .SetDontShowValue(true)
631 .SetShowMembersOneLiner(false)
632 .SetHideItemNames(false);
634 lldb::TypeSummaryImplSP std_string_summary_sp(
635 new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p}"));
637 lldb::TypeSummaryImplSP cxx11_string_summary_sp(new CXXFunctionSummaryFormat(
638 stl_summary_flags, LibStdcppStringSummaryProvider,
639 "libstdc++ c++11 std::string summary provider"));
640 lldb::TypeSummaryImplSP cxx11_wstring_summary_sp(new CXXFunctionSummaryFormat(
641 stl_summary_flags, LibStdcppWStringSummaryProvider,
642 "libstdc++ c++11 std::wstring summary provider"));
644 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::string"),
645 std_string_summary_sp);
646 cpp_category_sp->GetTypeSummariesContainer()->Add(
647 ConstString("std::basic_string<char>"), std_string_summary_sp);
648 cpp_category_sp->GetTypeSummariesContainer()->Add(
649 ConstString("std::basic_string<char,std::char_traits<char>,std::"
650 "allocator<char> >"),
651 std_string_summary_sp);
652 cpp_category_sp->GetTypeSummariesContainer()->Add(
653 ConstString("std::basic_string<char, std::char_traits<char>, "
654 "std::allocator<char> >"),
655 std_string_summary_sp);
657 cpp_category_sp->GetTypeSummariesContainer()->Add(
658 ConstString("std::__cxx11::string"), cxx11_string_summary_sp);
659 cpp_category_sp->GetTypeSummariesContainer()->Add(
660 ConstString("std::__cxx11::basic_string<char, std::char_traits<char>, "
661 "std::allocator<char> >"),
662 cxx11_string_summary_sp);
664 // making sure we force-pick the summary for printing wstring (_M_p is a
666 lldb::TypeSummaryImplSP std_wstring_summary_sp(
667 new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p%S}"));
669 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::wstring"),
670 std_wstring_summary_sp);
671 cpp_category_sp->GetTypeSummariesContainer()->Add(
672 ConstString("std::basic_string<wchar_t>"), std_wstring_summary_sp);
673 cpp_category_sp->GetTypeSummariesContainer()->Add(
674 ConstString("std::basic_string<wchar_t,std::char_traits<wchar_t>,std::"
675 "allocator<wchar_t> >"),
676 std_wstring_summary_sp);
677 cpp_category_sp->GetTypeSummariesContainer()->Add(
678 ConstString("std::basic_string<wchar_t, std::char_traits<wchar_t>, "
679 "std::allocator<wchar_t> >"),
680 std_wstring_summary_sp);
682 cpp_category_sp->GetTypeSummariesContainer()->Add(
683 ConstString("std::__cxx11::wstring"), cxx11_wstring_summary_sp);
684 cpp_category_sp->GetTypeSummariesContainer()->Add(
685 ConstString("std::__cxx11::basic_string<wchar_t, "
686 "std::char_traits<wchar_t>, std::allocator<wchar_t> >"),
687 cxx11_wstring_summary_sp);
689 #ifndef LLDB_DISABLE_PYTHON
691 SyntheticChildren::Flags stl_synth_flags;
692 stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
695 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
697 new RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$"))),
698 SyntheticChildrenSP(new ScriptedSyntheticChildren(
700 "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
701 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
703 new RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$"))),
704 SyntheticChildrenSP(new ScriptedSyntheticChildren(
706 "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider")));
707 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
708 RegularExpressionSP(new RegularExpression(
709 llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$"))),
710 SyntheticChildrenSP(new ScriptedSyntheticChildren(
712 "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
713 stl_summary_flags.SetDontShowChildren(false);
714 stl_summary_flags.SetSkipPointers(true);
715 cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
717 new RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$"))),
719 new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
720 cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
722 new RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$"))),
724 new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
725 cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
726 RegularExpressionSP(new RegularExpression(
727 llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$"))),
729 new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
733 lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator,
734 "std::vector iterator synthetic children",
735 ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
739 lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator,
740 "std::map iterator synthetic children",
741 ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
745 lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator,
746 "std::unique_ptr synthetic children",
747 ConstString("^std::unique_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
750 lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator,
751 "std::shared_ptr synthetic children",
752 ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
755 lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator,
756 "std::weak_ptr synthetic children",
757 ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
760 lldb_private::formatters::LibStdcppTupleSyntheticFrontEndCreator,
761 "std::tuple synthetic children", ConstString("^std::tuple<.+>(( )?&)?$"),
762 stl_synth_flags, true);
764 AddCXXSummary(cpp_category_sp,
765 lldb_private::formatters::LibStdcppUniquePointerSummaryProvider,
766 "libstdc++ std::unique_ptr summary provider",
767 ConstString("^std::unique_ptr<.+>(( )?&)?$"), stl_summary_flags,
769 AddCXXSummary(cpp_category_sp,
770 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider,
771 "libstdc++ std::shared_ptr summary provider",
772 ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_summary_flags,
774 AddCXXSummary(cpp_category_sp,
775 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider,
776 "libstdc++ std::weak_ptr summary provider",
777 ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_summary_flags,
782 static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
783 if (!cpp_category_sp)
786 TypeSummaryImpl::Flags string_flags;
787 string_flags.SetCascades(true)
788 .SetSkipPointers(true)
789 .SetSkipReferences(false)
790 .SetDontShowChildren(true)
791 .SetDontShowValue(false)
792 .SetShowMembersOneLiner(false)
793 .SetHideItemNames(false);
795 TypeSummaryImpl::Flags string_array_flags;
796 string_array_flags.SetCascades(true)
797 .SetSkipPointers(true)
798 .SetSkipReferences(false)
799 .SetDontShowChildren(true)
800 .SetDontShowValue(true)
801 .SetShowMembersOneLiner(false)
802 .SetHideItemNames(false);
804 #ifndef LLDB_DISABLE_PYTHON
805 // FIXME because of a bug in the FormattersContainer we need to add a summary
806 // for both X* and const X* (<rdar://problem/12717717>)
808 cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider,
809 "char16_t * summary provider", ConstString("char16_t *"), string_flags);
810 AddCXXSummary(cpp_category_sp,
811 lldb_private::formatters::Char16StringSummaryProvider,
812 "char16_t [] summary provider",
813 ConstString("char16_t \\[[0-9]+\\]"), string_array_flags, true);
816 cpp_category_sp, lldb_private::formatters::Char32StringSummaryProvider,
817 "char32_t * summary provider", ConstString("char32_t *"), string_flags);
818 AddCXXSummary(cpp_category_sp,
819 lldb_private::formatters::Char32StringSummaryProvider,
820 "char32_t [] summary provider",
821 ConstString("char32_t \\[[0-9]+\\]"), string_array_flags, true);
824 cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider,
825 "wchar_t * summary provider", ConstString("wchar_t *"), string_flags);
826 AddCXXSummary(cpp_category_sp,
827 lldb_private::formatters::WCharStringSummaryProvider,
828 "wchar_t * summary provider",
829 ConstString("wchar_t \\[[0-9]+\\]"), string_array_flags, true);
832 cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider,
833 "unichar * summary provider", ConstString("unichar *"), string_flags);
835 TypeSummaryImpl::Flags widechar_flags;
836 widechar_flags.SetDontShowValue(true)
837 .SetSkipPointers(true)
838 .SetSkipReferences(false)
840 .SetDontShowChildren(true)
841 .SetHideItemNames(true)
842 .SetShowMembersOneLiner(false);
845 cpp_category_sp, lldb_private::formatters::Char16SummaryProvider,
846 "char16_t summary provider", ConstString("char16_t"), widechar_flags);
848 cpp_category_sp, lldb_private::formatters::Char32SummaryProvider,
849 "char32_t summary provider", ConstString("char32_t"), widechar_flags);
850 AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharSummaryProvider,
851 "wchar_t summary provider", ConstString("wchar_t"),
855 cpp_category_sp, lldb_private::formatters::Char16SummaryProvider,
856 "unichar summary provider", ConstString("unichar"), widechar_flags);
860 std::unique_ptr<Language::TypeScavenger> CPlusPlusLanguage::GetTypeScavenger() {
861 class CPlusPlusTypeScavenger : public Language::ImageListTypeScavenger {
863 virtual CompilerType AdjustForInclusion(CompilerType &candidate) override {
864 LanguageType lang_type(candidate.GetMinimumLanguage());
865 if (!Language::LanguageIsC(lang_type) &&
866 !Language::LanguageIsCPlusPlus(lang_type))
867 return CompilerType();
868 if (candidate.IsTypedefType())
869 return candidate.GetTypedefedType();
874 return std::unique_ptr<TypeScavenger>(new CPlusPlusTypeScavenger());
877 lldb::TypeCategoryImplSP CPlusPlusLanguage::GetFormatters() {
878 static llvm::once_flag g_initialize;
879 static TypeCategoryImplSP g_category;
881 llvm::call_once(g_initialize, [this]() -> void {
882 DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
884 LoadLibCxxFormatters(g_category);
885 LoadLibStdcppFormatters(g_category);
886 LoadSystemFormatters(g_category);
892 HardcodedFormatters::HardcodedSummaryFinder
893 CPlusPlusLanguage::GetHardcodedSummaries() {
894 static llvm::once_flag g_initialize;
895 static ConstString g_vectortypes("VectorTypes");
896 static HardcodedFormatters::HardcodedSummaryFinder g_formatters;
898 llvm::call_once(g_initialize, []() -> void {
899 g_formatters.push_back(
900 [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
901 FormatManager &) -> TypeSummaryImpl::SharedPointer {
902 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
903 new CXXFunctionSummaryFormat(
904 TypeSummaryImpl::Flags(),
905 lldb_private::formatters::CXXFunctionPointerSummaryProvider,
906 "Function pointer summary provider"));
907 if (valobj.GetCompilerType().IsFunctionPointerType()) {
912 g_formatters.push_back(
913 [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
914 FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer {
915 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
916 new CXXFunctionSummaryFormat(
917 TypeSummaryImpl::Flags()
919 .SetDontShowChildren(true)
920 .SetHideItemNames(true)
921 .SetShowMembersOneLiner(true)
922 .SetSkipPointers(true)
923 .SetSkipReferences(false),
924 lldb_private::formatters::VectorTypeSummaryProvider,
925 "vector_type pointer summary provider"));
926 if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) {
927 if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
932 g_formatters.push_back(
933 [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
934 FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer {
935 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
936 new CXXFunctionSummaryFormat(
937 TypeSummaryImpl::Flags()
939 .SetDontShowChildren(true)
940 .SetHideItemNames(true)
941 .SetShowMembersOneLiner(true)
942 .SetSkipPointers(true)
943 .SetSkipReferences(false),
944 lldb_private::formatters::BlockPointerSummaryProvider,
945 "block pointer summary provider"));
946 if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) {
956 HardcodedFormatters::HardcodedSyntheticFinder
957 CPlusPlusLanguage::GetHardcodedSynthetics() {
958 static llvm::once_flag g_initialize;
959 static ConstString g_vectortypes("VectorTypes");
960 static HardcodedFormatters::HardcodedSyntheticFinder g_formatters;
962 llvm::call_once(g_initialize, []() -> void {
963 g_formatters.push_back([](lldb_private::ValueObject &valobj,
964 lldb::DynamicValueType,
966 fmt_mgr) -> SyntheticChildren::SharedPointer {
967 static CXXSyntheticChildren::SharedPointer formatter_sp(
968 new CXXSyntheticChildren(
969 SyntheticChildren::Flags()
971 .SetSkipPointers(true)
972 .SetSkipReferences(true)
973 .SetNonCacheable(true),
974 "vector_type synthetic children",
975 lldb_private::formatters::VectorTypeSyntheticFrontEndCreator));
976 if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) {
977 if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
982 g_formatters.push_back([](lldb_private::ValueObject &valobj,
983 lldb::DynamicValueType,
985 fmt_mgr) -> SyntheticChildren::SharedPointer {
986 static CXXSyntheticChildren::SharedPointer formatter_sp(
987 new CXXSyntheticChildren(
988 SyntheticChildren::Flags()
990 .SetSkipPointers(true)
991 .SetSkipReferences(true)
992 .SetNonCacheable(true),
993 "block pointer synthetic children",
994 lldb_private::formatters::BlockPointerSyntheticFrontEndCreator));
995 if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) {
1003 return g_formatters;