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"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/Demangle/ItaniumDemangle.h"
23 #include "lldb/Core/PluginManager.h"
24 #include "lldb/Core/UniqueCStringMap.h"
25 #include "lldb/DataFormatters/CXXFunctionPointer.h"
26 #include "lldb/DataFormatters/DataVisualization.h"
27 #include "lldb/DataFormatters/FormattersHelpers.h"
28 #include "lldb/DataFormatters/VectorType.h"
29 #include "lldb/Utility/ConstString.h"
30 #include "lldb/Utility/Log.h"
31 #include "lldb/Utility/RegularExpression.h"
33 #include "BlockPointer.h"
34 #include "CPlusPlusNameParser.h"
35 #include "CxxStringTypes.h"
37 #include "LibCxxAtomic.h"
38 #include "LibCxxVariant.h"
39 #include "LibStdcpp.h"
40 #include "MSVCUndecoratedNameParser.h"
43 using namespace lldb_private;
44 using namespace lldb_private::formatters;
46 void CPlusPlusLanguage::Initialize() {
47 PluginManager::RegisterPlugin(GetPluginNameStatic(), "C++ Language",
51 void CPlusPlusLanguage::Terminate() {
52 PluginManager::UnregisterPlugin(CreateInstance);
55 lldb_private::ConstString CPlusPlusLanguage::GetPluginNameStatic() {
56 static ConstString g_name("cplusplus");
60 //------------------------------------------------------------------
61 // PluginInterface protocol
62 //------------------------------------------------------------------
64 lldb_private::ConstString CPlusPlusLanguage::GetPluginName() {
65 return GetPluginNameStatic();
68 uint32_t CPlusPlusLanguage::GetPluginVersion() { return 1; }
70 //------------------------------------------------------------------
72 //------------------------------------------------------------------
74 Language *CPlusPlusLanguage::CreateInstance(lldb::LanguageType language) {
75 if (Language::LanguageIsCPlusPlus(language))
76 return new CPlusPlusLanguage();
80 void CPlusPlusLanguage::MethodName::Clear() {
82 m_basename = llvm::StringRef();
83 m_context = llvm::StringRef();
84 m_arguments = llvm::StringRef();
85 m_qualifiers = llvm::StringRef();
87 m_parse_error = false;
90 static bool ReverseFindMatchingChars(const llvm::StringRef &s,
91 const llvm::StringRef &left_right_chars,
92 size_t &left_pos, size_t &right_pos,
93 size_t pos = llvm::StringRef::npos) {
94 assert(left_right_chars.size() == 2);
95 left_pos = llvm::StringRef::npos;
96 const char left_char = left_right_chars[0];
97 const char right_char = left_right_chars[1];
98 pos = s.find_last_of(left_right_chars, pos);
99 if (pos == llvm::StringRef::npos || s[pos] == left_char)
103 while (pos > 0 && depth > 0) {
104 pos = s.find_last_of(left_right_chars, pos);
105 if (pos == llvm::StringRef::npos)
107 if (s[pos] == left_char) {
110 return left_pos < right_pos;
112 } else if (s[pos] == right_char) {
119 static bool IsTrivialBasename(const llvm::StringRef &basename) {
120 // Check that the basename matches with the following regular expression
121 // "^~?([A-Za-z_][A-Za-z_0-9]*)$" We are using a hand written implementation
122 // because it is significantly more efficient then using the general purpose
123 // regular expression library.
125 if (basename.size() > 0 && basename[0] == '~')
128 if (basename.size() <= idx)
129 return false; // Empty string or "~"
131 if (!std::isalpha(basename[idx]) && basename[idx] != '_')
132 return false; // First charater (after removing the possible '~'') isn't in
135 // Read all characters matching [A-Za-z_0-9]
137 while (idx < basename.size()) {
138 if (!std::isalnum(basename[idx]) && basename[idx] != '_')
143 // We processed all characters. It is a vaild basename.
144 return idx == basename.size();
147 bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() {
148 // This method tries to parse simple method definitions which are presumably
149 // most comman in user programs. Definitions that can be parsed by this
150 // function don't have return types and templates in the name.
151 // A::B::C::fun(std::vector<T> &) const
152 size_t arg_start, arg_end;
153 llvm::StringRef full(m_full.GetCString());
154 llvm::StringRef parens("()", 2);
155 if (ReverseFindMatchingChars(full, parens, arg_start, arg_end)) {
156 m_arguments = full.substr(arg_start, arg_end - arg_start + 1);
157 if (arg_end + 1 < full.size())
158 m_qualifiers = full.substr(arg_end + 1).ltrim();
162 size_t basename_end = arg_start;
163 size_t context_start = 0;
164 size_t context_end = full.rfind(':', basename_end);
165 if (context_end == llvm::StringRef::npos)
166 m_basename = full.substr(0, basename_end);
168 if (context_start < context_end)
169 m_context = full.substr(context_start, context_end - 1 - context_start);
170 const size_t basename_begin = context_end + 1;
171 m_basename = full.substr(basename_begin, basename_end - basename_begin);
174 if (IsTrivialBasename(m_basename)) {
177 // The C++ basename doesn't match our regular expressions so this can't
178 // be a valid C++ method, clear everything out and indicate an error
179 m_context = llvm::StringRef();
180 m_basename = llvm::StringRef();
181 m_arguments = llvm::StringRef();
182 m_qualifiers = llvm::StringRef();
189 void CPlusPlusLanguage::MethodName::Parse() {
190 if (!m_parsed && m_full) {
191 if (TrySimplifiedParse()) {
192 m_parse_error = false;
194 CPlusPlusNameParser parser(m_full.GetStringRef());
195 if (auto function = parser.ParseAsFunctionDefinition()) {
196 m_basename = function.getValue().name.basename;
197 m_context = function.getValue().name.context;
198 m_arguments = function.getValue().arguments;
199 m_qualifiers = function.getValue().qualifiers;
200 m_parse_error = false;
202 m_parse_error = true;
209 llvm::StringRef CPlusPlusLanguage::MethodName::GetBasename() {
215 llvm::StringRef CPlusPlusLanguage::MethodName::GetContext() {
221 llvm::StringRef CPlusPlusLanguage::MethodName::GetArguments() {
227 llvm::StringRef CPlusPlusLanguage::MethodName::GetQualifiers() {
233 std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() {
236 if (m_context.empty())
246 bool CPlusPlusLanguage::IsCPPMangledName(const char *name) {
247 // FIXME!! we should really run through all the known C++ Language plugins
248 // and ask each one if this is a C++ mangled name
253 // MSVC style mangling
257 return (name[0] != '\0' && name[0] == '_' && name[1] == 'Z');
260 bool CPlusPlusLanguage::ExtractContextAndIdentifier(
261 const char *name, llvm::StringRef &context, llvm::StringRef &identifier) {
262 if (MSVCUndecoratedNameParser::IsMSVCUndecoratedName(name))
263 return MSVCUndecoratedNameParser::ExtractContextAndIdentifier(name, context,
266 CPlusPlusNameParser parser(name);
267 if (auto full_name = parser.ParseAsFullName()) {
268 identifier = full_name.getValue().basename;
269 context = full_name.getValue().context;
276 class NodeAllocator {
277 llvm::BumpPtrAllocator Alloc;
280 void reset() { Alloc.Reset(); }
282 template <typename T, typename... Args> T *makeNode(Args &&... args) {
283 return new (Alloc.Allocate(sizeof(T), alignof(T)))
284 T(std::forward<Args>(args)...);
287 void *allocateNodeArray(size_t sz) {
288 return Alloc.Allocate(sizeof(llvm::itanium_demangle::Node *) * sz,
289 alignof(llvm::itanium_demangle::Node *));
293 /// Given a mangled function `Mangled`, replace all the primitive function type
294 /// arguments of `Search` with type `Replace`.
295 class TypeSubstitutor
296 : public llvm::itanium_demangle::AbstractManglingParser<TypeSubstitutor,
298 /// Input character until which we have constructed the respective output
302 llvm::StringRef Search;
303 llvm::StringRef Replace;
304 llvm::SmallString<128> Result;
306 /// Whether we have performed any substitutions.
309 void reset(llvm::StringRef Mangled, llvm::StringRef Search,
310 llvm::StringRef Replace) {
311 AbstractManglingParser::reset(Mangled.begin(), Mangled.end());
312 Written = Mangled.begin();
313 this->Search = Search;
314 this->Replace = Replace;
319 void appendUnchangedInput() {
320 Result += llvm::StringRef(Written, First - Written);
325 TypeSubstitutor() : AbstractManglingParser(nullptr, nullptr) {}
327 ConstString substitute(llvm::StringRef Mangled, llvm::StringRef From,
328 llvm::StringRef To) {
329 Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
331 reset(Mangled, From, To);
332 if (parse() == nullptr) {
333 LLDB_LOG(log, "Failed to substitute mangling in {0}", Mangled);
334 return ConstString();
337 return ConstString();
339 // Append any trailing unmodified input.
340 appendUnchangedInput();
341 LLDB_LOG(log, "Substituted mangling {0} -> {1}", Mangled, Result);
342 return ConstString(Result);
345 llvm::itanium_demangle::Node *parseType() {
346 if (llvm::StringRef(First, numLeft()).startswith(Search)) {
347 // We found a match. Append unmodified input up to this point.
348 appendUnchangedInput();
350 // And then perform the replacement.
352 Written += Search.size();
355 return AbstractManglingParser::parseType();
360 uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
361 const ConstString mangled_name, std::set<ConstString> &alternates) {
362 const auto start_size = alternates.size();
363 /// Get a basic set of alternative manglings for the given symbol `name`, by
364 /// making a few basic possible substitutions on basic types, storage duration
365 /// and `const`ness for the given symbol. The output parameter `alternates`
366 /// is filled with a best-guess, non-exhaustive set of different manglings
367 /// for the given name.
369 // Maybe we're looking for a const symbol but the debug info told us it was
371 if (!strncmp(mangled_name.GetCString(), "_ZN", 3) &&
372 strncmp(mangled_name.GetCString(), "_ZNK", 4)) {
373 std::string fixed_scratch("_ZNK");
374 fixed_scratch.append(mangled_name.GetCString() + 3);
375 alternates.insert(ConstString(fixed_scratch));
378 // Maybe we're looking for a static symbol but we thought it was global...
379 if (!strncmp(mangled_name.GetCString(), "_Z", 2) &&
380 strncmp(mangled_name.GetCString(), "_ZL", 3)) {
381 std::string fixed_scratch("_ZL");
382 fixed_scratch.append(mangled_name.GetCString() + 2);
383 alternates.insert(ConstString(fixed_scratch));
387 // `char` is implementation defined as either `signed` or `unsigned`. As a
388 // result a char parameter has 3 possible manglings: 'c'-char, 'a'-signed
389 // char, 'h'-unsigned char. If we're looking for symbols with a signed char
390 // parameter, try finding matches which have the general case 'c'.
391 if (ConstString char_fixup =
392 TS.substitute(mangled_name.GetStringRef(), "a", "c"))
393 alternates.insert(char_fixup);
395 // long long parameter mangling 'x', may actually just be a long 'l' argument
396 if (ConstString long_fixup =
397 TS.substitute(mangled_name.GetStringRef(), "x", "l"))
398 alternates.insert(long_fixup);
400 // unsigned long long parameter mangling 'y', may actually just be unsigned
402 if (ConstString ulong_fixup =
403 TS.substitute(mangled_name.GetStringRef(), "y", "m"))
404 alternates.insert(ulong_fixup);
406 return alternates.size() - start_size;
409 static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
410 if (!cpp_category_sp)
413 TypeSummaryImpl::Flags stl_summary_flags;
414 stl_summary_flags.SetCascades(true)
415 .SetSkipPointers(false)
416 .SetSkipReferences(false)
417 .SetDontShowChildren(true)
418 .SetDontShowValue(true)
419 .SetShowMembersOneLiner(false)
420 .SetHideItemNames(false);
422 #ifndef LLDB_DISABLE_PYTHON
423 lldb::TypeSummaryImplSP std_string_summary_sp(new CXXFunctionSummaryFormat(
425 lldb_private::formatters::LibcxxStringSummaryProviderASCII,
426 "std::string summary provider"));
427 lldb::TypeSummaryImplSP std_stringu16_summary_sp(new CXXFunctionSummaryFormat(
429 lldb_private::formatters::LibcxxStringSummaryProviderUTF16,
430 "std::u16string summary provider"));
431 lldb::TypeSummaryImplSP std_stringu32_summary_sp(new CXXFunctionSummaryFormat(
433 lldb_private::formatters::LibcxxStringSummaryProviderUTF32,
434 "std::u32string summary provider"));
435 lldb::TypeSummaryImplSP std_wstring_summary_sp(new CXXFunctionSummaryFormat(
436 stl_summary_flags, lldb_private::formatters::LibcxxWStringSummaryProvider,
437 "std::wstring summary provider"));
439 cpp_category_sp->GetTypeSummariesContainer()->Add(
440 ConstString("std::__1::string"), std_string_summary_sp);
441 cpp_category_sp->GetTypeSummariesContainer()->Add(
442 ConstString("std::__ndk1::string"), std_string_summary_sp);
443 cpp_category_sp->GetTypeSummariesContainer()->Add(
444 ConstString("std::__1::basic_string<char, std::__1::char_traits<char>, "
445 "std::__1::allocator<char> >"),
446 std_string_summary_sp);
447 cpp_category_sp->GetTypeSummariesContainer()->Add(
449 "std::__1::basic_string<char16_t, std::__1::char_traits<char16_t>, "
450 "std::__1::allocator<char16_t> >"),
451 std_stringu16_summary_sp);
452 cpp_category_sp->GetTypeSummariesContainer()->Add(
454 "std::__1::basic_string<char32_t, std::__1::char_traits<char32_t>, "
455 "std::__1::allocator<char32_t> >"),
456 std_stringu32_summary_sp);
457 cpp_category_sp->GetTypeSummariesContainer()->Add(
458 ConstString("std::__ndk1::basic_string<char, "
459 "std::__ndk1::char_traits<char>, "
460 "std::__ndk1::allocator<char> >"),
461 std_string_summary_sp);
463 cpp_category_sp->GetTypeSummariesContainer()->Add(
464 ConstString("std::__1::wstring"), std_wstring_summary_sp);
465 cpp_category_sp->GetTypeSummariesContainer()->Add(
466 ConstString("std::__ndk1::wstring"), std_wstring_summary_sp);
467 cpp_category_sp->GetTypeSummariesContainer()->Add(
468 ConstString("std::__1::basic_string<wchar_t, "
469 "std::__1::char_traits<wchar_t>, "
470 "std::__1::allocator<wchar_t> >"),
471 std_wstring_summary_sp);
472 cpp_category_sp->GetTypeSummariesContainer()->Add(
473 ConstString("std::__ndk1::basic_string<wchar_t, "
474 "std::__ndk1::char_traits<wchar_t>, "
475 "std::__ndk1::allocator<wchar_t> >"),
476 std_wstring_summary_sp);
478 SyntheticChildren::Flags stl_synth_flags;
479 stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
481 SyntheticChildren::Flags stl_deref_flags = stl_synth_flags;
482 stl_deref_flags.SetFrontEndWantsDereference();
486 lldb_private::formatters::LibcxxBitsetSyntheticFrontEndCreator,
487 "libc++ std::bitset synthetic children",
488 ConstString("^std::__(ndk)?1::bitset<.+>(( )?&)?$"), stl_deref_flags,
492 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator,
493 "libc++ std::vector synthetic children",
494 ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_deref_flags,
498 lldb_private::formatters::LibcxxStdForwardListSyntheticFrontEndCreator,
499 "libc++ std::forward_list synthetic children",
500 ConstString("^std::__(ndk)?1::forward_list<.+>(( )?&)?$"),
501 stl_synth_flags, true);
504 lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator,
505 "libc++ std::list synthetic children",
506 ConstString("^std::__(ndk)?1::list<.+>(( )?&)?$"), stl_synth_flags, true);
509 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
510 "libc++ std::map synthetic children",
511 ConstString("^std::__(ndk)?1::map<.+> >(( )?&)?$"), stl_synth_flags,
515 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
516 "libc++ std::set synthetic children",
517 ConstString("^std::__(ndk)?1::set<.+> >(( )?&)?$"), stl_deref_flags,
521 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
522 "libc++ std::multiset synthetic children",
523 ConstString("^std::__(ndk)?1::multiset<.+> >(( )?&)?$"), stl_deref_flags,
527 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
528 "libc++ std::multimap synthetic children",
529 ConstString("^std::__(ndk)?1::multimap<.+> >(( )?&)?$"), stl_synth_flags,
533 lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator,
534 "libc++ std::unordered containers synthetic children",
535 ConstString("^(std::__(ndk)?1::)unordered_(multi)?(map|set)<.+> >$"),
536 stl_synth_flags, true);
539 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator,
540 "libc++ std::initializer_list synthetic children",
541 ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags,
543 AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator,
544 "libc++ std::queue synthetic children",
545 ConstString("^std::__(ndk)?1::queue<.+>(( )?&)?$"),
546 stl_synth_flags, true);
547 AddCXXSynthetic(cpp_category_sp, LibcxxTupleFrontEndCreator,
548 "libc++ std::tuple synthetic children",
549 ConstString("^std::__(ndk)?1::tuple<.*>(( )?&)?$"), stl_synth_flags,
551 AddCXXSynthetic(cpp_category_sp, LibcxxOptionalFrontEndCreator,
552 "libc++ std::optional synthetic children",
553 ConstString("^std::__(ndk)?1::optional<.+>(( )?&)?$"),
554 stl_synth_flags, true);
555 AddCXXSynthetic(cpp_category_sp, LibcxxVariantFrontEndCreator,
556 "libc++ std::variant synthetic children",
557 ConstString("^std::__(ndk)?1::variant<.+>(( )?&)?$"),
558 stl_synth_flags, true);
561 lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator,
562 "libc++ std::atomic synthetic children",
563 ConstString("^std::__(ndk)?1::atomic<.+>$"), stl_synth_flags, true);
565 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
566 RegularExpressionSP(new RegularExpression(
567 llvm::StringRef("^(std::__(ndk)?1::)deque<.+>(( )?&)?$"))),
568 SyntheticChildrenSP(new ScriptedSyntheticChildren(
570 "lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));
574 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,
575 "shared_ptr synthetic children",
576 ConstString("^(std::__(ndk)?1::)shared_ptr<.+>(( )?&)?$"),
577 stl_synth_flags, true);
580 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,
581 "weak_ptr synthetic children",
582 ConstString("^(std::__(ndk)?1::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags,
586 cpp_category_sp, lldb_private::formatters::LibcxxFunctionSummaryProvider,
587 "libc++ std::function summary provider",
588 ConstString("^std::__(ndk)?1::function<.+>$"), stl_summary_flags, true);
590 stl_summary_flags.SetDontShowChildren(false);
591 stl_summary_flags.SetSkipPointers(false);
592 AddCXXSummary(cpp_category_sp,
593 lldb_private::formatters::LibcxxContainerSummaryProvider,
594 "libc++ std::bitset summary provider",
595 ConstString("^std::__(ndk)?1::bitset<.+>(( )?&)?$"),
596 stl_summary_flags, true);
597 AddCXXSummary(cpp_category_sp,
598 lldb_private::formatters::LibcxxContainerSummaryProvider,
599 "libc++ std::vector summary provider",
600 ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"),
601 stl_summary_flags, true);
602 AddCXXSummary(cpp_category_sp,
603 lldb_private::formatters::LibcxxContainerSummaryProvider,
604 "libc++ std::list summary provider",
605 ConstString("^std::__(ndk)?1::forward_list<.+>(( )?&)?$"),
606 stl_summary_flags, true);
607 AddCXXSummary(cpp_category_sp,
608 lldb_private::formatters::LibcxxContainerSummaryProvider,
609 "libc++ std::list summary provider",
610 ConstString("^std::__(ndk)?1::list<.+>(( )?&)?$"),
611 stl_summary_flags, true);
612 AddCXXSummary(cpp_category_sp,
613 lldb_private::formatters::LibcxxContainerSummaryProvider,
614 "libc++ std::map summary provider",
615 ConstString("^std::__(ndk)?1::map<.+>(( )?&)?$"),
616 stl_summary_flags, true);
617 AddCXXSummary(cpp_category_sp,
618 lldb_private::formatters::LibcxxContainerSummaryProvider,
619 "libc++ std::deque summary provider",
620 ConstString("^std::__(ndk)?1::deque<.+>(( )?&)?$"),
621 stl_summary_flags, true);
622 AddCXXSummary(cpp_category_sp,
623 lldb_private::formatters::LibcxxContainerSummaryProvider,
624 "libc++ std::queue summary provider",
625 ConstString("^std::__(ndk)?1::queue<.+>(( )?&)?$"),
626 stl_summary_flags, true);
627 AddCXXSummary(cpp_category_sp,
628 lldb_private::formatters::LibcxxContainerSummaryProvider,
629 "libc++ std::set summary provider",
630 ConstString("^std::__(ndk)?1::set<.+>(( )?&)?$"),
631 stl_summary_flags, true);
632 AddCXXSummary(cpp_category_sp,
633 lldb_private::formatters::LibcxxContainerSummaryProvider,
634 "libc++ std::multiset summary provider",
635 ConstString("^std::__(ndk)?1::multiset<.+>(( )?&)?$"),
636 stl_summary_flags, true);
637 AddCXXSummary(cpp_category_sp,
638 lldb_private::formatters::LibcxxContainerSummaryProvider,
639 "libc++ std::multimap summary provider",
640 ConstString("^std::__(ndk)?1::multimap<.+>(( )?&)?$"),
641 stl_summary_flags, true);
643 cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider,
644 "libc++ std::unordered containers summary provider",
645 ConstString("^(std::__(ndk)?1::)unordered_(multi)?(map|set)<.+> >$"),
646 stl_summary_flags, true);
647 AddCXXSummary(cpp_category_sp, LibcxxContainerSummaryProvider,
648 "libc++ std::tuple summary provider",
649 ConstString("^std::__(ndk)?1::tuple<.*>(( )?&)?$"), stl_summary_flags,
652 cpp_category_sp, lldb_private::formatters::LibCxxAtomicSummaryProvider,
653 "libc++ std::atomic summary provider",
654 ConstString("^std::__(ndk)?1::atomic<.+>$"), stl_summary_flags, true);
655 AddCXXSummary(cpp_category_sp,
656 lldb_private::formatters::LibcxxOptionalSummaryProvider,
657 "libc++ std::optional summary provider",
658 ConstString("^std::__(ndk)?1::optional<.+>(( )?&)?$"),
659 stl_summary_flags, true);
660 AddCXXSummary(cpp_category_sp,
661 lldb_private::formatters::LibcxxVariantSummaryProvider,
662 "libc++ std::variant summary provider",
663 ConstString("^std::__(ndk)?1::variant<.+>(( )?&)?$"),
664 stl_summary_flags, true);
666 stl_summary_flags.SetSkipPointers(true);
668 AddCXXSummary(cpp_category_sp,
669 lldb_private::formatters::LibcxxSmartPointerSummaryProvider,
670 "libc++ std::shared_ptr summary provider",
671 ConstString("^std::__(ndk)?1::shared_ptr<.+>(( )?&)?$"),
672 stl_summary_flags, true);
673 AddCXXSummary(cpp_category_sp,
674 lldb_private::formatters::LibcxxSmartPointerSummaryProvider,
675 "libc++ std::weak_ptr summary provider",
676 ConstString("^std::__(ndk)?1::weak_ptr<.+>(( )?&)?$"),
677 stl_summary_flags, true);
681 lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator,
682 "std::vector iterator synthetic children",
683 ConstString("^std::__(ndk)?1::__wrap_iter<.+>$"), stl_synth_flags, true);
687 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator,
688 "std::map iterator synthetic children",
689 ConstString("^std::__(ndk)?1::__map_iterator<.+>$"), stl_synth_flags,
694 static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
695 if (!cpp_category_sp)
698 TypeSummaryImpl::Flags stl_summary_flags;
699 stl_summary_flags.SetCascades(true)
700 .SetSkipPointers(false)
701 .SetSkipReferences(false)
702 .SetDontShowChildren(true)
703 .SetDontShowValue(true)
704 .SetShowMembersOneLiner(false)
705 .SetHideItemNames(false);
707 lldb::TypeSummaryImplSP std_string_summary_sp(
708 new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p}"));
710 lldb::TypeSummaryImplSP cxx11_string_summary_sp(new CXXFunctionSummaryFormat(
711 stl_summary_flags, LibStdcppStringSummaryProvider,
712 "libstdc++ c++11 std::string summary provider"));
713 lldb::TypeSummaryImplSP cxx11_wstring_summary_sp(new CXXFunctionSummaryFormat(
714 stl_summary_flags, LibStdcppWStringSummaryProvider,
715 "libstdc++ c++11 std::wstring summary provider"));
717 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::string"),
718 std_string_summary_sp);
719 cpp_category_sp->GetTypeSummariesContainer()->Add(
720 ConstString("std::basic_string<char>"), std_string_summary_sp);
721 cpp_category_sp->GetTypeSummariesContainer()->Add(
722 ConstString("std::basic_string<char,std::char_traits<char>,std::"
723 "allocator<char> >"),
724 std_string_summary_sp);
725 cpp_category_sp->GetTypeSummariesContainer()->Add(
726 ConstString("std::basic_string<char, std::char_traits<char>, "
727 "std::allocator<char> >"),
728 std_string_summary_sp);
730 cpp_category_sp->GetTypeSummariesContainer()->Add(
731 ConstString("std::__cxx11::string"), cxx11_string_summary_sp);
732 cpp_category_sp->GetTypeSummariesContainer()->Add(
733 ConstString("std::__cxx11::basic_string<char, std::char_traits<char>, "
734 "std::allocator<char> >"),
735 cxx11_string_summary_sp);
737 // making sure we force-pick the summary for printing wstring (_M_p is a
739 lldb::TypeSummaryImplSP std_wstring_summary_sp(
740 new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p%S}"));
742 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::wstring"),
743 std_wstring_summary_sp);
744 cpp_category_sp->GetTypeSummariesContainer()->Add(
745 ConstString("std::basic_string<wchar_t>"), std_wstring_summary_sp);
746 cpp_category_sp->GetTypeSummariesContainer()->Add(
747 ConstString("std::basic_string<wchar_t,std::char_traits<wchar_t>,std::"
748 "allocator<wchar_t> >"),
749 std_wstring_summary_sp);
750 cpp_category_sp->GetTypeSummariesContainer()->Add(
751 ConstString("std::basic_string<wchar_t, std::char_traits<wchar_t>, "
752 "std::allocator<wchar_t> >"),
753 std_wstring_summary_sp);
755 cpp_category_sp->GetTypeSummariesContainer()->Add(
756 ConstString("std::__cxx11::wstring"), cxx11_wstring_summary_sp);
757 cpp_category_sp->GetTypeSummariesContainer()->Add(
758 ConstString("std::__cxx11::basic_string<wchar_t, "
759 "std::char_traits<wchar_t>, std::allocator<wchar_t> >"),
760 cxx11_wstring_summary_sp);
762 #ifndef LLDB_DISABLE_PYTHON
764 SyntheticChildren::Flags stl_synth_flags;
765 stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
768 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
770 new RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$"))),
771 SyntheticChildrenSP(new ScriptedSyntheticChildren(
773 "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
774 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
776 new RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$"))),
777 SyntheticChildrenSP(new ScriptedSyntheticChildren(
779 "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider")));
780 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
781 RegularExpressionSP(new RegularExpression(
782 llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$"))),
783 SyntheticChildrenSP(new ScriptedSyntheticChildren(
785 "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
786 stl_summary_flags.SetDontShowChildren(false);
787 stl_summary_flags.SetSkipPointers(true);
788 cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
790 new RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$"))),
792 new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
793 cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
795 new RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$"))),
797 new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
798 cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
799 RegularExpressionSP(new RegularExpression(
800 llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$"))),
802 new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
806 lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator,
807 "std::vector iterator synthetic children",
808 ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
812 lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator,
813 "std::map iterator synthetic children",
814 ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
818 lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator,
819 "std::unique_ptr synthetic children",
820 ConstString("^std::unique_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
823 lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator,
824 "std::shared_ptr synthetic children",
825 ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
828 lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator,
829 "std::weak_ptr synthetic children",
830 ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
833 lldb_private::formatters::LibStdcppTupleSyntheticFrontEndCreator,
834 "std::tuple synthetic children", ConstString("^std::tuple<.+>(( )?&)?$"),
835 stl_synth_flags, true);
837 AddCXXSummary(cpp_category_sp,
838 lldb_private::formatters::LibStdcppUniquePointerSummaryProvider,
839 "libstdc++ std::unique_ptr summary provider",
840 ConstString("^std::unique_ptr<.+>(( )?&)?$"), stl_summary_flags,
842 AddCXXSummary(cpp_category_sp,
843 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider,
844 "libstdc++ std::shared_ptr summary provider",
845 ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_summary_flags,
847 AddCXXSummary(cpp_category_sp,
848 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider,
849 "libstdc++ std::weak_ptr summary provider",
850 ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_summary_flags,
855 static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
856 if (!cpp_category_sp)
859 TypeSummaryImpl::Flags string_flags;
860 string_flags.SetCascades(true)
861 .SetSkipPointers(true)
862 .SetSkipReferences(false)
863 .SetDontShowChildren(true)
864 .SetDontShowValue(false)
865 .SetShowMembersOneLiner(false)
866 .SetHideItemNames(false);
868 TypeSummaryImpl::Flags string_array_flags;
869 string_array_flags.SetCascades(true)
870 .SetSkipPointers(true)
871 .SetSkipReferences(false)
872 .SetDontShowChildren(true)
873 .SetDontShowValue(true)
874 .SetShowMembersOneLiner(false)
875 .SetHideItemNames(false);
877 #ifndef LLDB_DISABLE_PYTHON
878 // FIXME because of a bug in the FormattersContainer we need to add a summary
879 // for both X* and const X* (<rdar://problem/12717717>)
881 cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider,
882 "char16_t * summary provider", ConstString("char16_t *"), string_flags);
883 AddCXXSummary(cpp_category_sp,
884 lldb_private::formatters::Char16StringSummaryProvider,
885 "char16_t [] summary provider",
886 ConstString("char16_t \\[[0-9]+\\]"), string_array_flags, true);
889 cpp_category_sp, lldb_private::formatters::Char32StringSummaryProvider,
890 "char32_t * summary provider", ConstString("char32_t *"), string_flags);
891 AddCXXSummary(cpp_category_sp,
892 lldb_private::formatters::Char32StringSummaryProvider,
893 "char32_t [] summary provider",
894 ConstString("char32_t \\[[0-9]+\\]"), string_array_flags, true);
897 cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider,
898 "wchar_t * summary provider", ConstString("wchar_t *"), string_flags);
899 AddCXXSummary(cpp_category_sp,
900 lldb_private::formatters::WCharStringSummaryProvider,
901 "wchar_t * summary provider",
902 ConstString("wchar_t \\[[0-9]+\\]"), string_array_flags, true);
905 cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider,
906 "unichar * summary provider", ConstString("unichar *"), string_flags);
908 TypeSummaryImpl::Flags widechar_flags;
909 widechar_flags.SetDontShowValue(true)
910 .SetSkipPointers(true)
911 .SetSkipReferences(false)
913 .SetDontShowChildren(true)
914 .SetHideItemNames(true)
915 .SetShowMembersOneLiner(false);
918 cpp_category_sp, lldb_private::formatters::Char16SummaryProvider,
919 "char16_t summary provider", ConstString("char16_t"), widechar_flags);
921 cpp_category_sp, lldb_private::formatters::Char32SummaryProvider,
922 "char32_t summary provider", ConstString("char32_t"), widechar_flags);
923 AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharSummaryProvider,
924 "wchar_t summary provider", ConstString("wchar_t"),
928 cpp_category_sp, lldb_private::formatters::Char16SummaryProvider,
929 "unichar summary provider", ConstString("unichar"), widechar_flags);
933 std::unique_ptr<Language::TypeScavenger> CPlusPlusLanguage::GetTypeScavenger() {
934 class CPlusPlusTypeScavenger : public Language::ImageListTypeScavenger {
936 virtual CompilerType AdjustForInclusion(CompilerType &candidate) override {
937 LanguageType lang_type(candidate.GetMinimumLanguage());
938 if (!Language::LanguageIsC(lang_type) &&
939 !Language::LanguageIsCPlusPlus(lang_type))
940 return CompilerType();
941 if (candidate.IsTypedefType())
942 return candidate.GetTypedefedType();
947 return std::unique_ptr<TypeScavenger>(new CPlusPlusTypeScavenger());
950 lldb::TypeCategoryImplSP CPlusPlusLanguage::GetFormatters() {
951 static llvm::once_flag g_initialize;
952 static TypeCategoryImplSP g_category;
954 llvm::call_once(g_initialize, [this]() -> void {
955 DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
957 LoadLibCxxFormatters(g_category);
958 LoadLibStdcppFormatters(g_category);
959 LoadSystemFormatters(g_category);
965 HardcodedFormatters::HardcodedSummaryFinder
966 CPlusPlusLanguage::GetHardcodedSummaries() {
967 static llvm::once_flag g_initialize;
968 static ConstString g_vectortypes("VectorTypes");
969 static HardcodedFormatters::HardcodedSummaryFinder g_formatters;
971 llvm::call_once(g_initialize, []() -> void {
972 g_formatters.push_back(
973 [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
974 FormatManager &) -> TypeSummaryImpl::SharedPointer {
975 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
976 new CXXFunctionSummaryFormat(
977 TypeSummaryImpl::Flags(),
978 lldb_private::formatters::CXXFunctionPointerSummaryProvider,
979 "Function pointer summary provider"));
980 if (valobj.GetCompilerType().IsFunctionPointerType()) {
985 g_formatters.push_back(
986 [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
987 FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer {
988 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
989 new CXXFunctionSummaryFormat(
990 TypeSummaryImpl::Flags()
992 .SetDontShowChildren(true)
993 .SetHideItemNames(true)
994 .SetShowMembersOneLiner(true)
995 .SetSkipPointers(true)
996 .SetSkipReferences(false),
997 lldb_private::formatters::VectorTypeSummaryProvider,
998 "vector_type pointer summary provider"));
999 if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) {
1000 if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
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::BlockPointerSummaryProvider,
1018 "block pointer summary provider"));
1019 if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) {
1020 return formatter_sp;
1026 return g_formatters;
1029 HardcodedFormatters::HardcodedSyntheticFinder
1030 CPlusPlusLanguage::GetHardcodedSynthetics() {
1031 static llvm::once_flag g_initialize;
1032 static ConstString g_vectortypes("VectorTypes");
1033 static HardcodedFormatters::HardcodedSyntheticFinder g_formatters;
1035 llvm::call_once(g_initialize, []() -> void {
1036 g_formatters.push_back([](lldb_private::ValueObject &valobj,
1037 lldb::DynamicValueType,
1039 fmt_mgr) -> SyntheticChildren::SharedPointer {
1040 static CXXSyntheticChildren::SharedPointer formatter_sp(
1041 new CXXSyntheticChildren(
1042 SyntheticChildren::Flags()
1044 .SetSkipPointers(true)
1045 .SetSkipReferences(true)
1046 .SetNonCacheable(true),
1047 "vector_type synthetic children",
1048 lldb_private::formatters::VectorTypeSyntheticFrontEndCreator));
1049 if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) {
1050 if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
1051 return formatter_sp;
1055 g_formatters.push_back([](lldb_private::ValueObject &valobj,
1056 lldb::DynamicValueType,
1058 fmt_mgr) -> SyntheticChildren::SharedPointer {
1059 static CXXSyntheticChildren::SharedPointer formatter_sp(
1060 new CXXSyntheticChildren(
1061 SyntheticChildren::Flags()
1063 .SetSkipPointers(true)
1064 .SetSkipReferences(true)
1065 .SetNonCacheable(true),
1066 "block pointer synthetic children",
1067 lldb_private::formatters::BlockPointerSyntheticFrontEndCreator));
1068 if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) {
1069 return formatter_sp;
1076 return g_formatters;
1079 bool CPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const {
1080 const auto suffixes = {".cpp", ".cxx", ".c++", ".cc", ".c",
1081 ".h", ".hh", ".hpp", ".hxx", ".h++"};
1082 for (auto suffix : suffixes) {
1083 if (file_path.endswith_lower(suffix))
1087 // Check if we're in a STL path (where the files usually have no extension
1088 // that we could check for.
1089 return file_path.contains("/usr/include/c++/");