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