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