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