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]*)$"
124 // We are using a hand written implementation because it is significantly more
126 // using the general purpose regular expression library.
128 if (basename.size() > 0 && basename[0] == '~')
131 if (basename.size() <= idx)
132 return false; // Empty string or "~"
134 if (!std::isalpha(basename[idx]) && basename[idx] != '_')
135 return false; // First charater (after removing the possible '~'') isn't in
138 // Read all characters matching [A-Za-z_0-9]
140 while (idx < basename.size()) {
141 if (!std::isalnum(basename[idx]) && basename[idx] != '_')
146 // We processed all characters. It is a vaild basename.
147 if (idx == basename.size())
153 bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() {
154 // This method tries to parse simple method definitions
155 // which are presumably most comman in user programs.
156 // Definitions that can be parsed by this function don't have return types
157 // and templates in the name.
158 // A::B::C::fun(std::vector<T> &) const
159 size_t arg_start, arg_end;
160 llvm::StringRef full(m_full.GetCString());
161 llvm::StringRef parens("()", 2);
162 if (ReverseFindMatchingChars(full, parens, arg_start, arg_end)) {
163 m_arguments = full.substr(arg_start, arg_end - arg_start + 1);
164 if (arg_end + 1 < full.size())
165 m_qualifiers = full.substr(arg_end + 1).ltrim();
169 size_t basename_end = arg_start;
170 size_t context_start = 0;
171 size_t context_end = full.rfind(':', basename_end);
172 if (context_end == llvm::StringRef::npos)
173 m_basename = full.substr(0, basename_end);
175 if (context_start < context_end)
176 m_context = full.substr(context_start, context_end - 1 - context_start);
177 const size_t basename_begin = context_end + 1;
178 m_basename = full.substr(basename_begin, basename_end - basename_begin);
181 if (IsTrivialBasename(m_basename)) {
184 // The C++ basename doesn't match our regular expressions so this can't
185 // be a valid C++ method, clear everything out and indicate an error
186 m_context = llvm::StringRef();
187 m_basename = llvm::StringRef();
188 m_arguments = llvm::StringRef();
189 m_qualifiers = llvm::StringRef();
196 void CPlusPlusLanguage::MethodName::Parse() {
197 if (!m_parsed && m_full) {
198 if (TrySimplifiedParse()) {
199 m_parse_error = false;
201 CPlusPlusNameParser parser(m_full.GetStringRef());
202 if (auto function = parser.ParseAsFunctionDefinition()) {
203 m_basename = function.getValue().name.basename;
204 m_context = function.getValue().name.context;
205 m_arguments = function.getValue().arguments;
206 m_qualifiers = function.getValue().qualifiers;
207 m_parse_error = false;
209 m_parse_error = true;
216 llvm::StringRef CPlusPlusLanguage::MethodName::GetBasename() {
222 llvm::StringRef CPlusPlusLanguage::MethodName::GetContext() {
228 llvm::StringRef CPlusPlusLanguage::MethodName::GetArguments() {
234 llvm::StringRef CPlusPlusLanguage::MethodName::GetQualifiers() {
240 std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() {
243 if (m_context.empty())
253 bool CPlusPlusLanguage::IsCPPMangledName(const char *name) {
254 // FIXME, we should really run through all the known C++ Language plugins and
256 // this is a C++ mangled name, but we can put that off till there is actually
260 return (name != nullptr && name[0] == '_' && name[1] == 'Z');
263 bool CPlusPlusLanguage::ExtractContextAndIdentifier(
264 const char *name, llvm::StringRef &context, llvm::StringRef &identifier) {
265 CPlusPlusNameParser parser(name);
266 if (auto full_name = parser.ParseAsFullName()) {
267 identifier = full_name.getValue().basename;
268 context = full_name.getValue().context;
274 class CPPRuntimeEquivalents {
276 CPPRuntimeEquivalents() {
277 m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, "
278 "std::allocator<char> >")
280 ConstString("basic_string<char>"));
282 // these two (with a prefixed std::) occur when c++stdlib string class
283 // occurs as a template argument in some STL container
284 m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, "
285 "std::allocator<char> >")
287 ConstString("std::basic_string<char>"));
292 void Add(ConstString &type_name, ConstString &type_equivalent) {
293 m_impl.Insert(type_name.GetStringRef(), type_equivalent);
296 uint32_t FindExactMatches(ConstString &type_name,
297 std::vector<ConstString> &equivalents) {
300 for (ImplData match =
301 m_impl.FindFirstValueForName(type_name.GetStringRef());
302 match != nullptr; match = m_impl.FindNextValueForName(match)) {
303 equivalents.push_back(match->value);
310 // partial matches can occur when a name with equivalents is a template
312 // e.g. we may have "class Foo" be a match for "struct Bar". if we have a
314 // such as "class Templatized<class Foo, Anything>" we want this to be
316 // "class Templatized<struct Bar, Anything>". Since partial matching is time
318 // once we get a partial match, we add it to the exact matches list for faster
320 uint32_t FindPartialMatches(ConstString &type_name,
321 std::vector<ConstString> &equivalents) {
324 llvm::StringRef type_name_cstr = type_name.GetStringRef();
326 size_t items_count = m_impl.GetSize();
328 for (size_t item = 0; item < items_count; item++) {
329 llvm::StringRef key_cstr = m_impl.GetCStringAtIndex(item);
330 if (type_name_cstr.contains(key_cstr)) {
331 count += AppendReplacements(type_name_cstr, key_cstr, equivalents);
339 std::string &replace(std::string &target, std::string &pattern,
342 size_t pattern_len = pattern.size();
344 while ((pos = target.find(pattern)) != std::string::npos)
345 target.replace(pos, pattern_len, with);
350 uint32_t AppendReplacements(llvm::StringRef original,
351 llvm::StringRef matching_key,
352 std::vector<ConstString> &equivalents) {
353 std::string matching_key_str(matching_key);
354 ConstString original_const(original);
358 for (ImplData match = m_impl.FindFirstValueForName(matching_key);
359 match != nullptr; match = m_impl.FindNextValueForName(match)) {
360 std::string target(original);
361 std::string equiv_class(match->value.AsCString());
363 replace(target, matching_key_str, equiv_class);
365 ConstString target_const(target.c_str());
367 // you will most probably want to leave this off since it might make this map
369 #ifdef ENABLE_CPP_EQUIVALENTS_MAP_TO_GROW
370 Add(original_const, target_const);
372 equivalents.push_back(target_const);
380 typedef UniqueCStringMap<ConstString> Impl;
381 typedef const Impl::Entry *ImplData;
385 static CPPRuntimeEquivalents &GetEquivalentsMap() {
386 static CPPRuntimeEquivalents g_equivalents_map;
387 return g_equivalents_map;
391 CPlusPlusLanguage::FindEquivalentNames(ConstString type_name,
392 std::vector<ConstString> &equivalents) {
393 uint32_t count = GetEquivalentsMap().FindExactMatches(type_name, equivalents);
395 bool might_have_partials =
396 (count == 0) // if we have a full name match just use it
397 && (strchr(type_name.AsCString(), '<') !=
398 nullptr // we should only have partial matches when templates are
399 // involved, check that we have
400 && strchr(type_name.AsCString(), '>') != nullptr); // angle brackets
406 if (might_have_partials)
407 count = GetEquivalentsMap().FindPartialMatches(type_name, equivalents);
412 /// Given a mangled function `mangled`, replace all the primitive function type
413 /// arguments of `search` with type `replace`.
414 static ConstString SubsPrimitiveParmItanium(llvm::StringRef mangled,
415 llvm::StringRef search,
416 llvm::StringRef replace) {
417 Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
419 const size_t max_len =
420 mangled.size() + mangled.count(search) * replace.size() + 1;
422 // Make a temporary buffer to fix up the mangled parameter types and copy the
424 std::string output_buf;
425 output_buf.reserve(max_len);
426 output_buf.insert(0, mangled.str());
427 ptrdiff_t replaced_offset = 0;
429 auto swap_parms_hook = [&](const char *parsee) {
430 if (!parsee || !*parsee)
433 // Check whether we've found a substitutee
434 llvm::StringRef s(parsee);
435 if (s.startswith(search)) {
436 // account for the case where a replacement is of a different length to
438 replaced_offset += replace.size() - search.size();
440 ptrdiff_t replace_idx = (mangled.size() - s.size()) + replaced_offset;
441 output_buf.erase(replace_idx, search.size());
442 output_buf.insert(replace_idx, replace.str());
446 // FastDemangle will call our hook for each instance of a primitive type,
447 // allowing us to perform substitution
448 const char *const demangled =
449 FastDemangle(mangled.str().c_str(), mangled.size(), swap_parms_hook);
452 log->Printf("substituted mangling for %s:{%s} %s:{%s}\n",
453 mangled.str().c_str(), demangled, output_buf.c_str(),
454 FastDemangle(output_buf.c_str()));
456 return output_buf == mangled ? ConstString() : ConstString(output_buf);
459 uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
460 const ConstString mangled_name, std::set<ConstString> &alternates) {
461 const auto start_size = alternates.size();
462 /// Get a basic set of alternative manglings for the given symbol `name`, by
463 /// making a few basic possible substitutions on basic types, storage duration
464 /// and `const`ness for the given symbol. The output parameter `alternates`
465 /// is filled with a best-guess, non-exhaustive set of different manglings
466 /// for the given name.
468 // Maybe we're looking for a const symbol but the debug info told us it was
470 if (!strncmp(mangled_name.GetCString(), "_ZN", 3) &&
471 strncmp(mangled_name.GetCString(), "_ZNK", 4)) {
472 std::string fixed_scratch("_ZNK");
473 fixed_scratch.append(mangled_name.GetCString() + 3);
474 alternates.insert(ConstString(fixed_scratch));
477 // Maybe we're looking for a static symbol but we thought it was global...
478 if (!strncmp(mangled_name.GetCString(), "_Z", 2) &&
479 strncmp(mangled_name.GetCString(), "_ZL", 3)) {
480 std::string fixed_scratch("_ZL");
481 fixed_scratch.append(mangled_name.GetCString() + 2);
482 alternates.insert(ConstString(fixed_scratch));
485 // `char` is implementation defined as either `signed` or `unsigned`. As a
486 // result a char parameter has 3 possible manglings: 'c'-char, 'a'-signed
487 // char, 'h'-unsigned char. If we're looking for symbols with a signed char
488 // parameter, try finding matches which have the general case 'c'.
489 if (ConstString char_fixup =
490 SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "a", "c"))
491 alternates.insert(char_fixup);
493 // long long parameter mangling 'x', may actually just be a long 'l' argument
494 if (ConstString long_fixup =
495 SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "x", "l"))
496 alternates.insert(long_fixup);
498 // unsigned long long parameter mangling 'y', may actually just be unsigned
500 if (ConstString ulong_fixup =
501 SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "y", "m"))
502 alternates.insert(ulong_fixup);
504 return alternates.size() - start_size;
507 static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
508 if (!cpp_category_sp)
511 TypeSummaryImpl::Flags stl_summary_flags;
512 stl_summary_flags.SetCascades(true)
513 .SetSkipPointers(false)
514 .SetSkipReferences(false)
515 .SetDontShowChildren(true)
516 .SetDontShowValue(true)
517 .SetShowMembersOneLiner(false)
518 .SetHideItemNames(false);
520 #ifndef LLDB_DISABLE_PYTHON
521 lldb::TypeSummaryImplSP std_string_summary_sp(new CXXFunctionSummaryFormat(
522 stl_summary_flags, lldb_private::formatters::LibcxxStringSummaryProvider,
523 "std::string summary provider"));
524 lldb::TypeSummaryImplSP std_wstring_summary_sp(new CXXFunctionSummaryFormat(
525 stl_summary_flags, lldb_private::formatters::LibcxxWStringSummaryProvider,
526 "std::wstring summary provider"));
528 cpp_category_sp->GetTypeSummariesContainer()->Add(
529 ConstString("std::__1::string"), std_string_summary_sp);
530 cpp_category_sp->GetTypeSummariesContainer()->Add(
531 ConstString("std::__ndk1::string"), std_string_summary_sp);
532 cpp_category_sp->GetTypeSummariesContainer()->Add(
533 ConstString("std::__1::basic_string<char, std::__1::char_traits<char>, "
534 "std::__1::allocator<char> >"),
535 std_string_summary_sp);
536 cpp_category_sp->GetTypeSummariesContainer()->Add(
537 ConstString("std::__ndk1::basic_string<char, "
538 "std::__ndk1::char_traits<char>, "
539 "std::__ndk1::allocator<char> >"),
540 std_string_summary_sp);
542 cpp_category_sp->GetTypeSummariesContainer()->Add(
543 ConstString("std::__1::wstring"), std_wstring_summary_sp);
544 cpp_category_sp->GetTypeSummariesContainer()->Add(
545 ConstString("std::__ndk1::wstring"), std_wstring_summary_sp);
546 cpp_category_sp->GetTypeSummariesContainer()->Add(
547 ConstString("std::__1::basic_string<wchar_t, "
548 "std::__1::char_traits<wchar_t>, "
549 "std::__1::allocator<wchar_t> >"),
550 std_wstring_summary_sp);
551 cpp_category_sp->GetTypeSummariesContainer()->Add(
552 ConstString("std::__ndk1::basic_string<wchar_t, "
553 "std::__ndk1::char_traits<wchar_t>, "
554 "std::__ndk1::allocator<wchar_t> >"),
555 std_wstring_summary_sp);
557 SyntheticChildren::Flags stl_synth_flags;
558 stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
563 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator,
564 "libc++ std::vector synthetic children",
565 ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_synth_flags,
569 lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator,
570 "libc++ std::list synthetic children",
571 ConstString("^std::__(ndk)?1::list<.+>(( )?&)?$"), stl_synth_flags, true);
574 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
575 "libc++ std::map synthetic children",
576 ConstString("^std::__(ndk)?1::map<.+> >(( )?&)?$"), stl_synth_flags,
580 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
581 "libc++ std::set synthetic children",
582 ConstString("^std::__(ndk)?1::set<.+> >(( )?&)?$"), stl_synth_flags,
586 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
587 "libc++ std::multiset synthetic children",
588 ConstString("^std::__(ndk)?1::multiset<.+> >(( )?&)?$"), stl_synth_flags,
592 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
593 "libc++ std::multimap synthetic children",
594 ConstString("^std::__(ndk)?1::multimap<.+> >(( )?&)?$"), stl_synth_flags,
598 lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator,
599 "libc++ std::unordered containers synthetic children",
600 ConstString("^(std::__(ndk)?1::)unordered_(multi)?(map|set)<.+> >$"),
601 stl_synth_flags, true);
604 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator,
605 "libc++ std::initializer_list synthetic children",
606 ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags,
610 lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator,
611 "libc++ std::atomic synthetic children",
612 ConstString("^std::__(ndk)?1::atomic<.+>$"), stl_synth_flags, true);
614 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
615 RegularExpressionSP(new RegularExpression(
616 llvm::StringRef("^(std::__(ndk)?1::)deque<.+>(( )?&)?$"))),
617 SyntheticChildrenSP(new ScriptedSyntheticChildren(
619 "lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));
623 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,
624 "shared_ptr synthetic children",
625 ConstString("^(std::__(ndk)?1::)shared_ptr<.+>(( )?&)?$"),
626 stl_synth_flags, true);
629 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,
630 "weak_ptr synthetic children",
631 ConstString("^(std::__(ndk)?1::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags,
634 stl_summary_flags.SetDontShowChildren(false);
635 stl_summary_flags.SetSkipPointers(false);
636 AddCXXSummary(cpp_category_sp,
637 lldb_private::formatters::LibcxxContainerSummaryProvider,
638 "libc++ std::vector summary provider",
639 ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"),
640 stl_summary_flags, true);
641 AddCXXSummary(cpp_category_sp,
642 lldb_private::formatters::LibcxxContainerSummaryProvider,
643 "libc++ std::list summary provider",
644 ConstString("^std::__(ndk)?1::list<.+>(( )?&)?$"),
645 stl_summary_flags, true);
646 AddCXXSummary(cpp_category_sp,
647 lldb_private::formatters::LibcxxContainerSummaryProvider,
648 "libc++ std::map summary provider",
649 ConstString("^std::__(ndk)?1::map<.+>(( )?&)?$"),
650 stl_summary_flags, true);
651 AddCXXSummary(cpp_category_sp,
652 lldb_private::formatters::LibcxxContainerSummaryProvider,
653 "libc++ std::deque summary provider",
654 ConstString("^std::__(ndk)?1::deque<.+>(( )?&)?$"),
655 stl_summary_flags, true);
656 AddCXXSummary(cpp_category_sp,
657 lldb_private::formatters::LibcxxContainerSummaryProvider,
658 "libc++ std::set summary provider",
659 ConstString("^std::__(ndk)?1::set<.+>(( )?&)?$"),
660 stl_summary_flags, true);
661 AddCXXSummary(cpp_category_sp,
662 lldb_private::formatters::LibcxxContainerSummaryProvider,
663 "libc++ std::multiset summary provider",
664 ConstString("^std::__(ndk)?1::multiset<.+>(( )?&)?$"),
665 stl_summary_flags, true);
666 AddCXXSummary(cpp_category_sp,
667 lldb_private::formatters::LibcxxContainerSummaryProvider,
668 "libc++ std::multimap summary provider",
669 ConstString("^std::__(ndk)?1::multimap<.+>(( )?&)?$"),
670 stl_summary_flags, true);
672 cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider,
673 "libc++ std::unordered containers summary provider",
674 ConstString("^(std::__(ndk)?1::)unordered_(multi)?(map|set)<.+> >$"),
675 stl_summary_flags, true);
677 cpp_category_sp, lldb_private::formatters::LibCxxAtomicSummaryProvider,
678 "libc++ std::atomic summary provider",
679 ConstString("^std::__(ndk)?1::atomic<.+>$"), stl_summary_flags, true);
681 stl_summary_flags.SetSkipPointers(true);
683 AddCXXSummary(cpp_category_sp,
684 lldb_private::formatters::LibcxxSmartPointerSummaryProvider,
685 "libc++ std::shared_ptr summary provider",
686 ConstString("^std::__(ndk)?1::shared_ptr<.+>(( )?&)?$"),
687 stl_summary_flags, true);
688 AddCXXSummary(cpp_category_sp,
689 lldb_private::formatters::LibcxxSmartPointerSummaryProvider,
690 "libc++ std::weak_ptr summary provider",
691 ConstString("^std::__(ndk)?1::weak_ptr<.+>(( )?&)?$"),
692 stl_summary_flags, true);
696 lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator,
697 "std::vector iterator synthetic children",
698 ConstString("^std::__(ndk)?1::__wrap_iter<.+>$"), stl_synth_flags, true);
702 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator,
703 "std::map iterator synthetic children",
704 ConstString("^std::__(ndk)?1::__map_iterator<.+>$"), stl_synth_flags,
708 cpp_category_sp, lldb_private::formatters::LibcxxFunctionFrontEndCreator,
709 "std::function synthetic value provider",
710 ConstString("^std::__(ndk)?1::function<.+>$"), stl_synth_flags, true);
714 static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
715 if (!cpp_category_sp)
718 TypeSummaryImpl::Flags stl_summary_flags;
719 stl_summary_flags.SetCascades(true)
720 .SetSkipPointers(false)
721 .SetSkipReferences(false)
722 .SetDontShowChildren(true)
723 .SetDontShowValue(true)
724 .SetShowMembersOneLiner(false)
725 .SetHideItemNames(false);
727 lldb::TypeSummaryImplSP std_string_summary_sp(
728 new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p}"));
730 lldb::TypeSummaryImplSP cxx11_string_summary_sp(new CXXFunctionSummaryFormat(
731 stl_summary_flags, LibStdcppStringSummaryProvider,
732 "libstdc++ c++11 std::string summary provider"));
733 lldb::TypeSummaryImplSP cxx11_wstring_summary_sp(new CXXFunctionSummaryFormat(
734 stl_summary_flags, LibStdcppWStringSummaryProvider,
735 "libstdc++ c++11 std::wstring summary provider"));
737 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::string"),
738 std_string_summary_sp);
739 cpp_category_sp->GetTypeSummariesContainer()->Add(
740 ConstString("std::basic_string<char>"), std_string_summary_sp);
741 cpp_category_sp->GetTypeSummariesContainer()->Add(
742 ConstString("std::basic_string<char,std::char_traits<char>,std::"
743 "allocator<char> >"),
744 std_string_summary_sp);
745 cpp_category_sp->GetTypeSummariesContainer()->Add(
746 ConstString("std::basic_string<char, std::char_traits<char>, "
747 "std::allocator<char> >"),
748 std_string_summary_sp);
750 cpp_category_sp->GetTypeSummariesContainer()->Add(
751 ConstString("std::__cxx11::string"), cxx11_string_summary_sp);
752 cpp_category_sp->GetTypeSummariesContainer()->Add(
753 ConstString("std::__cxx11::basic_string<char, std::char_traits<char>, "
754 "std::allocator<char> >"),
755 cxx11_string_summary_sp);
757 // making sure we force-pick the summary for printing wstring (_M_p is a
759 lldb::TypeSummaryImplSP std_wstring_summary_sp(
760 new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p%S}"));
762 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::wstring"),
763 std_wstring_summary_sp);
764 cpp_category_sp->GetTypeSummariesContainer()->Add(
765 ConstString("std::basic_string<wchar_t>"), std_wstring_summary_sp);
766 cpp_category_sp->GetTypeSummariesContainer()->Add(
767 ConstString("std::basic_string<wchar_t,std::char_traits<wchar_t>,std::"
768 "allocator<wchar_t> >"),
769 std_wstring_summary_sp);
770 cpp_category_sp->GetTypeSummariesContainer()->Add(
771 ConstString("std::basic_string<wchar_t, std::char_traits<wchar_t>, "
772 "std::allocator<wchar_t> >"),
773 std_wstring_summary_sp);
775 cpp_category_sp->GetTypeSummariesContainer()->Add(
776 ConstString("std::__cxx11::wstring"), cxx11_wstring_summary_sp);
777 cpp_category_sp->GetTypeSummariesContainer()->Add(
778 ConstString("std::__cxx11::basic_string<wchar_t, "
779 "std::char_traits<wchar_t>, std::allocator<wchar_t> >"),
780 cxx11_wstring_summary_sp);
782 #ifndef LLDB_DISABLE_PYTHON
784 SyntheticChildren::Flags stl_synth_flags;
785 stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
788 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
790 new RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$"))),
791 SyntheticChildrenSP(new ScriptedSyntheticChildren(
793 "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
794 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
796 new RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$"))),
797 SyntheticChildrenSP(new ScriptedSyntheticChildren(
799 "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider")));
800 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
801 RegularExpressionSP(new RegularExpression(
802 llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$"))),
803 SyntheticChildrenSP(new ScriptedSyntheticChildren(
805 "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
806 stl_summary_flags.SetDontShowChildren(false);
807 stl_summary_flags.SetSkipPointers(true);
808 cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
810 new RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$"))),
812 new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
813 cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
815 new RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$"))),
817 new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
818 cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
819 RegularExpressionSP(new RegularExpression(
820 llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$"))),
822 new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
826 lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator,
827 "std::vector iterator synthetic children",
828 ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
832 lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator,
833 "std::map iterator synthetic children",
834 ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
838 lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator,
839 "std::unique_ptr synthetic children",
840 ConstString("^std::unique_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
843 lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator,
844 "std::shared_ptr synthetic children",
845 ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
848 lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator,
849 "std::weak_ptr synthetic children",
850 ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
853 lldb_private::formatters::LibStdcppTupleSyntheticFrontEndCreator,
854 "std::tuple synthetic children", ConstString("^std::tuple<.+>(( )?&)?$"),
855 stl_synth_flags, true);
857 AddCXXSummary(cpp_category_sp,
858 lldb_private::formatters::LibStdcppUniquePointerSummaryProvider,
859 "libstdc++ std::unique_ptr summary provider",
860 ConstString("^std::unique_ptr<.+>(( )?&)?$"), stl_summary_flags,
862 AddCXXSummary(cpp_category_sp,
863 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider,
864 "libstdc++ std::shared_ptr summary provider",
865 ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_summary_flags,
867 AddCXXSummary(cpp_category_sp,
868 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider,
869 "libstdc++ std::weak_ptr summary provider",
870 ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_summary_flags,
875 static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
876 if (!cpp_category_sp)
879 TypeSummaryImpl::Flags string_flags;
880 string_flags.SetCascades(true)
881 .SetSkipPointers(true)
882 .SetSkipReferences(false)
883 .SetDontShowChildren(true)
884 .SetDontShowValue(false)
885 .SetShowMembersOneLiner(false)
886 .SetHideItemNames(false);
888 TypeSummaryImpl::Flags string_array_flags;
889 string_array_flags.SetCascades(true)
890 .SetSkipPointers(true)
891 .SetSkipReferences(false)
892 .SetDontShowChildren(true)
893 .SetDontShowValue(true)
894 .SetShowMembersOneLiner(false)
895 .SetHideItemNames(false);
897 #ifndef LLDB_DISABLE_PYTHON
898 // FIXME because of a bug in the FormattersContainer we need to add a summary
899 // for both X* and const X* (<rdar://problem/12717717>)
901 cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider,
902 "char16_t * summary provider", ConstString("char16_t *"), string_flags);
903 AddCXXSummary(cpp_category_sp,
904 lldb_private::formatters::Char16StringSummaryProvider,
905 "char16_t [] summary provider",
906 ConstString("char16_t \\[[0-9]+\\]"), string_array_flags, true);
909 cpp_category_sp, lldb_private::formatters::Char32StringSummaryProvider,
910 "char32_t * summary provider", ConstString("char32_t *"), string_flags);
911 AddCXXSummary(cpp_category_sp,
912 lldb_private::formatters::Char32StringSummaryProvider,
913 "char32_t [] summary provider",
914 ConstString("char32_t \\[[0-9]+\\]"), string_array_flags, true);
917 cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider,
918 "wchar_t * summary provider", ConstString("wchar_t *"), string_flags);
919 AddCXXSummary(cpp_category_sp,
920 lldb_private::formatters::WCharStringSummaryProvider,
921 "wchar_t * summary provider",
922 ConstString("wchar_t \\[[0-9]+\\]"), string_array_flags, true);
925 cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider,
926 "unichar * summary provider", ConstString("unichar *"), string_flags);
928 TypeSummaryImpl::Flags widechar_flags;
929 widechar_flags.SetDontShowValue(true)
930 .SetSkipPointers(true)
931 .SetSkipReferences(false)
933 .SetDontShowChildren(true)
934 .SetHideItemNames(true)
935 .SetShowMembersOneLiner(false);
938 cpp_category_sp, lldb_private::formatters::Char16SummaryProvider,
939 "char16_t summary provider", ConstString("char16_t"), widechar_flags);
941 cpp_category_sp, lldb_private::formatters::Char32SummaryProvider,
942 "char32_t summary provider", ConstString("char32_t"), widechar_flags);
943 AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharSummaryProvider,
944 "wchar_t summary provider", ConstString("wchar_t"),
948 cpp_category_sp, lldb_private::formatters::Char16SummaryProvider,
949 "unichar summary provider", ConstString("unichar"), widechar_flags);
953 std::unique_ptr<Language::TypeScavenger> CPlusPlusLanguage::GetTypeScavenger() {
954 class CPlusPlusTypeScavenger : public Language::ImageListTypeScavenger {
956 virtual CompilerType AdjustForInclusion(CompilerType &candidate) override {
957 LanguageType lang_type(candidate.GetMinimumLanguage());
958 if (!Language::LanguageIsC(lang_type) &&
959 !Language::LanguageIsCPlusPlus(lang_type))
960 return CompilerType();
961 if (candidate.IsTypedefType())
962 return candidate.GetTypedefedType();
967 return std::unique_ptr<TypeScavenger>(new CPlusPlusTypeScavenger());
970 lldb::TypeCategoryImplSP CPlusPlusLanguage::GetFormatters() {
971 static llvm::once_flag g_initialize;
972 static TypeCategoryImplSP g_category;
974 llvm::call_once(g_initialize, [this]() -> void {
975 DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
977 LoadLibCxxFormatters(g_category);
978 LoadLibStdcppFormatters(g_category);
979 LoadSystemFormatters(g_category);
985 HardcodedFormatters::HardcodedSummaryFinder
986 CPlusPlusLanguage::GetHardcodedSummaries() {
987 static llvm::once_flag g_initialize;
988 static ConstString g_vectortypes("VectorTypes");
989 static HardcodedFormatters::HardcodedSummaryFinder g_formatters;
991 llvm::call_once(g_initialize, []() -> void {
992 g_formatters.push_back(
993 [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
994 FormatManager &) -> TypeSummaryImpl::SharedPointer {
995 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
996 new CXXFunctionSummaryFormat(
997 TypeSummaryImpl::Flags(),
998 lldb_private::formatters::CXXFunctionPointerSummaryProvider,
999 "Function pointer summary provider"));
1000 if (valobj.GetCompilerType().IsFunctionPointerType()) {
1001 return formatter_sp;
1005 g_formatters.push_back(
1006 [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
1007 FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer {
1008 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
1009 new CXXFunctionSummaryFormat(
1010 TypeSummaryImpl::Flags()
1012 .SetDontShowChildren(true)
1013 .SetHideItemNames(true)
1014 .SetShowMembersOneLiner(true)
1015 .SetSkipPointers(true)
1016 .SetSkipReferences(false),
1017 lldb_private::formatters::VectorTypeSummaryProvider,
1018 "vector_type pointer summary provider"));
1019 if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) {
1020 if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
1021 return formatter_sp;
1025 g_formatters.push_back(
1026 [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
1027 FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer {
1028 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
1029 new CXXFunctionSummaryFormat(
1030 TypeSummaryImpl::Flags()
1032 .SetDontShowChildren(true)
1033 .SetHideItemNames(true)
1034 .SetShowMembersOneLiner(true)
1035 .SetSkipPointers(true)
1036 .SetSkipReferences(false),
1037 lldb_private::formatters::BlockPointerSummaryProvider,
1038 "block pointer summary provider"));
1039 if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) {
1040 return formatter_sp;
1046 return g_formatters;
1049 HardcodedFormatters::HardcodedSyntheticFinder
1050 CPlusPlusLanguage::GetHardcodedSynthetics() {
1051 static llvm::once_flag g_initialize;
1052 static ConstString g_vectortypes("VectorTypes");
1053 static HardcodedFormatters::HardcodedSyntheticFinder g_formatters;
1055 llvm::call_once(g_initialize, []() -> void {
1056 g_formatters.push_back([](lldb_private::ValueObject &valobj,
1057 lldb::DynamicValueType,
1059 fmt_mgr) -> SyntheticChildren::SharedPointer {
1060 static CXXSyntheticChildren::SharedPointer formatter_sp(
1061 new CXXSyntheticChildren(
1062 SyntheticChildren::Flags()
1064 .SetSkipPointers(true)
1065 .SetSkipReferences(true)
1066 .SetNonCacheable(true),
1067 "vector_type synthetic children",
1068 lldb_private::formatters::VectorTypeSyntheticFrontEndCreator));
1069 if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) {
1070 if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
1071 return formatter_sp;
1075 g_formatters.push_back([](lldb_private::ValueObject &valobj,
1076 lldb::DynamicValueType,
1078 fmt_mgr) -> SyntheticChildren::SharedPointer {
1079 static CXXSyntheticChildren::SharedPointer formatter_sp(
1080 new CXXSyntheticChildren(
1081 SyntheticChildren::Flags()
1083 .SetSkipPointers(true)
1084 .SetSkipReferences(true)
1085 .SetNonCacheable(true),
1086 "block pointer synthetic children",
1087 lldb_private::formatters::BlockPointerSyntheticFrontEndCreator));
1088 if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) {
1089 return formatter_sp;
1096 return g_formatters;