1 //===-- CPlusPlusLanguage.cpp ---------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "CPlusPlusLanguage.h" 10 11 #include <cctype> 12 #include <cstring> 13 14 #include <functional> 15 #include <memory> 16 #include <mutex> 17 #include <set> 18 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/Demangle/ItaniumDemangle.h" 21 22 #include "lldb/Core/Mangled.h" 23 #include "lldb/Core/Module.h" 24 #include "lldb/Core/PluginManager.h" 25 #include "lldb/Core/UniqueCStringMap.h" 26 #include "lldb/DataFormatters/CXXFunctionPointer.h" 27 #include "lldb/DataFormatters/DataVisualization.h" 28 #include "lldb/DataFormatters/FormattersHelpers.h" 29 #include "lldb/DataFormatters/VectorType.h" 30 #include "lldb/Symbol/SymbolFile.h" 31 #include "lldb/Utility/ConstString.h" 32 #include "lldb/Utility/LLDBLog.h" 33 #include "lldb/Utility/Log.h" 34 #include "lldb/Utility/RegularExpression.h" 35 36 #include "BlockPointer.h" 37 #include "CPlusPlusNameParser.h" 38 #include "Coroutines.h" 39 #include "CxxStringTypes.h" 40 #include "Generic.h" 41 #include "LibCxx.h" 42 #include "LibCxxAtomic.h" 43 #include "LibCxxVariant.h" 44 #include "LibStdcpp.h" 45 #include "MSVCUndecoratedNameParser.h" 46 47 using namespace lldb; 48 using namespace lldb_private; 49 using namespace lldb_private::formatters; 50 51 LLDB_PLUGIN_DEFINE(CPlusPlusLanguage) 52 53 void CPlusPlusLanguage::Initialize() { 54 PluginManager::RegisterPlugin(GetPluginNameStatic(), "C++ Language", 55 CreateInstance); 56 } 57 58 void CPlusPlusLanguage::Terminate() { 59 PluginManager::UnregisterPlugin(CreateInstance); 60 } 61 62 bool CPlusPlusLanguage::SymbolNameFitsToLanguage(Mangled mangled) const { 63 const char *mangled_name = mangled.GetMangledName().GetCString(); 64 return mangled_name && CPlusPlusLanguage::IsCPPMangledName(mangled_name); 65 } 66 67 ConstString CPlusPlusLanguage::GetDemangledFunctionNameWithoutArguments( 68 Mangled mangled) const { 69 const char *mangled_name_cstr = mangled.GetMangledName().GetCString(); 70 ConstString demangled_name = mangled.GetDemangledName(); 71 if (demangled_name && mangled_name_cstr && mangled_name_cstr[0]) { 72 if (mangled_name_cstr[0] == '_' && mangled_name_cstr[1] == 'Z' && 73 (mangled_name_cstr[2] != 'T' && // avoid virtual table, VTT structure, 74 // typeinfo structure, and typeinfo 75 // mangled_name 76 mangled_name_cstr[2] != 'G' && // avoid guard variables 77 mangled_name_cstr[2] != 'Z')) // named local entities (if we 78 // eventually handle eSymbolTypeData, 79 // we will want this back) 80 { 81 CPlusPlusLanguage::MethodName cxx_method(demangled_name); 82 if (!cxx_method.GetBasename().empty()) { 83 std::string shortname; 84 if (!cxx_method.GetContext().empty()) 85 shortname = cxx_method.GetContext().str() + "::"; 86 shortname += cxx_method.GetBasename().str(); 87 return ConstString(shortname); 88 } 89 } 90 } 91 if (demangled_name) 92 return demangled_name; 93 return mangled.GetMangledName(); 94 } 95 96 // Static Functions 97 98 Language *CPlusPlusLanguage::CreateInstance(lldb::LanguageType language) { 99 // Use plugin for C++ but not for Objective-C++ (which has its own plugin). 100 if (Language::LanguageIsCPlusPlus(language) && 101 language != eLanguageTypeObjC_plus_plus) 102 return new CPlusPlusLanguage(); 103 return nullptr; 104 } 105 106 void CPlusPlusLanguage::MethodName::Clear() { 107 m_full.Clear(); 108 m_basename = llvm::StringRef(); 109 m_context = llvm::StringRef(); 110 m_arguments = llvm::StringRef(); 111 m_qualifiers = llvm::StringRef(); 112 m_parsed = false; 113 m_parse_error = false; 114 } 115 116 static bool ReverseFindMatchingChars(const llvm::StringRef &s, 117 const llvm::StringRef &left_right_chars, 118 size_t &left_pos, size_t &right_pos, 119 size_t pos = llvm::StringRef::npos) { 120 assert(left_right_chars.size() == 2); 121 left_pos = llvm::StringRef::npos; 122 const char left_char = left_right_chars[0]; 123 const char right_char = left_right_chars[1]; 124 pos = s.find_last_of(left_right_chars, pos); 125 if (pos == llvm::StringRef::npos || s[pos] == left_char) 126 return false; 127 right_pos = pos; 128 uint32_t depth = 1; 129 while (pos > 0 && depth > 0) { 130 pos = s.find_last_of(left_right_chars, pos); 131 if (pos == llvm::StringRef::npos) 132 return false; 133 if (s[pos] == left_char) { 134 if (--depth == 0) { 135 left_pos = pos; 136 return left_pos < right_pos; 137 } 138 } else if (s[pos] == right_char) { 139 ++depth; 140 } 141 } 142 return false; 143 } 144 145 static bool IsTrivialBasename(const llvm::StringRef &basename) { 146 // Check that the basename matches with the following regular expression 147 // "^~?([A-Za-z_][A-Za-z_0-9]*)$" We are using a hand written implementation 148 // because it is significantly more efficient then using the general purpose 149 // regular expression library. 150 size_t idx = 0; 151 if (basename.size() > 0 && basename[0] == '~') 152 idx = 1; 153 154 if (basename.size() <= idx) 155 return false; // Empty string or "~" 156 157 if (!std::isalpha(basename[idx]) && basename[idx] != '_') 158 return false; // First character (after removing the possible '~'') isn't in 159 // [A-Za-z_] 160 161 // Read all characters matching [A-Za-z_0-9] 162 ++idx; 163 while (idx < basename.size()) { 164 if (!std::isalnum(basename[idx]) && basename[idx] != '_') 165 break; 166 ++idx; 167 } 168 169 // We processed all characters. It is a vaild basename. 170 return idx == basename.size(); 171 } 172 173 bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() { 174 // This method tries to parse simple method definitions which are presumably 175 // most comman in user programs. Definitions that can be parsed by this 176 // function don't have return types and templates in the name. 177 // A::B::C::fun(std::vector<T> &) const 178 size_t arg_start, arg_end; 179 llvm::StringRef full(m_full.GetCString()); 180 llvm::StringRef parens("()", 2); 181 if (ReverseFindMatchingChars(full, parens, arg_start, arg_end)) { 182 m_arguments = full.substr(arg_start, arg_end - arg_start + 1); 183 if (arg_end + 1 < full.size()) 184 m_qualifiers = full.substr(arg_end + 1).ltrim(); 185 186 if (arg_start == 0) 187 return false; 188 size_t basename_end = arg_start; 189 size_t context_start = 0; 190 size_t context_end = full.rfind(':', basename_end); 191 if (context_end == llvm::StringRef::npos) 192 m_basename = full.substr(0, basename_end); 193 else { 194 if (context_start < context_end) 195 m_context = full.substr(context_start, context_end - 1 - context_start); 196 const size_t basename_begin = context_end + 1; 197 m_basename = full.substr(basename_begin, basename_end - basename_begin); 198 } 199 200 if (IsTrivialBasename(m_basename)) { 201 return true; 202 } else { 203 // The C++ basename doesn't match our regular expressions so this can't 204 // be a valid C++ method, clear everything out and indicate an error 205 m_context = llvm::StringRef(); 206 m_basename = llvm::StringRef(); 207 m_arguments = llvm::StringRef(); 208 m_qualifiers = llvm::StringRef(); 209 return false; 210 } 211 } 212 return false; 213 } 214 215 void CPlusPlusLanguage::MethodName::Parse() { 216 if (!m_parsed && m_full) { 217 if (TrySimplifiedParse()) { 218 m_parse_error = false; 219 } else { 220 CPlusPlusNameParser parser(m_full.GetStringRef()); 221 if (auto function = parser.ParseAsFunctionDefinition()) { 222 m_basename = function.value().name.basename; 223 m_context = function.value().name.context; 224 m_arguments = function.value().arguments; 225 m_qualifiers = function.value().qualifiers; 226 m_parse_error = false; 227 } else { 228 m_parse_error = true; 229 } 230 } 231 m_parsed = true; 232 } 233 } 234 235 llvm::StringRef CPlusPlusLanguage::MethodName::GetBasename() { 236 if (!m_parsed) 237 Parse(); 238 return m_basename; 239 } 240 241 llvm::StringRef CPlusPlusLanguage::MethodName::GetContext() { 242 if (!m_parsed) 243 Parse(); 244 return m_context; 245 } 246 247 llvm::StringRef CPlusPlusLanguage::MethodName::GetArguments() { 248 if (!m_parsed) 249 Parse(); 250 return m_arguments; 251 } 252 253 llvm::StringRef CPlusPlusLanguage::MethodName::GetQualifiers() { 254 if (!m_parsed) 255 Parse(); 256 return m_qualifiers; 257 } 258 259 std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() { 260 if (!m_parsed) 261 Parse(); 262 if (m_context.empty()) 263 return std::string(m_basename); 264 265 std::string res; 266 res += m_context; 267 res += "::"; 268 res += m_basename; 269 return res; 270 } 271 272 llvm::StringRef 273 CPlusPlusLanguage::MethodName::GetBasenameNoTemplateParameters() { 274 llvm::StringRef basename = GetBasename(); 275 size_t arg_start, arg_end; 276 llvm::StringRef parens("<>", 2); 277 if (ReverseFindMatchingChars(basename, parens, arg_start, arg_end)) 278 return basename.substr(0, arg_start); 279 280 return basename; 281 } 282 283 bool CPlusPlusLanguage::MethodName::ContainsPath(llvm::StringRef path) { 284 if (!m_parsed) 285 Parse(); 286 287 // If we can't parse the incoming name, then just check that it contains path. 288 if (m_parse_error) 289 return m_full.GetStringRef().contains(path); 290 291 llvm::StringRef identifier; 292 llvm::StringRef context; 293 std::string path_str = path.str(); 294 bool success 295 = CPlusPlusLanguage::ExtractContextAndIdentifier(path_str.c_str(), 296 context, 297 identifier); 298 if (!success) 299 return m_full.GetStringRef().contains(path); 300 301 // Basename may include template arguments. 302 // E.g., 303 // GetBaseName(): func<int> 304 // identifier : func 305 // 306 // ...but we still want to account for identifiers with template parameter 307 // lists, e.g., when users set breakpoints on template specializations. 308 // 309 // E.g., 310 // GetBaseName(): func<uint32_t> 311 // identifier : func<int32_t*> 312 // 313 // Try to match the basename with or without template parameters. 314 if (GetBasename() != identifier && 315 GetBasenameNoTemplateParameters() != identifier) 316 return false; 317 318 // Incoming path only had an identifier, so we match. 319 if (context.empty()) 320 return true; 321 // Incoming path has context but this method does not, no match. 322 if (m_context.empty()) 323 return false; 324 325 llvm::StringRef haystack = m_context; 326 if (!haystack.consume_back(context)) 327 return false; 328 if (haystack.empty() || !isalnum(haystack.back())) 329 return true; 330 331 return false; 332 } 333 334 bool CPlusPlusLanguage::IsCPPMangledName(llvm::StringRef name) { 335 // FIXME!! we should really run through all the known C++ Language plugins 336 // and ask each one if this is a C++ mangled name 337 338 Mangled::ManglingScheme scheme = Mangled::GetManglingScheme(name); 339 340 if (scheme == Mangled::eManglingSchemeNone) 341 return false; 342 343 return true; 344 } 345 346 bool CPlusPlusLanguage::DemangledNameContainsPath(llvm::StringRef path, 347 ConstString demangled) const { 348 MethodName demangled_name(demangled); 349 return demangled_name.ContainsPath(path); 350 } 351 352 bool CPlusPlusLanguage::ExtractContextAndIdentifier( 353 const char *name, llvm::StringRef &context, llvm::StringRef &identifier) { 354 if (MSVCUndecoratedNameParser::IsMSVCUndecoratedName(name)) 355 return MSVCUndecoratedNameParser::ExtractContextAndIdentifier(name, context, 356 identifier); 357 358 CPlusPlusNameParser parser(name); 359 if (auto full_name = parser.ParseAsFullName()) { 360 identifier = full_name.value().basename; 361 context = full_name.value().context; 362 return true; 363 } 364 return false; 365 } 366 367 namespace { 368 class NodeAllocator { 369 llvm::BumpPtrAllocator Alloc; 370 371 public: 372 void reset() { Alloc.Reset(); } 373 374 template <typename T, typename... Args> T *makeNode(Args &&... args) { 375 return new (Alloc.Allocate(sizeof(T), alignof(T))) 376 T(std::forward<Args>(args)...); 377 } 378 379 void *allocateNodeArray(size_t sz) { 380 return Alloc.Allocate(sizeof(llvm::itanium_demangle::Node *) * sz, 381 alignof(llvm::itanium_demangle::Node *)); 382 } 383 }; 384 385 template <typename Derived> 386 class ManglingSubstitutor 387 : public llvm::itanium_demangle::AbstractManglingParser<Derived, 388 NodeAllocator> { 389 using Base = 390 llvm::itanium_demangle::AbstractManglingParser<Derived, NodeAllocator>; 391 392 public: 393 ManglingSubstitutor() : Base(nullptr, nullptr) {} 394 395 template <typename... Ts> 396 ConstString substitute(llvm::StringRef Mangled, Ts &&... Vals) { 397 this->getDerived().reset(Mangled, std::forward<Ts>(Vals)...); 398 return substituteImpl(Mangled); 399 } 400 401 protected: 402 void reset(llvm::StringRef Mangled) { 403 Base::reset(Mangled.begin(), Mangled.end()); 404 Written = Mangled.begin(); 405 Result.clear(); 406 Substituted = false; 407 } 408 409 ConstString substituteImpl(llvm::StringRef Mangled) { 410 Log *log = GetLog(LLDBLog::Language); 411 if (this->parse() == nullptr) { 412 LLDB_LOG(log, "Failed to substitute mangling in {0}", Mangled); 413 return ConstString(); 414 } 415 if (!Substituted) 416 return ConstString(); 417 418 // Append any trailing unmodified input. 419 appendUnchangedInput(); 420 LLDB_LOG(log, "Substituted mangling {0} -> {1}", Mangled, Result); 421 return ConstString(Result); 422 } 423 424 void trySubstitute(llvm::StringRef From, llvm::StringRef To) { 425 if (!llvm::StringRef(currentParserPos(), this->numLeft()).startswith(From)) 426 return; 427 428 // We found a match. Append unmodified input up to this point. 429 appendUnchangedInput(); 430 431 // And then perform the replacement. 432 Result += To; 433 Written += From.size(); 434 Substituted = true; 435 } 436 437 private: 438 /// Input character until which we have constructed the respective output 439 /// already. 440 const char *Written = ""; 441 442 llvm::SmallString<128> Result; 443 444 /// Whether we have performed any substitutions. 445 bool Substituted = false; 446 447 const char *currentParserPos() const { return this->First; } 448 449 void appendUnchangedInput() { 450 Result += 451 llvm::StringRef(Written, std::distance(Written, currentParserPos())); 452 Written = currentParserPos(); 453 } 454 }; 455 456 /// Given a mangled function `Mangled`, replace all the primitive function type 457 /// arguments of `Search` with type `Replace`. 458 class TypeSubstitutor : public ManglingSubstitutor<TypeSubstitutor> { 459 llvm::StringRef Search; 460 llvm::StringRef Replace; 461 462 public: 463 void reset(llvm::StringRef Mangled, llvm::StringRef Search, 464 llvm::StringRef Replace) { 465 ManglingSubstitutor::reset(Mangled); 466 this->Search = Search; 467 this->Replace = Replace; 468 } 469 470 llvm::itanium_demangle::Node *parseType() { 471 trySubstitute(Search, Replace); 472 return ManglingSubstitutor::parseType(); 473 } 474 }; 475 476 class CtorDtorSubstitutor : public ManglingSubstitutor<CtorDtorSubstitutor> { 477 public: 478 llvm::itanium_demangle::Node * 479 parseCtorDtorName(llvm::itanium_demangle::Node *&SoFar, NameState *State) { 480 trySubstitute("C1", "C2"); 481 trySubstitute("D1", "D2"); 482 return ManglingSubstitutor::parseCtorDtorName(SoFar, State); 483 } 484 }; 485 } // namespace 486 487 std::vector<ConstString> CPlusPlusLanguage::GenerateAlternateFunctionManglings( 488 const ConstString mangled_name) const { 489 std::vector<ConstString> alternates; 490 491 /// Get a basic set of alternative manglings for the given symbol `name`, by 492 /// making a few basic possible substitutions on basic types, storage duration 493 /// and `const`ness for the given symbol. The output parameter `alternates` 494 /// is filled with a best-guess, non-exhaustive set of different manglings 495 /// for the given name. 496 497 // Maybe we're looking for a const symbol but the debug info told us it was 498 // non-const... 499 if (!strncmp(mangled_name.GetCString(), "_ZN", 3) && 500 strncmp(mangled_name.GetCString(), "_ZNK", 4)) { 501 std::string fixed_scratch("_ZNK"); 502 fixed_scratch.append(mangled_name.GetCString() + 3); 503 alternates.push_back(ConstString(fixed_scratch)); 504 } 505 506 // Maybe we're looking for a static symbol but we thought it was global... 507 if (!strncmp(mangled_name.GetCString(), "_Z", 2) && 508 strncmp(mangled_name.GetCString(), "_ZL", 3)) { 509 std::string fixed_scratch("_ZL"); 510 fixed_scratch.append(mangled_name.GetCString() + 2); 511 alternates.push_back(ConstString(fixed_scratch)); 512 } 513 514 TypeSubstitutor TS; 515 // `char` is implementation defined as either `signed` or `unsigned`. As a 516 // result a char parameter has 3 possible manglings: 'c'-char, 'a'-signed 517 // char, 'h'-unsigned char. If we're looking for symbols with a signed char 518 // parameter, try finding matches which have the general case 'c'. 519 if (ConstString char_fixup = 520 TS.substitute(mangled_name.GetStringRef(), "a", "c")) 521 alternates.push_back(char_fixup); 522 523 // long long parameter mangling 'x', may actually just be a long 'l' argument 524 if (ConstString long_fixup = 525 TS.substitute(mangled_name.GetStringRef(), "x", "l")) 526 alternates.push_back(long_fixup); 527 528 // unsigned long long parameter mangling 'y', may actually just be unsigned 529 // long 'm' argument 530 if (ConstString ulong_fixup = 531 TS.substitute(mangled_name.GetStringRef(), "y", "m")) 532 alternates.push_back(ulong_fixup); 533 534 if (ConstString ctor_fixup = 535 CtorDtorSubstitutor().substitute(mangled_name.GetStringRef())) 536 alternates.push_back(ctor_fixup); 537 538 return alternates; 539 } 540 541 ConstString CPlusPlusLanguage::FindBestAlternateFunctionMangledName( 542 const Mangled mangled, const SymbolContext &sym_ctx) const { 543 ConstString demangled = mangled.GetDemangledName(); 544 if (!demangled) 545 return ConstString(); 546 547 CPlusPlusLanguage::MethodName cpp_name(demangled); 548 std::string scope_qualified_name = cpp_name.GetScopeQualifiedName(); 549 550 if (!scope_qualified_name.size()) 551 return ConstString(); 552 553 if (!sym_ctx.module_sp) 554 return ConstString(); 555 556 lldb_private::SymbolFile *sym_file = sym_ctx.module_sp->GetSymbolFile(); 557 if (!sym_file) 558 return ConstString(); 559 560 std::vector<ConstString> alternates; 561 sym_file->GetMangledNamesForFunction(scope_qualified_name, alternates); 562 563 std::vector<ConstString> param_and_qual_matches; 564 std::vector<ConstString> param_matches; 565 for (size_t i = 0; i < alternates.size(); i++) { 566 ConstString alternate_mangled_name = alternates[i]; 567 Mangled mangled(alternate_mangled_name); 568 ConstString demangled = mangled.GetDemangledName(); 569 570 CPlusPlusLanguage::MethodName alternate_cpp_name(demangled); 571 if (!cpp_name.IsValid()) 572 continue; 573 574 if (alternate_cpp_name.GetArguments() == cpp_name.GetArguments()) { 575 if (alternate_cpp_name.GetQualifiers() == cpp_name.GetQualifiers()) 576 param_and_qual_matches.push_back(alternate_mangled_name); 577 else 578 param_matches.push_back(alternate_mangled_name); 579 } 580 } 581 582 if (param_and_qual_matches.size()) 583 return param_and_qual_matches[0]; // It is assumed that there will be only 584 // one! 585 else if (param_matches.size()) 586 return param_matches[0]; // Return one of them as a best match 587 else 588 return ConstString(); 589 } 590 591 static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { 592 if (!cpp_category_sp) 593 return; 594 595 TypeSummaryImpl::Flags stl_summary_flags; 596 stl_summary_flags.SetCascades(true) 597 .SetSkipPointers(false) 598 .SetSkipReferences(false) 599 .SetDontShowChildren(true) 600 .SetDontShowValue(true) 601 .SetShowMembersOneLiner(false) 602 .SetHideItemNames(false); 603 604 AddCXXSummary(cpp_category_sp, 605 lldb_private::formatters::LibcxxStringSummaryProviderASCII, 606 "std::string summary provider", 607 ConstString("^std::__[[:alnum:]]+::string$"), stl_summary_flags, 608 true); 609 AddCXXSummary(cpp_category_sp, 610 lldb_private::formatters::LibcxxStringSummaryProviderASCII, 611 "std::string summary provider", 612 ConstString("^std::__[[:alnum:]]+::basic_string<char, " 613 "std::__[[:alnum:]]+::char_traits<char>, " 614 "std::__[[:alnum:]]+::allocator<char> >$"), 615 stl_summary_flags, true); 616 AddCXXSummary(cpp_category_sp, 617 lldb_private::formatters::LibcxxStringSummaryProviderASCII, 618 "std::string summary provider", 619 ConstString("^std::__[[:alnum:]]+::basic_string<unsigned char, " 620 "std::__[[:alnum:]]+::char_traits<unsigned char>, " 621 "std::__[[:alnum:]]+::allocator<unsigned char> >$"), 622 stl_summary_flags, true); 623 624 AddCXXSummary(cpp_category_sp, 625 lldb_private::formatters::LibcxxStringSummaryProviderUTF16, 626 "std::u16string summary provider", 627 ConstString("^std::__[[:alnum:]]+::basic_string<char16_t, " 628 "std::__[[:alnum:]]+::char_traits<char16_t>, " 629 "std::__[[:alnum:]]+::allocator<char16_t> >$"), 630 stl_summary_flags, true); 631 632 AddCXXSummary(cpp_category_sp, 633 lldb_private::formatters::LibcxxStringSummaryProviderUTF32, 634 "std::u32string summary provider", 635 ConstString("^std::__[[:alnum:]]+::basic_string<char32_t, " 636 "std::__[[:alnum:]]+::char_traits<char32_t>, " 637 "std::__[[:alnum:]]+::allocator<char32_t> >$"), 638 stl_summary_flags, true); 639 640 AddCXXSummary( 641 cpp_category_sp, lldb_private::formatters::LibcxxWStringSummaryProvider, 642 "std::wstring summary provider", 643 ConstString("^std::__[[:alnum:]]+::wstring$"), stl_summary_flags, true); 644 AddCXXSummary(cpp_category_sp, 645 lldb_private::formatters::LibcxxWStringSummaryProvider, 646 "std::wstring summary provider", 647 ConstString("^std::__[[:alnum:]]+::basic_string<wchar_t, " 648 "std::__[[:alnum:]]+::char_traits<wchar_t>, " 649 "std::__[[:alnum:]]+::allocator<wchar_t> >$"), 650 stl_summary_flags, true); 651 652 AddCXXSummary(cpp_category_sp, 653 lldb_private::formatters::LibcxxStringViewSummaryProviderASCII, 654 "std::string_view summary provider", 655 ConstString("^std::__[[:alnum:]]+::string_view$"), 656 stl_summary_flags, true); 657 AddCXXSummary(cpp_category_sp, 658 lldb_private::formatters::LibcxxStringViewSummaryProviderASCII, 659 "std::string_view summary provider", 660 ConstString("^std::__[[:alnum:]]+::basic_string_view<char, " 661 "std::__[[:alnum:]]+::char_traits<char> >$"), 662 stl_summary_flags, true); 663 AddCXXSummary( 664 cpp_category_sp, 665 lldb_private::formatters::LibcxxStringViewSummaryProviderASCII, 666 "std::string_view summary provider", 667 ConstString("^std::__[[:alnum:]]+::basic_string_view<unsigned char, " 668 "std::__[[:alnum:]]+::char_traits<unsigned char> >$"), 669 stl_summary_flags, true); 670 671 AddCXXSummary(cpp_category_sp, 672 lldb_private::formatters::LibcxxStringViewSummaryProviderUTF16, 673 "std::u16string_view summary provider", 674 ConstString("^std::__[[:alnum:]]+::basic_string_view<char16_t, " 675 "std::__[[:alnum:]]+::char_traits<char16_t> >$"), 676 stl_summary_flags, true); 677 678 AddCXXSummary(cpp_category_sp, 679 lldb_private::formatters::LibcxxStringViewSummaryProviderUTF32, 680 "std::u32string_view summary provider", 681 ConstString("^std::__[[:alnum:]]+::basic_string_view<char32_t, " 682 "std::__[[:alnum:]]+::char_traits<char32_t> >$"), 683 stl_summary_flags, true); 684 685 AddCXXSummary(cpp_category_sp, 686 lldb_private::formatters::LibcxxWStringViewSummaryProvider, 687 "std::wstring_view summary provider", 688 ConstString("^std::__[[:alnum:]]+::wstring_view$"), 689 stl_summary_flags, true); 690 AddCXXSummary(cpp_category_sp, 691 lldb_private::formatters::LibcxxWStringViewSummaryProvider, 692 "std::wstring_view summary provider", 693 ConstString("^std::__[[:alnum:]]+::basic_string_view<wchar_t, " 694 "std::__[[:alnum:]]+::char_traits<wchar_t> >$"), 695 stl_summary_flags, true); 696 697 SyntheticChildren::Flags stl_synth_flags; 698 stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences( 699 false); 700 SyntheticChildren::Flags stl_deref_flags = stl_synth_flags; 701 stl_deref_flags.SetFrontEndWantsDereference(); 702 703 AddCXXSynthetic( 704 cpp_category_sp, 705 lldb_private::formatters::LibcxxBitsetSyntheticFrontEndCreator, 706 "libc++ std::bitset synthetic children", 707 ConstString("^std::__[[:alnum:]]+::bitset<.+>(( )?&)?$"), stl_deref_flags, 708 true); 709 AddCXXSynthetic( 710 cpp_category_sp, 711 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator, 712 "libc++ std::vector synthetic children", 713 ConstString("^std::__[[:alnum:]]+::vector<.+>(( )?&)?$"), stl_deref_flags, 714 true); 715 AddCXXSynthetic( 716 cpp_category_sp, 717 lldb_private::formatters::LibcxxStdForwardListSyntheticFrontEndCreator, 718 "libc++ std::forward_list synthetic children", 719 ConstString("^std::__[[:alnum:]]+::forward_list<.+>(( )?&)?$"), 720 stl_synth_flags, true); 721 AddCXXSynthetic( 722 cpp_category_sp, 723 lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, 724 "libc++ std::list synthetic children", 725 // A POSIX variant of: "^std::__(?!cxx11:)[[:alnum:]]+::list<.+>(( )?&)?$" 726 // so that it does not clash with: "^std::(__cxx11::)?list<.+>(( )?&)?$" 727 ConstString("^std::__([A-Zabd-z0-9]|cx?[A-Za-wyz0-9]|cxx1?[A-Za-z02-9]|" 728 "cxx11[[:alnum:]])[[:alnum:]]*::list<.+>(( )?&)?$"), 729 stl_deref_flags, true); 730 AddCXXSynthetic( 731 cpp_category_sp, 732 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, 733 "libc++ std::map synthetic children", 734 ConstString("^std::__[[:alnum:]]+::map<.+> >(( )?&)?$"), stl_synth_flags, 735 true); 736 AddCXXSynthetic( 737 cpp_category_sp, 738 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, 739 "libc++ std::set synthetic children", 740 ConstString("^std::__[[:alnum:]]+::set<.+> >(( )?&)?$"), stl_deref_flags, 741 true); 742 AddCXXSynthetic( 743 cpp_category_sp, 744 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, 745 "libc++ std::multiset synthetic children", 746 ConstString("^std::__[[:alnum:]]+::multiset<.+> >(( )?&)?$"), 747 stl_deref_flags, true); 748 AddCXXSynthetic( 749 cpp_category_sp, 750 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, 751 "libc++ std::multimap synthetic children", 752 ConstString("^std::__[[:alnum:]]+::multimap<.+> >(( )?&)?$"), 753 stl_synth_flags, true); 754 AddCXXSynthetic( 755 cpp_category_sp, 756 lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator, 757 "libc++ std::unordered containers synthetic children", 758 ConstString("^(std::__[[:alnum:]]+::)unordered_(multi)?(map|set)<.+> >$"), 759 stl_synth_flags, true); 760 AddCXXSynthetic( 761 cpp_category_sp, 762 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator, 763 "libc++ std::initializer_list synthetic children", 764 ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags, 765 true); 766 AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator, 767 "libc++ std::queue synthetic children", 768 ConstString("^std::__[[:alnum:]]+::queue<.+>(( )?&)?$"), 769 stl_synth_flags, true); 770 AddCXXSynthetic(cpp_category_sp, LibcxxTupleFrontEndCreator, 771 "libc++ std::tuple synthetic children", 772 ConstString("^std::__[[:alnum:]]+::tuple<.*>(( )?&)?$"), 773 stl_synth_flags, true); 774 AddCXXSynthetic(cpp_category_sp, LibcxxOptionalSyntheticFrontEndCreator, 775 "libc++ std::optional synthetic children", 776 ConstString("^std::__[[:alnum:]]+::optional<.+>(( )?&)?$"), 777 stl_synth_flags, true); 778 AddCXXSynthetic(cpp_category_sp, LibcxxVariantFrontEndCreator, 779 "libc++ std::variant synthetic children", 780 ConstString("^std::__[[:alnum:]]+::variant<.+>(( )?&)?$"), 781 stl_synth_flags, true); 782 AddCXXSynthetic( 783 cpp_category_sp, 784 lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator, 785 "libc++ std::atomic synthetic children", 786 ConstString("^std::__[[:alnum:]]+::atomic<.+>$"), stl_synth_flags, true); 787 AddCXXSynthetic( 788 cpp_category_sp, 789 lldb_private::formatters::LibcxxStdSpanSyntheticFrontEndCreator, 790 "libc++ std::span synthetic children", 791 ConstString("^std::__[[:alnum:]]+::span<.+>(( )?&)?$"), stl_deref_flags, 792 true); 793 794 cpp_category_sp->AddTypeSynthetic( 795 "^(std::__[[:alnum:]]+::)deque<.+>(( )?&)?$", eFormatterMatchRegex, 796 SyntheticChildrenSP(new ScriptedSyntheticChildren( 797 stl_synth_flags, 798 "lldb.formatters.cpp.libcxx.stddeque_SynthProvider"))); 799 800 AddCXXSynthetic( 801 cpp_category_sp, 802 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, 803 "shared_ptr synthetic children", 804 ConstString("^(std::__[[:alnum:]]+::)shared_ptr<.+>(( )?&)?$"), 805 stl_synth_flags, true); 806 807 ConstString libcxx_std_unique_ptr_regex( 808 "^std::__[[:alnum:]]+::unique_ptr<.+>(( )?&)?$"); 809 AddCXXSynthetic( 810 cpp_category_sp, 811 lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEndCreator, 812 "unique_ptr synthetic children", libcxx_std_unique_ptr_regex, 813 stl_synth_flags, true); 814 815 AddCXXSynthetic( 816 cpp_category_sp, 817 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, 818 "weak_ptr synthetic children", 819 ConstString("^(std::__[[:alnum:]]+::)weak_ptr<.+>(( )?&)?$"), 820 stl_synth_flags, true); 821 AddCXXSummary(cpp_category_sp, 822 lldb_private::formatters::LibcxxFunctionSummaryProvider, 823 "libc++ std::function summary provider", 824 ConstString("^std::__[[:alnum:]]+::function<.+>$"), 825 stl_summary_flags, true); 826 827 ConstString libcxx_std_coroutine_handle_regex( 828 "^std::__[[:alnum:]]+::coroutine_handle<.+>(( )?&)?$"); 829 AddCXXSynthetic( 830 cpp_category_sp, 831 lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEndCreator, 832 "coroutine_handle synthetic children", libcxx_std_coroutine_handle_regex, 833 stl_deref_flags, true); 834 835 stl_summary_flags.SetDontShowChildren(false); 836 stl_summary_flags.SetSkipPointers(false); 837 AddCXXSummary(cpp_category_sp, 838 lldb_private::formatters::LibcxxContainerSummaryProvider, 839 "libc++ std::bitset summary provider", 840 ConstString("^std::__[[:alnum:]]+::bitset<.+>(( )?&)?$"), 841 stl_summary_flags, true); 842 AddCXXSummary(cpp_category_sp, 843 lldb_private::formatters::LibcxxContainerSummaryProvider, 844 "libc++ std::vector summary provider", 845 ConstString("^std::__[[:alnum:]]+::vector<.+>(( )?&)?$"), 846 stl_summary_flags, true); 847 AddCXXSummary(cpp_category_sp, 848 lldb_private::formatters::LibcxxContainerSummaryProvider, 849 "libc++ std::list summary provider", 850 ConstString("^std::__[[:alnum:]]+::forward_list<.+>(( )?&)?$"), 851 stl_summary_flags, true); 852 AddCXXSummary( 853 cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, 854 "libc++ std::list summary provider", 855 // A POSIX variant of: "^std::__(?!cxx11:)[[:alnum:]]+::list<.+>(( )?&)?$" 856 // so that it does not clash with: "^std::(__cxx11::)?list<.+>(( )?&)?$" 857 ConstString("^std::__([A-Zabd-z0-9]|cx?[A-Za-wyz0-9]|cxx1?[A-Za-z02-9]|" 858 "cxx11[[:alnum:]])[[:alnum:]]*::list<.+>(( )?&)?$"), 859 stl_summary_flags, true); 860 AddCXXSummary(cpp_category_sp, 861 lldb_private::formatters::LibcxxContainerSummaryProvider, 862 "libc++ std::map summary provider", 863 ConstString("^std::__[[:alnum:]]+::map<.+>(( )?&)?$"), 864 stl_summary_flags, true); 865 AddCXXSummary(cpp_category_sp, 866 lldb_private::formatters::LibcxxContainerSummaryProvider, 867 "libc++ std::deque summary provider", 868 ConstString("^std::__[[:alnum:]]+::deque<.+>(( )?&)?$"), 869 stl_summary_flags, true); 870 AddCXXSummary(cpp_category_sp, 871 lldb_private::formatters::LibcxxContainerSummaryProvider, 872 "libc++ std::queue summary provider", 873 ConstString("^std::__[[:alnum:]]+::queue<.+>(( )?&)?$"), 874 stl_summary_flags, true); 875 AddCXXSummary(cpp_category_sp, 876 lldb_private::formatters::LibcxxContainerSummaryProvider, 877 "libc++ std::set summary provider", 878 ConstString("^std::__[[:alnum:]]+::set<.+>(( )?&)?$"), 879 stl_summary_flags, true); 880 AddCXXSummary(cpp_category_sp, 881 lldb_private::formatters::LibcxxContainerSummaryProvider, 882 "libc++ std::multiset summary provider", 883 ConstString("^std::__[[:alnum:]]+::multiset<.+>(( )?&)?$"), 884 stl_summary_flags, true); 885 AddCXXSummary(cpp_category_sp, 886 lldb_private::formatters::LibcxxContainerSummaryProvider, 887 "libc++ std::multimap summary provider", 888 ConstString("^std::__[[:alnum:]]+::multimap<.+>(( )?&)?$"), 889 stl_summary_flags, true); 890 AddCXXSummary( 891 cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, 892 "libc++ std::unordered containers summary provider", 893 ConstString("^(std::__[[:alnum:]]+::)unordered_(multi)?(map|set)<.+> >$"), 894 stl_summary_flags, true); 895 AddCXXSummary(cpp_category_sp, LibcxxContainerSummaryProvider, 896 "libc++ std::tuple summary provider", 897 ConstString("^std::__[[:alnum:]]+::tuple<.*>(( )?&)?$"), 898 stl_summary_flags, true); 899 AddCXXSummary(cpp_category_sp, 900 lldb_private::formatters::LibCxxAtomicSummaryProvider, 901 "libc++ std::atomic summary provider", 902 ConstString("^std::__[[:alnum:]]+::atomic<.+>$"), 903 stl_summary_flags, true); 904 AddCXXSummary(cpp_category_sp, 905 lldb_private::formatters::GenericOptionalSummaryProvider, 906 "libc++ std::optional summary provider", 907 ConstString("^std::__[[:alnum:]]+::optional<.+>(( )?&)?$"), 908 stl_summary_flags, true); 909 AddCXXSummary(cpp_category_sp, 910 lldb_private::formatters::LibcxxVariantSummaryProvider, 911 "libc++ std::variant summary provider", 912 ConstString("^std::__[[:alnum:]]+::variant<.+>(( )?&)?$"), 913 stl_summary_flags, true); 914 AddCXXSummary(cpp_category_sp, 915 lldb_private::formatters::LibcxxContainerSummaryProvider, 916 "libc++ std::span summary provider", 917 ConstString("^std::__[[:alnum:]]+::span<.+>(( )?&)?$"), 918 stl_summary_flags, true); 919 920 stl_summary_flags.SetSkipPointers(true); 921 922 AddCXXSummary(cpp_category_sp, 923 lldb_private::formatters::LibcxxSmartPointerSummaryProvider, 924 "libc++ std::shared_ptr summary provider", 925 ConstString("^std::__[[:alnum:]]+::shared_ptr<.+>(( )?&)?$"), 926 stl_summary_flags, true); 927 AddCXXSummary(cpp_category_sp, 928 lldb_private::formatters::LibcxxSmartPointerSummaryProvider, 929 "libc++ std::weak_ptr summary provider", 930 ConstString("^std::__[[:alnum:]]+::weak_ptr<.+>(( )?&)?$"), 931 stl_summary_flags, true); 932 AddCXXSummary(cpp_category_sp, 933 lldb_private::formatters::LibcxxUniquePointerSummaryProvider, 934 "libc++ std::unique_ptr summary provider", 935 libcxx_std_unique_ptr_regex, stl_summary_flags, true); 936 937 AddCXXSummary(cpp_category_sp, 938 lldb_private::formatters::StdlibCoroutineHandleSummaryProvider, 939 "libc++ std::coroutine_handle summary provider", 940 libcxx_std_coroutine_handle_regex, stl_summary_flags, true); 941 942 AddCXXSynthetic( 943 cpp_category_sp, 944 lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator, 945 "std::vector iterator synthetic children", 946 ConstString("^std::__[[:alnum:]]+::__wrap_iter<.+>$"), stl_synth_flags, 947 true); 948 949 AddCXXSynthetic( 950 cpp_category_sp, 951 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator, 952 "std::map iterator synthetic children", 953 ConstString("^std::__[[:alnum:]]+::__map_(const_)?iterator<.+>$"), stl_synth_flags, 954 true); 955 956 AddCXXSynthetic( 957 cpp_category_sp, 958 lldb_private::formatters:: 959 LibCxxUnorderedMapIteratorSyntheticFrontEndCreator, 960 "std::unordered_map iterator synthetic children", 961 ConstString("^std::__[[:alnum:]]+::__hash_map_(const_)?iterator<.+>$"), 962 stl_synth_flags, true); 963 } 964 965 static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { 966 if (!cpp_category_sp) 967 return; 968 969 TypeSummaryImpl::Flags stl_summary_flags; 970 stl_summary_flags.SetCascades(true) 971 .SetSkipPointers(false) 972 .SetSkipReferences(false) 973 .SetDontShowChildren(true) 974 .SetDontShowValue(true) 975 .SetShowMembersOneLiner(false) 976 .SetHideItemNames(false); 977 978 lldb::TypeSummaryImplSP std_string_summary_sp( 979 new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p}")); 980 981 lldb::TypeSummaryImplSP cxx11_string_summary_sp(new CXXFunctionSummaryFormat( 982 stl_summary_flags, LibStdcppStringSummaryProvider, 983 "libstdc++ c++11 std::string summary provider")); 984 lldb::TypeSummaryImplSP cxx11_wstring_summary_sp(new CXXFunctionSummaryFormat( 985 stl_summary_flags, LibStdcppWStringSummaryProvider, 986 "libstdc++ c++11 std::wstring summary provider")); 987 988 cpp_category_sp->AddTypeSummary("std::string", eFormatterMatchExact, 989 std_string_summary_sp); 990 cpp_category_sp->AddTypeSummary("std::basic_string<char>", 991 eFormatterMatchRegex, std_string_summary_sp); 992 cpp_category_sp->AddTypeSummary( 993 "std::basic_string<char,std::char_traits<char>,std::allocator<char> >", 994 eFormatterMatchExact, std_string_summary_sp); 995 cpp_category_sp->AddTypeSummary( 996 "std::basic_string<char, std::char_traits<char>, std::allocator<char> >", 997 eFormatterMatchExact, std_string_summary_sp); 998 999 cpp_category_sp->AddTypeSummary("std::__cxx11::string", eFormatterMatchExact, 1000 cxx11_string_summary_sp); 1001 cpp_category_sp->AddTypeSummary( 1002 "std::__cxx11::basic_string<char, std::char_traits<char>, " 1003 "std::allocator<char> >", 1004 eFormatterMatchExact, cxx11_string_summary_sp); 1005 cpp_category_sp->AddTypeSummary("std::__cxx11::basic_string<unsigned char, " 1006 "std::char_traits<unsigned char>, " 1007 "std::allocator<unsigned char> >", 1008 eFormatterMatchExact, 1009 cxx11_string_summary_sp); 1010 1011 // making sure we force-pick the summary for printing wstring (_M_p is a 1012 // wchar_t*) 1013 lldb::TypeSummaryImplSP std_wstring_summary_sp( 1014 new StringSummaryFormat(stl_summary_flags, "${var._M_dataplus._M_p%S}")); 1015 1016 cpp_category_sp->AddTypeSummary("std::wstring", eFormatterMatchExact, 1017 std_wstring_summary_sp); 1018 cpp_category_sp->AddTypeSummary("std::basic_string<wchar_t>", 1019 eFormatterMatchExact, std_wstring_summary_sp); 1020 cpp_category_sp->AddTypeSummary("std::basic_string<wchar_t,std::char_traits<" 1021 "wchar_t>,std::allocator<wchar_t> >", 1022 eFormatterMatchExact, std_wstring_summary_sp); 1023 cpp_category_sp->AddTypeSummary( 1024 "std::basic_string<wchar_t, std::char_traits<wchar_t>, " 1025 "std::allocator<wchar_t> >", 1026 eFormatterMatchExact, std_wstring_summary_sp); 1027 1028 cpp_category_sp->AddTypeSummary("std::__cxx11::wstring", eFormatterMatchExact, 1029 cxx11_wstring_summary_sp); 1030 cpp_category_sp->AddTypeSummary( 1031 "std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, " 1032 "std::allocator<wchar_t> >", 1033 eFormatterMatchExact, cxx11_wstring_summary_sp); 1034 1035 SyntheticChildren::Flags stl_synth_flags; 1036 stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences( 1037 false); 1038 SyntheticChildren::Flags stl_deref_flags = stl_synth_flags; 1039 stl_deref_flags.SetFrontEndWantsDereference(); 1040 1041 cpp_category_sp->AddTypeSynthetic( 1042 "^std::vector<.+>(( )?&)?$", eFormatterMatchRegex, 1043 SyntheticChildrenSP(new ScriptedSyntheticChildren( 1044 stl_synth_flags, 1045 "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider"))); 1046 cpp_category_sp->AddTypeSynthetic( 1047 "^std::map<.+> >(( )?&)?$", eFormatterMatchRegex, 1048 SyntheticChildrenSP(new ScriptedSyntheticChildren( 1049 stl_synth_flags, 1050 "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider"))); 1051 cpp_category_sp->AddTypeSynthetic( 1052 "^std::deque<.+>(( )?&)?$", eFormatterMatchRegex, 1053 SyntheticChildrenSP(new ScriptedSyntheticChildren( 1054 stl_deref_flags, 1055 "lldb.formatters.cpp.gnu_libstdcpp.StdDequeSynthProvider"))); 1056 cpp_category_sp->AddTypeSynthetic( 1057 "^std::set<.+> >(( )?&)?$", eFormatterMatchRegex, 1058 SyntheticChildrenSP(new ScriptedSyntheticChildren( 1059 stl_deref_flags, 1060 "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider"))); 1061 cpp_category_sp->AddTypeSynthetic( 1062 "^std::multimap<.+> >(( )?&)?$", eFormatterMatchRegex, 1063 SyntheticChildrenSP(new ScriptedSyntheticChildren( 1064 stl_deref_flags, 1065 "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider"))); 1066 cpp_category_sp->AddTypeSynthetic( 1067 "^std::multiset<.+> >(( )?&)?$", eFormatterMatchRegex, 1068 SyntheticChildrenSP(new ScriptedSyntheticChildren( 1069 stl_deref_flags, 1070 "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider"))); 1071 cpp_category_sp->AddTypeSynthetic( 1072 "^std::unordered_(multi)?(map|set)<.+> >$", eFormatterMatchRegex, 1073 SyntheticChildrenSP(new ScriptedSyntheticChildren( 1074 stl_deref_flags, 1075 "lldb.formatters.cpp.gnu_libstdcpp.StdUnorderedMapSynthProvider"))); 1076 cpp_category_sp->AddTypeSynthetic( 1077 "^std::(__cxx11::)?list<.+>(( )?&)?$", eFormatterMatchRegex, 1078 SyntheticChildrenSP(new ScriptedSyntheticChildren( 1079 stl_deref_flags, 1080 "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider"))); 1081 cpp_category_sp->AddTypeSynthetic( 1082 "^std::(__cxx11::)?forward_list<.+>(( )?&)?$", eFormatterMatchRegex, 1083 SyntheticChildrenSP(new ScriptedSyntheticChildren( 1084 stl_synth_flags, 1085 "lldb.formatters.cpp.gnu_libstdcpp.StdForwardListSynthProvider"))); 1086 1087 stl_summary_flags.SetDontShowChildren(false); 1088 stl_summary_flags.SetSkipPointers(false); 1089 cpp_category_sp->AddTypeSummary("^std::bitset<.+>(( )?&)?$", 1090 eFormatterMatchRegex, 1091 TypeSummaryImplSP(new StringSummaryFormat( 1092 stl_summary_flags, "size=${svar%#}"))); 1093 cpp_category_sp->AddTypeSummary("^std::vector<.+>(( )?&)?$", 1094 eFormatterMatchRegex, 1095 TypeSummaryImplSP(new StringSummaryFormat( 1096 stl_summary_flags, "size=${svar%#}"))); 1097 cpp_category_sp->AddTypeSummary("^std::map<.+> >(( )?&)?$", 1098 eFormatterMatchRegex, 1099 TypeSummaryImplSP(new StringSummaryFormat( 1100 stl_summary_flags, "size=${svar%#}"))); 1101 cpp_category_sp->AddTypeSummary("^std::set<.+> >(( )?&)?$", 1102 eFormatterMatchRegex, 1103 TypeSummaryImplSP(new StringSummaryFormat( 1104 stl_summary_flags, "size=${svar%#}"))); 1105 cpp_category_sp->AddTypeSummary("^std::deque<.+>(( )?&)?$", 1106 eFormatterMatchRegex, 1107 TypeSummaryImplSP(new StringSummaryFormat( 1108 stl_summary_flags, "size=${svar%#}"))); 1109 cpp_category_sp->AddTypeSummary("^std::multimap<.+> >(( )?&)?$", 1110 eFormatterMatchRegex, 1111 TypeSummaryImplSP(new StringSummaryFormat( 1112 stl_summary_flags, "size=${svar%#}"))); 1113 cpp_category_sp->AddTypeSummary("^std::multiset<.+> >(( )?&)?$", 1114 eFormatterMatchRegex, 1115 TypeSummaryImplSP(new StringSummaryFormat( 1116 stl_summary_flags, "size=${svar%#}"))); 1117 cpp_category_sp->AddTypeSummary("^std::unordered_(multi)?(map|set)<.+> >$", 1118 eFormatterMatchRegex, 1119 TypeSummaryImplSP(new StringSummaryFormat( 1120 stl_summary_flags, "size=${svar%#}"))); 1121 cpp_category_sp->AddTypeSummary("^std::(__cxx11::)?list<.+>(( )?&)?$", 1122 eFormatterMatchRegex, 1123 TypeSummaryImplSP(new StringSummaryFormat( 1124 stl_summary_flags, "size=${svar%#}"))); 1125 cpp_category_sp->AddTypeSummary( 1126 "^std::(__cxx11::)?forward_list<.+>(( )?&)?$", eFormatterMatchRegex, 1127 TypeSummaryImplSP(new ScriptSummaryFormat( 1128 stl_summary_flags, 1129 "lldb.formatters.cpp.gnu_libstdcpp.ForwardListSummaryProvider"))); 1130 1131 AddCXXSynthetic( 1132 cpp_category_sp, 1133 lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator, 1134 "std::vector iterator synthetic children", 1135 ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true); 1136 1137 AddCXXSynthetic( 1138 cpp_category_sp, 1139 lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator, 1140 "std::map iterator synthetic children", 1141 ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true); 1142 1143 AddCXXSynthetic( 1144 cpp_category_sp, 1145 lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator, 1146 "std::unique_ptr synthetic children", 1147 ConstString("^std::unique_ptr<.+>(( )?&)?$"), stl_synth_flags, true); 1148 AddCXXSynthetic( 1149 cpp_category_sp, 1150 lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator, 1151 "std::shared_ptr synthetic children", 1152 ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_synth_flags, true); 1153 AddCXXSynthetic( 1154 cpp_category_sp, 1155 lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator, 1156 "std::weak_ptr synthetic children", 1157 ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true); 1158 AddCXXSynthetic( 1159 cpp_category_sp, 1160 lldb_private::formatters::LibStdcppTupleSyntheticFrontEndCreator, 1161 "std::tuple synthetic children", ConstString("^std::tuple<.+>(( )?&)?$"), 1162 stl_synth_flags, true); 1163 1164 ConstString libstdcpp_std_coroutine_handle_regex( 1165 "^std::coroutine_handle<.+>(( )?&)?$"); 1166 AddCXXSynthetic( 1167 cpp_category_sp, 1168 lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEndCreator, 1169 "std::coroutine_handle synthetic children", 1170 libstdcpp_std_coroutine_handle_regex, stl_deref_flags, true); 1171 1172 AddCXXSynthetic( 1173 cpp_category_sp, 1174 lldb_private::formatters::LibStdcppBitsetSyntheticFrontEndCreator, 1175 "std::bitset synthetic child", ConstString("^std::bitset<.+>(( )?&)?$"), 1176 stl_deref_flags, true); 1177 1178 AddCXXSynthetic( 1179 cpp_category_sp, 1180 lldb_private::formatters::LibStdcppOptionalSyntheticFrontEndCreator, 1181 "std::optional synthetic child", 1182 ConstString("^std::optional<.+>(( )?&)?$"), stl_deref_flags, true); 1183 1184 AddCXXSummary(cpp_category_sp, 1185 lldb_private::formatters::LibStdcppUniquePointerSummaryProvider, 1186 "libstdc++ std::unique_ptr summary provider", 1187 ConstString("^std::unique_ptr<.+>(( )?&)?$"), stl_summary_flags, 1188 true); 1189 AddCXXSummary(cpp_category_sp, 1190 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider, 1191 "libstdc++ std::shared_ptr summary provider", 1192 ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_summary_flags, 1193 true); 1194 AddCXXSummary(cpp_category_sp, 1195 lldb_private::formatters::LibStdcppSmartPointerSummaryProvider, 1196 "libstdc++ std::weak_ptr summary provider", 1197 ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_summary_flags, 1198 true); 1199 AddCXXSummary(cpp_category_sp, 1200 lldb_private::formatters::StdlibCoroutineHandleSummaryProvider, 1201 "libstdc++ std::coroutine_handle summary provider", 1202 libstdcpp_std_coroutine_handle_regex, stl_summary_flags, true); 1203 AddCXXSummary( 1204 cpp_category_sp, lldb_private::formatters::GenericOptionalSummaryProvider, 1205 "libstd++ std::optional summary provider", 1206 ConstString("^std::optional<.+>(( )?&)?$"), stl_summary_flags, true); 1207 } 1208 1209 static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { 1210 if (!cpp_category_sp) 1211 return; 1212 1213 TypeSummaryImpl::Flags string_flags; 1214 string_flags.SetCascades(true) 1215 .SetSkipPointers(true) 1216 .SetSkipReferences(false) 1217 .SetDontShowChildren(true) 1218 .SetDontShowValue(false) 1219 .SetShowMembersOneLiner(false) 1220 .SetHideItemNames(false); 1221 1222 TypeSummaryImpl::Flags string_array_flags; 1223 string_array_flags.SetCascades(true) 1224 .SetSkipPointers(true) 1225 .SetSkipReferences(false) 1226 .SetDontShowChildren(true) 1227 .SetDontShowValue(true) 1228 .SetShowMembersOneLiner(false) 1229 .SetHideItemNames(false); 1230 1231 AddCXXSummary( 1232 cpp_category_sp, lldb_private::formatters::Char8StringSummaryProvider, 1233 "char8_t * summary provider", ConstString("char8_t *"), string_flags); 1234 AddCXXSummary(cpp_category_sp, 1235 lldb_private::formatters::Char8StringSummaryProvider, 1236 "char8_t [] summary provider", 1237 ConstString("char8_t ?\\[[0-9]+\\]"), string_array_flags, true); 1238 1239 AddCXXSummary( 1240 cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, 1241 "char16_t * summary provider", ConstString("char16_t *"), string_flags); 1242 AddCXXSummary(cpp_category_sp, 1243 lldb_private::formatters::Char16StringSummaryProvider, 1244 "char16_t [] summary provider", 1245 ConstString("char16_t ?\\[[0-9]+\\]"), string_array_flags, true); 1246 1247 AddCXXSummary( 1248 cpp_category_sp, lldb_private::formatters::Char32StringSummaryProvider, 1249 "char32_t * summary provider", ConstString("char32_t *"), string_flags); 1250 AddCXXSummary(cpp_category_sp, 1251 lldb_private::formatters::Char32StringSummaryProvider, 1252 "char32_t [] summary provider", 1253 ConstString("char32_t ?\\[[0-9]+\\]"), string_array_flags, true); 1254 1255 AddCXXSummary( 1256 cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider, 1257 "wchar_t * summary provider", ConstString("wchar_t *"), string_flags); 1258 AddCXXSummary(cpp_category_sp, 1259 lldb_private::formatters::WCharStringSummaryProvider, 1260 "wchar_t * summary provider", 1261 ConstString("wchar_t ?\\[[0-9]+\\]"), string_array_flags, true); 1262 1263 AddCXXSummary( 1264 cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, 1265 "unichar * summary provider", ConstString("unichar *"), string_flags); 1266 1267 TypeSummaryImpl::Flags widechar_flags; 1268 widechar_flags.SetDontShowValue(true) 1269 .SetSkipPointers(true) 1270 .SetSkipReferences(false) 1271 .SetCascades(true) 1272 .SetDontShowChildren(true) 1273 .SetHideItemNames(true) 1274 .SetShowMembersOneLiner(false); 1275 1276 AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char8SummaryProvider, 1277 "char8_t summary provider", ConstString("char8_t"), 1278 widechar_flags); 1279 AddCXXSummary( 1280 cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, 1281 "char16_t summary provider", ConstString("char16_t"), widechar_flags); 1282 AddCXXSummary( 1283 cpp_category_sp, lldb_private::formatters::Char32SummaryProvider, 1284 "char32_t summary provider", ConstString("char32_t"), widechar_flags); 1285 AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharSummaryProvider, 1286 "wchar_t summary provider", ConstString("wchar_t"), 1287 widechar_flags); 1288 1289 AddCXXSummary( 1290 cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, 1291 "unichar summary provider", ConstString("unichar"), widechar_flags); 1292 } 1293 1294 std::unique_ptr<Language::TypeScavenger> CPlusPlusLanguage::GetTypeScavenger() { 1295 class CPlusPlusTypeScavenger : public Language::ImageListTypeScavenger { 1296 public: 1297 CompilerType AdjustForInclusion(CompilerType &candidate) override { 1298 LanguageType lang_type(candidate.GetMinimumLanguage()); 1299 if (!Language::LanguageIsC(lang_type) && 1300 !Language::LanguageIsCPlusPlus(lang_type)) 1301 return CompilerType(); 1302 if (candidate.IsTypedefType()) 1303 return candidate.GetTypedefedType(); 1304 return candidate; 1305 } 1306 }; 1307 1308 return std::unique_ptr<TypeScavenger>(new CPlusPlusTypeScavenger()); 1309 } 1310 1311 lldb::TypeCategoryImplSP CPlusPlusLanguage::GetFormatters() { 1312 static llvm::once_flag g_initialize; 1313 static TypeCategoryImplSP g_category; 1314 1315 llvm::call_once(g_initialize, [this]() -> void { 1316 DataVisualization::Categories::GetCategory(ConstString(GetPluginName()), 1317 g_category); 1318 if (g_category) { 1319 LoadLibStdcppFormatters(g_category); 1320 LoadLibCxxFormatters(g_category); 1321 LoadSystemFormatters(g_category); 1322 } 1323 }); 1324 return g_category; 1325 } 1326 1327 HardcodedFormatters::HardcodedSummaryFinder 1328 CPlusPlusLanguage::GetHardcodedSummaries() { 1329 static llvm::once_flag g_initialize; 1330 static ConstString g_vectortypes("VectorTypes"); 1331 static HardcodedFormatters::HardcodedSummaryFinder g_formatters; 1332 1333 llvm::call_once(g_initialize, []() -> void { 1334 g_formatters.push_back( 1335 [](lldb_private::ValueObject &valobj, lldb::DynamicValueType, 1336 FormatManager &) -> TypeSummaryImpl::SharedPointer { 1337 static CXXFunctionSummaryFormat::SharedPointer formatter_sp( 1338 new CXXFunctionSummaryFormat( 1339 TypeSummaryImpl::Flags(), 1340 lldb_private::formatters::CXXFunctionPointerSummaryProvider, 1341 "Function pointer summary provider")); 1342 if (valobj.GetCompilerType().IsFunctionPointerType()) { 1343 return formatter_sp; 1344 } 1345 return nullptr; 1346 }); 1347 g_formatters.push_back( 1348 [](lldb_private::ValueObject &valobj, lldb::DynamicValueType, 1349 FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer { 1350 static CXXFunctionSummaryFormat::SharedPointer formatter_sp( 1351 new CXXFunctionSummaryFormat( 1352 TypeSummaryImpl::Flags() 1353 .SetCascades(true) 1354 .SetDontShowChildren(true) 1355 .SetHideItemNames(true) 1356 .SetShowMembersOneLiner(true) 1357 .SetSkipPointers(true) 1358 .SetSkipReferences(false), 1359 lldb_private::formatters::VectorTypeSummaryProvider, 1360 "vector_type pointer summary provider")); 1361 if (valobj.GetCompilerType().IsVectorType()) { 1362 if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled()) 1363 return formatter_sp; 1364 } 1365 return nullptr; 1366 }); 1367 g_formatters.push_back( 1368 [](lldb_private::ValueObject &valobj, lldb::DynamicValueType, 1369 FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer { 1370 static CXXFunctionSummaryFormat::SharedPointer formatter_sp( 1371 new CXXFunctionSummaryFormat( 1372 TypeSummaryImpl::Flags() 1373 .SetCascades(true) 1374 .SetDontShowChildren(true) 1375 .SetHideItemNames(true) 1376 .SetShowMembersOneLiner(true) 1377 .SetSkipPointers(true) 1378 .SetSkipReferences(false), 1379 lldb_private::formatters::BlockPointerSummaryProvider, 1380 "block pointer summary provider")); 1381 if (valobj.GetCompilerType().IsBlockPointerType()) { 1382 return formatter_sp; 1383 } 1384 return nullptr; 1385 }); 1386 }); 1387 1388 return g_formatters; 1389 } 1390 1391 HardcodedFormatters::HardcodedSyntheticFinder 1392 CPlusPlusLanguage::GetHardcodedSynthetics() { 1393 static llvm::once_flag g_initialize; 1394 static ConstString g_vectortypes("VectorTypes"); 1395 static HardcodedFormatters::HardcodedSyntheticFinder g_formatters; 1396 1397 llvm::call_once(g_initialize, []() -> void { 1398 g_formatters.push_back([](lldb_private::ValueObject &valobj, 1399 lldb::DynamicValueType, FormatManager &fmt_mgr) 1400 -> SyntheticChildren::SharedPointer { 1401 static CXXSyntheticChildren::SharedPointer formatter_sp( 1402 new CXXSyntheticChildren( 1403 SyntheticChildren::Flags() 1404 .SetCascades(true) 1405 .SetSkipPointers(true) 1406 .SetSkipReferences(true) 1407 .SetNonCacheable(true), 1408 "vector_type synthetic children", 1409 lldb_private::formatters::VectorTypeSyntheticFrontEndCreator)); 1410 if (valobj.GetCompilerType().IsVectorType()) { 1411 if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled()) 1412 return formatter_sp; 1413 } 1414 return nullptr; 1415 }); 1416 g_formatters.push_back([](lldb_private::ValueObject &valobj, 1417 lldb::DynamicValueType, FormatManager &fmt_mgr) 1418 -> SyntheticChildren::SharedPointer { 1419 static CXXSyntheticChildren::SharedPointer formatter_sp( 1420 new CXXSyntheticChildren( 1421 SyntheticChildren::Flags() 1422 .SetCascades(true) 1423 .SetSkipPointers(true) 1424 .SetSkipReferences(true) 1425 .SetNonCacheable(true), 1426 "block pointer synthetic children", 1427 lldb_private::formatters::BlockPointerSyntheticFrontEndCreator)); 1428 if (valobj.GetCompilerType().IsBlockPointerType()) { 1429 return formatter_sp; 1430 } 1431 return nullptr; 1432 }); 1433 }); 1434 1435 return g_formatters; 1436 } 1437 1438 bool CPlusPlusLanguage::IsNilReference(ValueObject &valobj) { 1439 if (!Language::LanguageIsCPlusPlus(valobj.GetObjectRuntimeLanguage()) || 1440 !valobj.IsPointerType()) 1441 return false; 1442 bool canReadValue = true; 1443 bool isZero = valobj.GetValueAsUnsigned(0, &canReadValue) == 0; 1444 return canReadValue && isZero; 1445 } 1446 1447 bool CPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const { 1448 const auto suffixes = {".cpp", ".cxx", ".c++", ".cc", ".c", 1449 ".h", ".hh", ".hpp", ".hxx", ".h++"}; 1450 for (auto suffix : suffixes) { 1451 if (file_path.endswith_insensitive(suffix)) 1452 return true; 1453 } 1454 1455 // Check if we're in a STL path (where the files usually have no extension 1456 // that we could check for. 1457 return file_path.contains("/usr/include/c++/"); 1458 } 1459