2548 lines · cpp
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-exception6//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/DemangledNameInfo.h"23#include "lldb/Core/Mangled.h"24#include "lldb/Core/Module.h"25#include "lldb/Core/PluginManager.h"26#include "lldb/Core/UniqueCStringMap.h"27#include "lldb/DataFormatters/CXXFunctionPointer.h"28#include "lldb/DataFormatters/DataVisualization.h"29#include "lldb/DataFormatters/FormattersHelpers.h"30#include "lldb/DataFormatters/VectorType.h"31#include "lldb/Interpreter/OptionValueProperties.h"32#include "lldb/Symbol/SymbolFile.h"33#include "lldb/Symbol/VariableList.h"34#include "lldb/Utility/ConstString.h"35#include "lldb/Utility/LLDBLog.h"36#include "lldb/Utility/Log.h"37#include "lldb/Utility/RegularExpression.h"38#include "lldb/ValueObject/ValueObjectVariable.h"39 40#include "BlockPointer.h"41#include "CPlusPlusNameParser.h"42#include "Coroutines.h"43#include "CxxStringTypes.h"44#include "Generic.h"45#include "LibCxx.h"46#include "LibCxxAtomic.h"47#include "LibCxxVariant.h"48#include "LibStdcpp.h"49#include "MSVCUndecoratedNameParser.h"50#include "MsvcStl.h"51#include "lldb/lldb-enumerations.h"52 53using namespace lldb;54using namespace lldb_private;55using namespace lldb_private::formatters;56 57LLDB_PLUGIN_DEFINE(CPlusPlusLanguage)58 59void CPlusPlusLanguage::Initialize() {60 PluginManager::RegisterPlugin(GetPluginNameStatic(), "C++ Language",61 CreateInstance, &DebuggerInitialize);62}63 64void CPlusPlusLanguage::Terminate() {65 PluginManager::UnregisterPlugin(CreateInstance);66}67 68std::unique_ptr<Language::MethodName>69CPlusPlusLanguage::GetMethodName(ConstString full_name) const {70 std::unique_ptr<CxxMethodName> cpp_method =71 std::make_unique<CxxMethodName>(full_name);72 cpp_method->IsValid();73 return cpp_method;74}75 76std::pair<FunctionNameType, std::optional<ConstString>>77CPlusPlusLanguage::GetFunctionNameInfo(ConstString name) const {78 if (Mangled::IsMangledName(name.GetCString()))79 return {eFunctionNameTypeFull, std::nullopt};80 81 FunctionNameType func_name_type = eFunctionNameTypeNone;82 CxxMethodName method(name);83 llvm::StringRef basename = method.GetBasename();84 if (basename.empty()) {85 llvm::StringRef context;86 func_name_type |=87 (ExtractContextAndIdentifier(name.GetStringRef(), context, basename)88 ? (eFunctionNameTypeMethod | eFunctionNameTypeBase)89 : eFunctionNameTypeFull);90 } else {91 func_name_type |= (eFunctionNameTypeMethod | eFunctionNameTypeBase);92 }93 94 if (!method.GetQualifiers().empty()) {95 // There is a 'const' or other qualifier following the end of the function96 // parens, this can't be a eFunctionNameTypeBase.97 func_name_type &= ~(eFunctionNameTypeBase);98 }99 100 if (basename.empty())101 return {func_name_type, std::nullopt};102 else103 return {func_name_type, ConstString(basename)};104}105 106bool CPlusPlusLanguage::SymbolNameFitsToLanguage(const Mangled &mangled) const {107 auto mangling_scheme =108 Mangled::GetManglingScheme(mangled.GetMangledName().GetStringRef());109 return mangling_scheme == Mangled::eManglingSchemeItanium ||110 mangling_scheme == Mangled::eManglingSchemeMSVC;111}112 113ConstString CPlusPlusLanguage::GetDemangledFunctionNameWithoutArguments(114 Mangled mangled) const {115 const char *mangled_name_cstr = mangled.GetMangledName().GetCString();116 ConstString demangled_name = mangled.GetDemangledName();117 if (demangled_name && mangled_name_cstr && mangled_name_cstr[0]) {118 if (mangled_name_cstr[0] == '_' && mangled_name_cstr[1] == 'Z' &&119 (mangled_name_cstr[2] != 'T' && // avoid virtual table, VTT structure,120 // typeinfo structure, and typeinfo121 // mangled_name122 mangled_name_cstr[2] != 'G' && // avoid guard variables123 mangled_name_cstr[2] != 'Z')) // named local entities (if we124 // eventually handle eSymbolTypeData,125 // we will want this back)126 {127 CxxMethodName cxx_method(demangled_name);128 if (!cxx_method.GetBasename().empty()) {129 std::string shortname;130 if (!cxx_method.GetContext().empty())131 shortname = cxx_method.GetContext().str() + "::";132 shortname += cxx_method.GetBasename().str();133 return ConstString(shortname);134 }135 }136 }137 if (demangled_name)138 return demangled_name;139 return mangled.GetMangledName();140}141 142// Static Functions143 144Language *CPlusPlusLanguage::CreateInstance(lldb::LanguageType language) {145 // Use plugin for C++ but not for Objective-C++ (which has its own plugin).146 if (Language::LanguageIsCPlusPlus(language) &&147 language != eLanguageTypeObjC_plus_plus)148 return new CPlusPlusLanguage();149 return nullptr;150}151 152static bool ReverseFindMatchingChars(const llvm::StringRef &s,153 const llvm::StringRef &left_right_chars,154 size_t &left_pos, size_t &right_pos,155 size_t pos = llvm::StringRef::npos) {156 assert(left_right_chars.size() == 2);157 left_pos = llvm::StringRef::npos;158 const char left_char = left_right_chars[0];159 const char right_char = left_right_chars[1];160 pos = s.find_last_of(left_right_chars, pos);161 if (pos == llvm::StringRef::npos || s[pos] == left_char)162 return false;163 right_pos = pos;164 uint32_t depth = 1;165 while (pos > 0 && depth > 0) {166 pos = s.find_last_of(left_right_chars, pos);167 if (pos == llvm::StringRef::npos)168 return false;169 if (s[pos] == left_char) {170 if (--depth == 0) {171 left_pos = pos;172 return left_pos < right_pos;173 }174 } else if (s[pos] == right_char) {175 ++depth;176 }177 }178 return false;179}180 181static bool IsTrivialBasename(const llvm::StringRef &basename) {182 // Check that the basename matches with the following regular expression183 // "^~?([A-Za-z_][A-Za-z_0-9]*)$" We are using a hand written implementation184 // because it is significantly more efficient then using the general purpose185 // regular expression library.186 size_t idx = 0;187 if (basename.starts_with('~'))188 idx = 1;189 190 if (basename.size() <= idx)191 return false; // Empty string or "~"192 193 if (!std::isalpha(static_cast<unsigned char>(basename[idx])) &&194 basename[idx] != '_')195 return false; // First character (after removing the possible '~'') isn't in196 // [A-Za-z_]197 198 // Read all characters matching [A-Za-z_0-9]199 ++idx;200 while (idx < basename.size()) {201 if (!std::isalnum(static_cast<unsigned char>(basename[idx])) &&202 basename[idx] != '_')203 break;204 ++idx;205 }206 207 // We processed all characters. It is a vaild basename.208 return idx == basename.size();209}210 211/// A context is trivial if an only if it matches this pattern.212/// "^\s*([A-Za-z_:]*)\s*$". for example function `foo::bar::func()`213/// has a trivial context but. but `foo<int>::bar::func()` doesn't.214static bool IsTrivialContext(llvm::StringRef context) {215 // remove trailing or leading whitespace.216 context = context.trim();217 218 const auto iter = context.find_if_not([](char current) {219 return std::isalnum(static_cast<unsigned char>(current)) ||220 current == '_' || current == ':';221 });222 return iter == llvm::StringRef::npos;223}224 225/// Writes out the function name in 'full_name' to 'out_stream'226/// but replaces each argument type with the variable name227/// and the corresponding pretty-printed value228static bool PrettyPrintFunctionNameWithArgs(Stream &out_stream,229 char const *full_name,230 ExecutionContextScope *exe_scope,231 VariableList const &args) {232 CPlusPlusLanguage::CxxMethodName cpp_method{ConstString(full_name)};233 234 if (!cpp_method.IsValid())235 return false;236 237 llvm::StringRef return_type = cpp_method.GetReturnType();238 if (!return_type.empty()) {239 out_stream.PutCString(return_type);240 out_stream.PutChar(' ');241 }242 243 out_stream.PutCString(cpp_method.GetScopeQualifiedName());244 out_stream.PutChar('(');245 246 FormatEntity::PrettyPrintFunctionArguments(out_stream, args, exe_scope);247 248 out_stream.PutChar(')');249 250 llvm::StringRef qualifiers = cpp_method.GetQualifiers();251 if (!qualifiers.empty()) {252 out_stream.PutChar(' ');253 out_stream.PutCString(qualifiers);254 }255 256 return true;257}258 259static llvm::Expected<std::pair<llvm::StringRef, DemangledNameInfo>>260GetAndValidateInfo(const SymbolContext &sc) {261 Mangled mangled = sc.GetPossiblyInlinedFunctionName();262 if (!mangled)263 return llvm::createStringError("Function does not have a mangled name.");264 265 auto demangled_name = mangled.GetDemangledName().GetStringRef();266 if (demangled_name.empty())267 return llvm::createStringError(268 "Function '%s' does not have a demangled name.",269 mangled.GetMangledName().AsCString(""));270 271 const std::optional<DemangledNameInfo> &info = mangled.GetDemangledInfo();272 if (!info)273 return llvm::createStringError(274 "Function '%s' does not have demangled info.", demangled_name.data());275 276 // Function without a basename is nonsense.277 if (!info->hasBasename())278 return llvm::createStringError(279 "DemangledInfo for '%s does not have basename range.",280 demangled_name.data());281 282 return std::make_pair(demangled_name, *info);283}284 285static llvm::Expected<llvm::StringRef>286GetDemangledBasename(const SymbolContext &sc) {287 auto info_or_err = GetAndValidateInfo(sc);288 if (!info_or_err)289 return info_or_err.takeError();290 291 auto [demangled_name, info] = *info_or_err;292 293 return CPlusPlusLanguage::GetDemangledBasename(demangled_name, info);294}295 296llvm::StringRef297CPlusPlusLanguage::GetDemangledBasename(llvm::StringRef demangled,298 const DemangledNameInfo &info) {299 assert(info.hasBasename());300 return demangled.slice(info.BasenameRange.first, info.BasenameRange.second);301}302 303llvm::Expected<llvm::StringRef>304CPlusPlusLanguage::GetDemangledTemplateArguments(305 llvm::StringRef demangled, const DemangledNameInfo &info) {306 if (!info.hasTemplateArguments())307 return llvm::createStringError(308 "Template arguments range for '%s' is invalid.", demangled.data());309 310 return demangled.slice(info.TemplateArgumentsRange.first,311 info.TemplateArgumentsRange.second);312}313 314static llvm::Expected<llvm::StringRef>315GetDemangledTemplateArguments(const SymbolContext &sc) {316 auto info_or_err = GetAndValidateInfo(sc);317 if (!info_or_err)318 return info_or_err.takeError();319 320 auto [demangled_name, info] = *info_or_err;321 322 return CPlusPlusLanguage::GetDemangledTemplateArguments(demangled_name, info);323}324 325llvm::Expected<llvm::StringRef>326CPlusPlusLanguage::GetDemangledReturnTypeLHS(llvm::StringRef demangled,327 const DemangledNameInfo &info) {328 if (info.ScopeRange.first >= demangled.size())329 return llvm::createStringError(330 "Scope range for '%s' LHS return type is invalid.", demangled.data());331 332 return demangled.substr(0, info.ScopeRange.first);333}334 335static llvm::Expected<llvm::StringRef>336GetDemangledReturnTypeLHS(const SymbolContext &sc) {337 auto info_or_err = GetAndValidateInfo(sc);338 if (!info_or_err)339 return info_or_err.takeError();340 341 auto [demangled_name, info] = *info_or_err;342 343 return CPlusPlusLanguage::GetDemangledReturnTypeLHS(demangled_name, info);344}345 346llvm::Expected<llvm::StringRef>347CPlusPlusLanguage::GetDemangledFunctionQualifiers(348 llvm::StringRef demangled, const DemangledNameInfo &info) {349 if (!info.hasQualifiers())350 return llvm::createStringError("Qualifiers range for '%s' is invalid.",351 demangled.data());352 353 return demangled.slice(info.QualifiersRange.first,354 info.QualifiersRange.second);355}356 357static llvm::Expected<llvm::StringRef>358GetDemangledFunctionQualifiers(const SymbolContext &sc) {359 auto info_or_err = GetAndValidateInfo(sc);360 if (!info_or_err)361 return info_or_err.takeError();362 363 auto [demangled_name, info] = *info_or_err;364 365 return CPlusPlusLanguage::GetDemangledFunctionQualifiers(demangled_name,366 info);367}368 369llvm::Expected<llvm::StringRef>370CPlusPlusLanguage::GetDemangledReturnTypeRHS(llvm::StringRef demangled,371 const DemangledNameInfo &info) {372 if (info.QualifiersRange.first < info.ArgumentsRange.second)373 return llvm::createStringError(374 "Qualifiers range for '%s' RHS return type is invalid.",375 demangled.data());376 377 return demangled.slice(info.ArgumentsRange.second,378 info.QualifiersRange.first);379}380 381static llvm::Expected<llvm::StringRef>382GetDemangledReturnTypeRHS(const SymbolContext &sc) {383 auto info_or_err = GetAndValidateInfo(sc);384 if (!info_or_err)385 return info_or_err.takeError();386 387 auto [demangled_name, info] = *info_or_err;388 389 return CPlusPlusLanguage::GetDemangledReturnTypeRHS(demangled_name, info);390}391 392llvm::Expected<llvm::StringRef>393CPlusPlusLanguage::GetDemangledScope(llvm::StringRef demangled,394 const DemangledNameInfo &info) {395 if (!info.hasScope())396 return llvm::createStringError("Scope range for '%s' is invalid.",397 demangled.data());398 399 return demangled.slice(info.ScopeRange.first, info.ScopeRange.second);400}401 402static llvm::Expected<llvm::StringRef>403GetDemangledScope(const SymbolContext &sc) {404 auto info_or_err = GetAndValidateInfo(sc);405 if (!info_or_err)406 return info_or_err.takeError();407 408 auto [demangled_name, info] = *info_or_err;409 410 return CPlusPlusLanguage::GetDemangledScope(demangled_name, info);411}412 413llvm::Expected<llvm::StringRef>414CPlusPlusLanguage::GetDemangledFunctionSuffix(llvm::StringRef demangled,415 const DemangledNameInfo &info) {416 if (!info.hasSuffix())417 return llvm::createStringError("Suffix range for '%s' is invalid.",418 demangled.data());419 420 return demangled.slice(info.SuffixRange.first, info.SuffixRange.second);421}422 423static llvm::Expected<llvm::StringRef>424GetDemangledFunctionSuffix(const SymbolContext &sc) {425 auto info_or_err = GetAndValidateInfo(sc);426 if (!info_or_err)427 return info_or_err.takeError();428 429 auto [demangled_name, info] = *info_or_err;430 431 return CPlusPlusLanguage::GetDemangledFunctionSuffix(demangled_name, info);432}433 434llvm::Expected<llvm::StringRef>435CPlusPlusLanguage::GetDemangledFunctionArguments(436 llvm::StringRef demangled, const DemangledNameInfo &info) {437 if (!info.hasArguments())438 return llvm::createStringError(439 "Function arguments range for '%s' is invalid.", demangled.data());440 441 return demangled.slice(info.ArgumentsRange.first, info.ArgumentsRange.second);442}443 444static bool PrintDemangledArgumentList(Stream &s, const SymbolContext &sc) {445 assert(sc.symbol);446 447 auto info_or_err = GetAndValidateInfo(sc);448 if (!info_or_err) {449 LLDB_LOG_ERROR(GetLog(LLDBLog::Language), info_or_err.takeError(),450 "Failed to handle ${{function.formatted-arguments}} "451 "frame-format variable: {0}");452 return false;453 }454 455 auto [demangled_name, info] = *info_or_err;456 457 auto args_or_err =458 CPlusPlusLanguage::GetDemangledFunctionArguments(demangled_name, info);459 if (!args_or_err) {460 LLDB_LOG_ERROR(GetLog(LLDBLog::Language), args_or_err.takeError(),461 "Failed to handle ${{function.formatted-arguments}} "462 "frame-format variable: {0}");463 return false;464 }465 466 s << *args_or_err;467 468 return true;469}470 471bool CPlusPlusLanguage::CxxMethodName::TrySimplifiedParse() {472 // This method tries to parse simple method definitions which are presumably473 // most comman in user programs. Definitions that can be parsed by this474 // function don't have return types and templates in the name.475 // A::B::C::fun(std::vector<T> &) const476 size_t arg_start, arg_end;477 llvm::StringRef full(m_full.GetCString());478 llvm::StringRef parens("()", 2);479 if (ReverseFindMatchingChars(full, parens, arg_start, arg_end)) {480 m_arguments = full.substr(arg_start, arg_end - arg_start + 1);481 if (arg_end + 1 < full.size())482 m_qualifiers = full.substr(arg_end + 1).ltrim();483 484 if (arg_start == 0)485 return false;486 size_t basename_end = arg_start;487 size_t context_start = 0;488 size_t context_end = full.rfind(':', basename_end);489 if (context_end == llvm::StringRef::npos)490 m_basename = full.substr(0, basename_end);491 else {492 if (context_start < context_end)493 m_context = full.substr(context_start, context_end - 1 - context_start);494 const size_t basename_begin = context_end + 1;495 m_basename = full.substr(basename_begin, basename_end - basename_begin);496 }497 498 if (IsTrivialBasename(m_basename) && IsTrivialContext(m_context)) {499 return true;500 }501 // The C++ basename doesn't match our regular expressions so this can't502 // be a valid C++ method, clear everything out and indicate an error503 m_context = llvm::StringRef();504 m_basename = llvm::StringRef();505 m_arguments = llvm::StringRef();506 m_qualifiers = llvm::StringRef();507 m_return_type = llvm::StringRef();508 return false;509 }510 return false;511}512 513void CPlusPlusLanguage::CxxMethodName::Parse() {514 if (!m_parsed && m_full) {515 if (TrySimplifiedParse()) {516 m_parse_error = false;517 } else {518 CPlusPlusNameParser parser(m_full.GetStringRef());519 if (auto function = parser.ParseAsFunctionDefinition()) {520 m_basename = function->name.basename;521 m_context = function->name.context;522 m_arguments = function->arguments;523 m_qualifiers = function->qualifiers;524 m_return_type = function->return_type;525 m_parse_error = false;526 } else {527 m_parse_error = true;528 }529 }530 if (m_context.empty()) {531 m_scope_qualified = std::string(m_basename);532 } else {533 m_scope_qualified = m_context;534 m_scope_qualified += "::";535 m_scope_qualified += m_basename;536 }537 m_parsed = true;538 }539}540 541llvm::StringRef542CPlusPlusLanguage::CxxMethodName::GetBasenameNoTemplateParameters() {543 llvm::StringRef basename = GetBasename();544 size_t arg_start, arg_end;545 llvm::StringRef parens("<>", 2);546 if (ReverseFindMatchingChars(basename, parens, arg_start, arg_end))547 return basename.substr(0, arg_start);548 549 return basename;550}551 552bool CPlusPlusLanguage::CxxMethodName::ContainsPath(llvm::StringRef path) {553 if (!m_parsed)554 Parse();555 556 // If we can't parse the incoming name, then just check that it contains path.557 if (m_parse_error)558 return m_full.GetStringRef().contains(path);559 560 llvm::StringRef identifier;561 llvm::StringRef context;562 const bool success =563 CPlusPlusLanguage::ExtractContextAndIdentifier(path, context, identifier);564 if (!success)565 return m_full.GetStringRef().contains(path);566 567 // Basename may include template arguments.568 // E.g.,569 // GetBaseName(): func<int>570 // identifier : func571 //572 // ...but we still want to account for identifiers with template parameter573 // lists, e.g., when users set breakpoints on template specializations.574 //575 // E.g.,576 // GetBaseName(): func<uint32_t>577 // identifier : func<int32_t*>578 //579 // Try to match the basename with or without template parameters.580 if (GetBasename() != identifier &&581 GetBasenameNoTemplateParameters() != identifier)582 return false;583 584 // Incoming path only had an identifier, so we match.585 if (context.empty())586 return true;587 // Incoming path has context but this method does not, no match.588 if (m_context.empty())589 return false;590 591 llvm::StringRef haystack = m_context;592 if (!haystack.consume_back(context))593 return false;594 if (haystack.empty() || !isalnum(haystack.back()))595 return true;596 597 return false;598}599 600bool CPlusPlusLanguage::DemangledNameContainsPath(llvm::StringRef path,601 ConstString demangled) const {602 CxxMethodName demangled_name(demangled);603 return demangled_name.ContainsPath(path);604}605 606bool CPlusPlusLanguage::ExtractContextAndIdentifier(607 llvm::StringRef name, llvm::StringRef &context,608 llvm::StringRef &identifier) {609 if (MSVCUndecoratedNameParser::IsMSVCUndecoratedName(name))610 return MSVCUndecoratedNameParser::ExtractContextAndIdentifier(name, context,611 identifier);612 613 CPlusPlusNameParser parser(name);614 if (auto full_name = parser.ParseAsFullName()) {615 identifier = full_name->basename;616 context = full_name->context;617 return true;618 }619 return false;620}621 622std::vector<ConstString> CPlusPlusLanguage::GenerateAlternateFunctionManglings(623 const ConstString mangled_name) const {624 std::vector<ConstString> alternates;625 626 /// Get a basic set of alternative manglings for the given symbol `name`, by627 /// making a few basic possible substitutions on basic types, storage duration628 /// and `const`ness for the given symbol. The output parameter `alternates`629 /// is filled with a best-guess, non-exhaustive set of different manglings630 /// for the given name.631 632 // Maybe we're looking for a const symbol but the debug info told us it was633 // non-const...634 if (!strncmp(mangled_name.GetCString(), "_ZN", 3) &&635 strncmp(mangled_name.GetCString(), "_ZNK", 4)) {636 std::string fixed_scratch("_ZNK");637 fixed_scratch.append(mangled_name.GetCString() + 3);638 alternates.push_back(ConstString(fixed_scratch));639 }640 641 // Maybe we're looking for a static symbol but we thought it was global...642 if (!strncmp(mangled_name.GetCString(), "_Z", 2) &&643 strncmp(mangled_name.GetCString(), "_ZL", 3)) {644 std::string fixed_scratch("_ZL");645 fixed_scratch.append(mangled_name.GetCString() + 2);646 alternates.push_back(ConstString(fixed_scratch));647 }648 649 auto *log = GetLog(LLDBLog::Language);650 651 // `char` is implementation defined as either `signed` or `unsigned`. As a652 // result a char parameter has 3 possible manglings: 'c'-char, 'a'-signed653 // char, 'h'-unsigned char. If we're looking for symbols with a signed char654 // parameter, try finding matches which have the general case 'c'.655 if (auto char_fixup_or_err =656 SubstituteType_ItaniumMangle(mangled_name.GetStringRef(), "a", "c")) {657 // LLDB_LOG(log, "Substituted mangling {0} -> {1}", Mangled, Result);658 if (*char_fixup_or_err)659 alternates.push_back(*char_fixup_or_err);660 } else661 LLDB_LOG_ERROR(log, char_fixup_or_err.takeError(),662 "Failed to substitute 'char' type mangling: {0}");663 664 // long long parameter mangling 'x', may actually just be a long 'l' argument665 if (auto long_fixup_or_err =666 SubstituteType_ItaniumMangle(mangled_name.GetStringRef(), "x", "l")) {667 if (*long_fixup_or_err)668 alternates.push_back(*long_fixup_or_err);669 } else670 LLDB_LOG_ERROR(log, long_fixup_or_err.takeError(),671 "Failed to substitute 'long long' type mangling: {0}");672 673 // unsigned long long parameter mangling 'y', may actually just be unsigned674 // long 'm' argument675 if (auto ulong_fixup_or_err =676 SubstituteType_ItaniumMangle(mangled_name.GetStringRef(), "y", "m")) {677 if (*ulong_fixup_or_err)678 alternates.push_back(*ulong_fixup_or_err);679 } else680 LLDB_LOG_ERROR(681 log, ulong_fixup_or_err.takeError(),682 "Failed to substitute 'unsigned long long' type mangling: {0}");683 684 if (auto ctor_fixup_or_err = SubstituteStructorAliases_ItaniumMangle(685 mangled_name.GetStringRef())) {686 if (*ctor_fixup_or_err) {687 alternates.push_back(*ctor_fixup_or_err);688 }689 } else690 LLDB_LOG_ERROR(log, ctor_fixup_or_err.takeError(),691 "Failed to substitute structor alias manglings: {0}");692 693 return alternates;694}695 696ConstString CPlusPlusLanguage::FindBestAlternateFunctionMangledName(697 const Mangled mangled, const SymbolContext &sym_ctx) const {698 ConstString demangled = mangled.GetDemangledName();699 if (!demangled)700 return ConstString();701 702 CxxMethodName cpp_name(demangled);703 std::string scope_qualified_name = cpp_name.GetScopeQualifiedName();704 705 if (!scope_qualified_name.size())706 return ConstString();707 708 if (!sym_ctx.module_sp)709 return ConstString();710 711 lldb_private::SymbolFile *sym_file = sym_ctx.module_sp->GetSymbolFile();712 if (!sym_file)713 return ConstString();714 715 std::vector<ConstString> alternates;716 sym_file->GetMangledNamesForFunction(scope_qualified_name, alternates);717 718 std::vector<ConstString> param_and_qual_matches;719 std::vector<ConstString> param_matches;720 for (size_t i = 0; i < alternates.size(); i++) {721 ConstString alternate_mangled_name = alternates[i];722 Mangled mangled(alternate_mangled_name);723 ConstString demangled = mangled.GetDemangledName();724 725 CxxMethodName alternate_cpp_name(demangled);726 if (!cpp_name.IsValid())727 continue;728 729 if (alternate_cpp_name.GetArguments() == cpp_name.GetArguments()) {730 if (alternate_cpp_name.GetQualifiers() == cpp_name.GetQualifiers())731 param_and_qual_matches.push_back(alternate_mangled_name);732 else733 param_matches.push_back(alternate_mangled_name);734 }735 }736 737 if (param_and_qual_matches.size())738 return param_and_qual_matches[0]; // It is assumed that there will be only739 // one!740 else if (param_matches.size())741 return param_matches[0]; // Return one of them as a best match742 else743 return ConstString();744}745 746static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {747 if (!cpp_category_sp)748 return;749 750 TypeSummaryImpl::Flags stl_summary_flags;751 stl_summary_flags.SetCascades(true)752 .SetSkipPointers(false)753 .SetSkipReferences(false)754 .SetDontShowChildren(true)755 .SetDontShowValue(false)756 .SetShowMembersOneLiner(false)757 .SetHideItemNames(false);758 759 AddCXXSummary(cpp_category_sp,760 lldb_private::formatters::LibcxxStringSummaryProviderASCII,761 "std::string summary provider", "^std::__[[:alnum:]]+::string$",762 stl_summary_flags, true);763 AddCXXSummary(cpp_category_sp,764 lldb_private::formatters::LibcxxStringSummaryProviderASCII,765 "std::string summary provider",766 "^std::__[[:alnum:]]+::basic_string<char, "767 "std::__[[:alnum:]]+::char_traits<char>,.*>$",768 stl_summary_flags, true);769 AddCXXSummary(cpp_category_sp,770 lldb_private::formatters::LibcxxStringSummaryProviderASCII,771 "std::string summary provider",772 "^std::__[[:alnum:]]+::basic_string<unsigned char, "773 "std::__[[:alnum:]]+::char_traits<unsigned char>,.*>$",774 stl_summary_flags, true);775 776 AddCXXSummary(cpp_category_sp,777 lldb_private::formatters::LibcxxStringSummaryProviderUTF16,778 "std::u16string summary provider",779 "^std::__[[:alnum:]]+::basic_string<char16_t, "780 "std::__[[:alnum:]]+::char_traits<char16_t>,.*>$",781 stl_summary_flags, true);782 783 AddCXXSummary(cpp_category_sp,784 lldb_private::formatters::LibcxxStringSummaryProviderUTF32,785 "std::u32string summary provider",786 "^std::__[[:alnum:]]+::basic_string<char32_t, "787 "std::__[[:alnum:]]+::char_traits<char32_t>,.*>$",788 stl_summary_flags, true);789 790 AddCXXSummary(cpp_category_sp,791 lldb_private::formatters::LibcxxWStringSummaryProvider,792 "std::wstring summary provider",793 "^std::__[[:alnum:]]+::wstring$", stl_summary_flags, true);794 AddCXXSummary(cpp_category_sp,795 lldb_private::formatters::LibcxxWStringSummaryProvider,796 "std::wstring summary provider",797 "^std::__[[:alnum:]]+::basic_string<wchar_t, "798 "std::__[[:alnum:]]+::char_traits<wchar_t>,.*>$",799 stl_summary_flags, true);800 801 AddCXXSummary(cpp_category_sp,802 lldb_private::formatters::LibcxxStringViewSummaryProviderASCII,803 "std::string_view summary provider",804 "^std::__[[:alnum:]]+::string_view$", stl_summary_flags, true);805 AddCXXSummary(cpp_category_sp,806 lldb_private::formatters::LibcxxStringViewSummaryProviderASCII,807 "std::string_view summary provider",808 "^std::__[[:alnum:]]+::basic_string_view<char, "809 "std::__[[:alnum:]]+::char_traits<char> >$",810 stl_summary_flags, true);811 AddCXXSummary(cpp_category_sp,812 lldb_private::formatters::LibcxxStringViewSummaryProviderASCII,813 "std::string_view summary provider",814 "^std::__[[:alnum:]]+::basic_string_view<unsigned char, "815 "std::__[[:alnum:]]+::char_traits<unsigned char> >$",816 stl_summary_flags, true);817 818 AddCXXSummary(cpp_category_sp,819 lldb_private::formatters::LibcxxStringViewSummaryProviderUTF16,820 "std::u16string_view summary provider",821 "^std::__[[:alnum:]]+::basic_string_view<char16_t, "822 "std::__[[:alnum:]]+::char_traits<char16_t> >$",823 stl_summary_flags, true);824 825 AddCXXSummary(cpp_category_sp,826 lldb_private::formatters::LibcxxStringViewSummaryProviderUTF32,827 "std::u32string_view summary provider",828 "^std::__[[:alnum:]]+::basic_string_view<char32_t, "829 "std::__[[:alnum:]]+::char_traits<char32_t> >$",830 stl_summary_flags, true);831 832 AddCXXSummary(cpp_category_sp,833 lldb_private::formatters::LibcxxWStringViewSummaryProvider,834 "std::wstring_view summary provider",835 "^std::__[[:alnum:]]+::wstring_view$", stl_summary_flags, true);836 AddCXXSummary(cpp_category_sp,837 lldb_private::formatters::LibcxxWStringViewSummaryProvider,838 "std::wstring_view summary provider",839 "^std::__[[:alnum:]]+::basic_string_view<wchar_t, "840 "std::__[[:alnum:]]+::char_traits<wchar_t> >$",841 stl_summary_flags, true);842 843 SyntheticChildren::Flags stl_synth_flags;844 stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(845 false);846 SyntheticChildren::Flags stl_deref_flags = stl_synth_flags;847 stl_deref_flags.SetFrontEndWantsDereference();848 849 AddCXXSynthetic(850 cpp_category_sp,851 lldb_private::formatters::LibcxxBitsetSyntheticFrontEndCreator,852 "libc++ std::bitset synthetic children",853 "^std::__[[:alnum:]]+::bitset<.+>$", stl_deref_flags, true);854 AddCXXSynthetic(855 cpp_category_sp,856 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator,857 "libc++ std::vector synthetic children",858 "^std::__[[:alnum:]]+::vector<.+>$", stl_deref_flags, true);859 AddCXXSynthetic(860 cpp_category_sp,861 lldb_private::formatters::LibcxxStdValarraySyntheticFrontEndCreator,862 "libc++ std::valarray synthetic children",863 "^std::__[[:alnum:]]+::valarray<.+>$", stl_deref_flags, true);864 AddCXXSynthetic(865 cpp_category_sp,866 lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEndCreator,867 "libc++ std::slice_array synthetic children",868 "^std::__[[:alnum:]]+::slice_array<.+>$", stl_deref_flags, true);869 AddCXXSynthetic(870 cpp_category_sp,871 lldb_private::formatters::LibcxxStdProxyArraySyntheticFrontEndCreator,872 "libc++ synthetic children for the valarray proxy arrays",873 "^std::__[[:alnum:]]+::(gslice|mask|indirect)_array<.+>$",874 stl_deref_flags, true);875 AddCXXSynthetic(876 cpp_category_sp,877 lldb_private::formatters::LibcxxStdForwardListSyntheticFrontEndCreator,878 "libc++ std::forward_list synthetic children",879 "^std::__[[:alnum:]]+::forward_list<.+>$", stl_synth_flags, true);880 AddCXXSynthetic(881 cpp_category_sp,882 lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator,883 "libc++ std::list synthetic children",884 // A POSIX variant of: "^std::__(?!cxx11:)[[:alnum:]]+::list<.+>$"885 // so that it does not clash with: "^std::(__cxx11::)?list<.+>$"886 "^std::__([A-Zabd-z0-9]|cx?[A-Za-wyz0-9]|cxx1?[A-Za-z02-9]|"887 "cxx11[[:alnum:]])[[:alnum:]]*::list<.+>$",888 stl_deref_flags, true);889 AddCXXSynthetic(890 cpp_category_sp,891 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,892 "libc++ std::map synthetic children", "^std::__[[:alnum:]]+::map<.+> >$",893 stl_synth_flags, true);894 AddCXXSynthetic(895 cpp_category_sp,896 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,897 "libc++ std::set synthetic children", "^std::__[[:alnum:]]+::set<.+> >$",898 stl_deref_flags, true);899 AddCXXSynthetic(900 cpp_category_sp,901 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,902 "libc++ std::multiset synthetic children",903 "^std::__[[:alnum:]]+::multiset<.+> >$", stl_deref_flags, true);904 AddCXXSynthetic(905 cpp_category_sp,906 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,907 "libc++ std::multimap synthetic children",908 "^std::__[[:alnum:]]+::multimap<.+> >$", stl_synth_flags, true);909 AddCXXSynthetic(910 cpp_category_sp,911 lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator,912 "libc++ std::unordered containers synthetic children",913 "^std::__[[:alnum:]]+::unordered_(multi)?(map|set)<.+> >$",914 stl_synth_flags, true);915 AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator,916 "libc++ std::queue synthetic children",917 "^std::__[[:alnum:]]+::queue<.+>$", stl_synth_flags, true);918 AddCXXSynthetic(cpp_category_sp, LibcxxTupleFrontEndCreator,919 "libc++ std::tuple synthetic children",920 "^std::__[[:alnum:]]+::tuple<.*>$", stl_synth_flags, true);921 AddCXXSynthetic(cpp_category_sp, LibcxxOptionalSyntheticFrontEndCreator,922 "libc++ std::optional synthetic children",923 "^std::__[[:alnum:]]+::optional<.+>$", stl_synth_flags, true);924 AddCXXSynthetic(cpp_category_sp, LibcxxVariantFrontEndCreator,925 "libc++ std::variant synthetic children",926 "^std::__[[:alnum:]]+::variant<.+>$", stl_synth_flags, true);927 AddCXXSynthetic(928 cpp_category_sp,929 lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator,930 "libc++ std::atomic synthetic children",931 "^std::__[[:alnum:]]+::atomic<.+>$", stl_synth_flags, true);932 AddCXXSynthetic(933 cpp_category_sp,934 lldb_private::formatters::LibcxxStdSpanSyntheticFrontEndCreator,935 "libc++ std::span synthetic children", "^std::__[[:alnum:]]+::span<.+>$",936 stl_deref_flags, true);937 AddCXXSynthetic(938 cpp_category_sp,939 lldb_private::formatters::LibcxxStdRangesRefViewSyntheticFrontEndCreator,940 "libc++ std::ranges::ref_view synthetic children",941 "^std::__[[:alnum:]]+::ranges::ref_view<.+>$", stl_deref_flags, true);942 943 cpp_category_sp->AddTypeSynthetic(944 "^std::__[[:alnum:]]+::deque<.+>$", eFormatterMatchRegex,945 SyntheticChildrenSP(new ScriptedSyntheticChildren(946 stl_synth_flags,947 "lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));948 949 AddCXXSynthetic(950 cpp_category_sp,951 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,952 "shared_ptr synthetic children", "^std::__[[:alnum:]]+::shared_ptr<.+>$",953 stl_synth_flags, true);954 955 static constexpr const char *const libcxx_std_unique_ptr_regex =956 "^std::__[[:alnum:]]+::unique_ptr<.+>$";957 AddCXXSynthetic(958 cpp_category_sp,959 lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEndCreator,960 "unique_ptr synthetic children", libcxx_std_unique_ptr_regex,961 stl_synth_flags, true);962 963 AddCXXSynthetic(964 cpp_category_sp,965 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator,966 "weak_ptr synthetic children", "^std::__[[:alnum:]]+::weak_ptr<.+>$",967 stl_synth_flags, true);968 AddCXXSummary(cpp_category_sp,969 lldb_private::formatters::LibcxxFunctionSummaryProvider,970 "libc++ std::function summary provider",971 "^std::__[[:alnum:]]+::function<.+>$", stl_summary_flags, true);972 973 static constexpr const char *const libcxx_std_coroutine_handle_regex =974 "^std::__[[:alnum:]]+::coroutine_handle<.+>$";975 AddCXXSynthetic(976 cpp_category_sp,977 lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEndCreator,978 "coroutine_handle synthetic children", libcxx_std_coroutine_handle_regex,979 stl_deref_flags, true);980 981 stl_summary_flags.SetDontShowChildren(false);982 stl_summary_flags.SetSkipPointers(false);983 AddCXXSummary(cpp_category_sp,984 lldb_private::formatters::ContainerSizeSummaryProvider,985 "libc++ std::bitset summary provider",986 "^std::__[[:alnum:]]+::bitset<.+>$", stl_summary_flags, true);987 AddCXXSummary(cpp_category_sp,988 lldb_private::formatters::ContainerSizeSummaryProvider,989 "libc++ std::vector summary provider",990 "^std::__[[:alnum:]]+::vector<.+>$", stl_summary_flags, true);991 AddCXXSummary(cpp_category_sp,992 lldb_private::formatters::ContainerSizeSummaryProvider,993 "libc++ std::valarray summary provider",994 "^std::__[[:alnum:]]+::valarray<.+>$", stl_summary_flags, true);995 AddCXXSummary(cpp_category_sp,996 lldb_private::formatters::LibcxxStdSliceArraySummaryProvider,997 "libc++ std::slice_array summary provider",998 "^std::__[[:alnum:]]+::slice_array<.+>$", stl_summary_flags,999 true);1000 AddCXXSummary(cpp_category_sp,1001 lldb_private::formatters::ContainerSizeSummaryProvider,1002 "libc++ summary provider for the valarray proxy arrays",1003 "^std::__[[:alnum:]]+::(gslice|mask|indirect)_array<.+>$",1004 stl_summary_flags, true);1005 AddCXXSummary(1006 cpp_category_sp, lldb_private::formatters::ContainerSizeSummaryProvider,1007 "libc++ std::list summary provider",1008 "^std::__[[:alnum:]]+::forward_list<.+>$", stl_summary_flags, true);1009 AddCXXSummary(1010 cpp_category_sp, lldb_private::formatters::ContainerSizeSummaryProvider,1011 "libc++ std::list summary provider",1012 // A POSIX variant of: "^std::__(?!cxx11:)[[:alnum:]]+::list<.+>$"1013 // so that it does not clash with: "^std::(__cxx11::)?list<.+>$"1014 "^std::__([A-Zabd-z0-9]|cx?[A-Za-wyz0-9]|cxx1?[A-Za-z02-9]|"1015 "cxx11[[:alnum:]])[[:alnum:]]*::list<.+>$",1016 stl_summary_flags, true);1017 AddCXXSummary(cpp_category_sp,1018 lldb_private::formatters::ContainerSizeSummaryProvider,1019 "libc++ std::map summary provider",1020 "^std::__[[:alnum:]]+::map<.+>$", stl_summary_flags, true);1021 AddCXXSummary(cpp_category_sp,1022 lldb_private::formatters::ContainerSizeSummaryProvider,1023 "libc++ std::deque summary provider",1024 "^std::__[[:alnum:]]+::deque<.+>$", stl_summary_flags, true);1025 AddCXXSummary(cpp_category_sp,1026 lldb_private::formatters::ContainerSizeSummaryProvider,1027 "libc++ std::queue summary provider",1028 "^std::__[[:alnum:]]+::queue<.+>$", stl_summary_flags, true);1029 AddCXXSummary(cpp_category_sp,1030 lldb_private::formatters::ContainerSizeSummaryProvider,1031 "libc++ std::set summary provider",1032 "^std::__[[:alnum:]]+::set<.+>$", stl_summary_flags, true);1033 AddCXXSummary(cpp_category_sp,1034 lldb_private::formatters::ContainerSizeSummaryProvider,1035 "libc++ std::multiset summary provider",1036 "^std::__[[:alnum:]]+::multiset<.+>$", stl_summary_flags, true);1037 AddCXXSummary(cpp_category_sp,1038 lldb_private::formatters::ContainerSizeSummaryProvider,1039 "libc++ std::multimap summary provider",1040 "^std::__[[:alnum:]]+::multimap<.+>$", stl_summary_flags, true);1041 AddCXXSummary(cpp_category_sp,1042 lldb_private::formatters::ContainerSizeSummaryProvider,1043 "libc++ std::unordered containers summary provider",1044 "^std::__[[:alnum:]]+::unordered_(multi)?(map|set)<.+> >$",1045 stl_summary_flags, true);1046 AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,1047 "libc++ std::tuple summary provider",1048 "^std::__[[:alnum:]]+::tuple<.*>$", stl_summary_flags, true);1049 AddCXXSummary(cpp_category_sp,1050 lldb_private::formatters::LibCxxAtomicSummaryProvider,1051 "libc++ std::atomic summary provider",1052 "^std::__[[:alnum:]]+::atomic<.+>$", stl_summary_flags, true);1053 AddCXXSummary(cpp_category_sp,1054 lldb_private::formatters::GenericOptionalSummaryProvider,1055 "libc++ std::optional summary provider",1056 "^std::__[[:alnum:]]+::optional<.+>$", stl_summary_flags, true);1057 AddCXXSummary(cpp_category_sp,1058 lldb_private::formatters::LibcxxVariantSummaryProvider,1059 "libc++ std::variant summary provider",1060 "^std::__[[:alnum:]]+::variant<.+>$", stl_summary_flags, true);1061 AddCXXSummary(cpp_category_sp,1062 lldb_private::formatters::ContainerSizeSummaryProvider,1063 "libc++ std::span summary provider",1064 "^std::__[[:alnum:]]+::span<.+>$", stl_summary_flags, true);1065 1066 stl_summary_flags.SetSkipPointers(true);1067 1068 AddCXXSummary(cpp_category_sp,1069 lldb_private::formatters::LibcxxSmartPointerSummaryProvider,1070 "libc++ std::shared_ptr summary provider",1071 "^std::__[[:alnum:]]+::shared_ptr<.+>$", stl_summary_flags,1072 true);1073 AddCXXSummary(cpp_category_sp,1074 lldb_private::formatters::LibcxxSmartPointerSummaryProvider,1075 "libc++ std::weak_ptr summary provider",1076 "^std::__[[:alnum:]]+::weak_ptr<.+>$", stl_summary_flags, true);1077 AddCXXSummary(cpp_category_sp,1078 lldb_private::formatters::LibcxxUniquePointerSummaryProvider,1079 "libc++ std::unique_ptr summary provider",1080 libcxx_std_unique_ptr_regex, stl_summary_flags, true);1081 1082 AddCXXSummary(cpp_category_sp,1083 lldb_private::formatters::StdlibCoroutineHandleSummaryProvider,1084 "libc++ std::coroutine_handle summary provider",1085 libcxx_std_coroutine_handle_regex, stl_summary_flags, true);1086 1087 AddCXXSynthetic(1088 cpp_category_sp,1089 lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator,1090 "std::vector iterator synthetic children",1091 "^std::__[[:alnum:]]+::__wrap_iter<.+>$", stl_synth_flags, true);1092 1093 AddCXXSynthetic(1094 cpp_category_sp,1095 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator,1096 "std::map iterator synthetic children",1097 "^std::__[[:alnum:]]+::__map_(const_)?iterator<.+>$", stl_synth_flags,1098 true);1099 1100 AddCXXSynthetic(cpp_category_sp,1101 lldb_private::formatters::1102 LibCxxUnorderedMapIteratorSyntheticFrontEndCreator,1103 "std::unordered_map iterator synthetic children",1104 "^std::__[[:alnum:]]+::__hash_map_(const_)?iterator<.+>$",1105 stl_synth_flags, true);1106 // Chrono duration typedefs1107 cpp_category_sp->AddTypeSummary(1108 "^std::__[[:alnum:]]+::chrono::nanoseconds", eFormatterMatchRegex,1109 TypeSummaryImplSP(new StringSummaryFormat(1110 eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} ns")));1111 cpp_category_sp->AddTypeSummary(1112 "^std::__[[:alnum:]]+::chrono::microseconds", eFormatterMatchRegex,1113 TypeSummaryImplSP(new StringSummaryFormat(1114 eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} µs")));1115 cpp_category_sp->AddTypeSummary(1116 "^std::__[[:alnum:]]+::chrono::milliseconds", eFormatterMatchRegex,1117 TypeSummaryImplSP(new StringSummaryFormat(1118 eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} ms")));1119 cpp_category_sp->AddTypeSummary(1120 "^std::__[[:alnum:]]+::chrono::seconds", eFormatterMatchRegex,1121 TypeSummaryImplSP(new StringSummaryFormat(1122 eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} s")));1123 cpp_category_sp->AddTypeSummary(1124 "^std::__[[:alnum:]]+::chrono::minutes", eFormatterMatchRegex,1125 TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |1126 eTypeOptionHideValue,1127 "${var.__rep_} min")));1128 cpp_category_sp->AddTypeSummary(1129 "^std::__[[:alnum:]]+::chrono::hours", eFormatterMatchRegex,1130 TypeSummaryImplSP(new StringSummaryFormat(1131 eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} h")));1132 1133 cpp_category_sp->AddTypeSummary(1134 "^std::__[[:alnum:]]+::chrono::days", eFormatterMatchRegex,1135 TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |1136 eTypeOptionHideValue,1137 "${var.__rep_} days")));1138 cpp_category_sp->AddTypeSummary(1139 "^std::__[[:alnum:]]+::chrono::weeks", eFormatterMatchRegex,1140 TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |1141 eTypeOptionHideValue,1142 "${var.__rep_} weeks")));1143 cpp_category_sp->AddTypeSummary(1144 "^std::__[[:alnum:]]+::chrono::months", eFormatterMatchRegex,1145 TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |1146 eTypeOptionHideValue,1147 "${var.__rep_} months")));1148 cpp_category_sp->AddTypeSummary(1149 "^std::__[[:alnum:]]+::chrono::years", eFormatterMatchRegex,1150 TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |1151 eTypeOptionHideValue,1152 "${var.__rep_} years")));1153 cpp_category_sp->AddTypeSummary(1154 "^std::__[[:alnum:]]+::chrono::seconds", eFormatterMatchRegex,1155 TypeSummaryImplSP(new StringSummaryFormat(1156 eTypeOptionHideChildren | eTypeOptionHideValue, "${var.__rep_} s")));1157 1158 // Chrono time point types1159 1160 AddCXXSummary(cpp_category_sp,1161 lldb_private::formatters::LibcxxChronoSysSecondsSummaryProvider,1162 "libc++ std::chrono::sys_seconds summary provider",1163 "^std::__[[:alnum:]]+::chrono::time_point<"1164 "std::__[[:alnum:]]+::chrono::system_clock, "1165 "std::__[[:alnum:]]+::chrono::duration<.*, "1166 "std::__[[:alnum:]]+::ratio<1, 1> "1167 "> >$",1168 eTypeOptionHideChildren | eTypeOptionHideValue |1169 eTypeOptionCascade,1170 true);1171 AddCXXSummary(cpp_category_sp,1172 lldb_private::formatters::LibcxxChronoSysDaysSummaryProvider,1173 "libc++ std::chrono::sys_seconds summary provider",1174 "^std::__[[:alnum:]]+::chrono::time_point<"1175 "std::__[[:alnum:]]+::chrono::system_clock, "1176 "std::__[[:alnum:]]+::chrono::duration<int, "1177 "std::__[[:alnum:]]+::ratio<86400, 1> "1178 "> >$",1179 eTypeOptionHideChildren | eTypeOptionHideValue |1180 eTypeOptionCascade,1181 true);1182 1183 AddCXXSummary(1184 cpp_category_sp,1185 lldb_private::formatters::LibcxxChronoLocalSecondsSummaryProvider,1186 "libc++ std::chrono::local_seconds summary provider",1187 "^std::__[[:alnum:]]+::chrono::time_point<"1188 "std::__[[:alnum:]]+::chrono::local_t, "1189 "std::__[[:alnum:]]+::chrono::duration<.*, "1190 "std::__[[:alnum:]]+::ratio<1, 1> "1191 "> >$",1192 eTypeOptionHideChildren | eTypeOptionHideValue | eTypeOptionCascade,1193 true);1194 AddCXXSummary(cpp_category_sp,1195 lldb_private::formatters::LibcxxChronoLocalDaysSummaryProvider,1196 "libc++ std::chrono::local_seconds summary provider",1197 "^std::__[[:alnum:]]+::chrono::time_point<"1198 "std::__[[:alnum:]]+::chrono::local_t, "1199 "std::__[[:alnum:]]+::chrono::duration<int, "1200 "std::__[[:alnum:]]+::ratio<86400, 1> "1201 "> >$",1202 eTypeOptionHideChildren | eTypeOptionHideValue |1203 eTypeOptionCascade,1204 true);1205 1206 // Chrono calendar types1207 1208 cpp_category_sp->AddTypeSummary(1209 "^std::__[[:alnum:]]+::chrono::day$", eFormatterMatchRegex,1210 TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |1211 eTypeOptionHideValue,1212 "day=${var.__d_%u}")));1213 1214 AddCXXSummary(cpp_category_sp,1215 lldb_private::formatters::LibcxxChronoMonthSummaryProvider,1216 "libc++ std::chrono::month summary provider",1217 "^std::__[[:alnum:]]+::chrono::month$",1218 eTypeOptionHideChildren | eTypeOptionHideValue, true);1219 1220 cpp_category_sp->AddTypeSummary(1221 "^std::__[[:alnum:]]+::chrono::year$", eFormatterMatchRegex,1222 TypeSummaryImplSP(new StringSummaryFormat(1223 eTypeOptionHideChildren | eTypeOptionHideValue, "year=${var.__y_}")));1224 1225 AddCXXSummary(cpp_category_sp,1226 lldb_private::formatters::LibcxxChronoWeekdaySummaryProvider,1227 "libc++ std::chrono::weekday summary provider",1228 "^std::__[[:alnum:]]+::chrono::weekday$",1229 eTypeOptionHideChildren | eTypeOptionHideValue, true);1230 1231 cpp_category_sp->AddTypeSummary(1232 "^std::__[[:alnum:]]+::chrono::weekday_indexed$", eFormatterMatchRegex,1233 TypeSummaryImplSP(new StringSummaryFormat(1234 eTypeOptionHideChildren | eTypeOptionHideValue,1235 "${var.__wd_} index=${var.__idx_%u}")));1236 1237 cpp_category_sp->AddTypeSummary(1238 "^std::__[[:alnum:]]+::chrono::weekday_last$", eFormatterMatchRegex,1239 TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |1240 eTypeOptionHideValue,1241 "${var.__wd_} index=last")));1242 cpp_category_sp->AddTypeSummary(1243 "^std::__[[:alnum:]]+::chrono::month_day$", eFormatterMatchRegex,1244 TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |1245 eTypeOptionHideValue,1246 "${var.__m_} ${var.__d_}")));1247 cpp_category_sp->AddTypeSummary(1248 "^std::__[[:alnum:]]+::chrono::month_day_last$", eFormatterMatchRegex,1249 TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |1250 eTypeOptionHideValue,1251 "${var.__m_} day=last")));1252 1253 cpp_category_sp->AddTypeSummary(1254 "^std::__[[:alnum:]]+::chrono::month_weekday$", eFormatterMatchRegex,1255 TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |1256 eTypeOptionHideValue,1257 "${var.__m_} ${var.__wdi_}")));1258 1259 cpp_category_sp->AddTypeSummary(1260 "^std::__[[:alnum:]]+::chrono::month_weekday_last$", eFormatterMatchRegex,1261 TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |1262 eTypeOptionHideValue,1263 "${var.__m_} ${var.__wdl_}")));1264 1265 cpp_category_sp->AddTypeSummary(1266 "^std::__[[:alnum:]]+::chrono::year_month$", eFormatterMatchRegex,1267 TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |1268 eTypeOptionHideValue,1269 "${var.__y_} ${var.__m_}")));1270 1271 AddCXXSummary(1272 cpp_category_sp,1273 lldb_private::formatters::LibcxxChronoYearMonthDaySummaryProvider,1274 "libc++ std::chrono::year_month_day summary provider",1275 "^std::__[[:alnum:]]+::chrono::year_month_day$",1276 eTypeOptionHideChildren | eTypeOptionHideValue, true);1277 1278 cpp_category_sp->AddTypeSummary(1279 "^std::__[[:alnum:]]+::chrono::year_month_day_last$",1280 eFormatterMatchRegex,1281 TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |1282 eTypeOptionHideValue,1283 "${var.__y_} ${var.__mdl_}")));1284 1285 cpp_category_sp->AddTypeSummary(1286 "^std::__[[:alnum:]]+::chrono::year_month_weekday$", eFormatterMatchRegex,1287 TypeSummaryImplSP(new StringSummaryFormat(1288 eTypeOptionHideChildren | eTypeOptionHideValue,1289 "${var.__y_} ${var.__m_} ${var.__wdi_}")));1290 1291 cpp_category_sp->AddTypeSummary(1292 "^std::__[[:alnum:]]+::chrono::year_month_weekday_last$",1293 eFormatterMatchRegex,1294 TypeSummaryImplSP(new StringSummaryFormat(1295 eTypeOptionHideChildren | eTypeOptionHideValue,1296 "${var.__y_} ${var.__m_} ${var.__wdl_}")));1297}1298 1299static void RegisterStdStringSummaryProvider(1300 const lldb::TypeCategoryImplSP &category_sp, llvm::StringRef string_ty,1301 llvm::StringRef char_ty, lldb::TypeSummaryImplSP summary_sp) {1302 auto makeSpecifier = [](llvm::StringRef name) {1303 return std::make_shared<lldb_private::TypeNameSpecifierImpl>(1304 name, eFormatterMatchExact);1305 };1306 1307 category_sp->AddTypeSummary(makeSpecifier(string_ty), summary_sp);1308 1309 category_sp->AddTypeSummary(1310 makeSpecifier(llvm::formatv("std::basic_string<{}>", char_ty).str()),1311 summary_sp);1312 1313 category_sp->AddTypeSummary(1314 std::make_shared<lldb_private::TypeNameSpecifierImpl>(1315 llvm::formatv("^std::basic_string<{0}, ?std::char_traits<{0}>,.*>$",1316 char_ty)1317 .str(),1318 eFormatterMatchRegex),1319 summary_sp);1320}1321 1322static void RegisterStdStringViewSummaryProvider(1323 const lldb::TypeCategoryImplSP &category_sp, llvm::StringRef string_ty,1324 llvm::StringRef char_ty, lldb::TypeSummaryImplSP summary_sp) {1325 // std::string_view1326 category_sp->AddTypeSummary(1327 std::make_shared<lldb_private::TypeNameSpecifierImpl>(1328 string_ty, eFormatterMatchExact),1329 summary_sp);1330 1331 // std::basic_string_view<char, std::char_traits<char>>1332 // NativePDB has spaces at different positions compared to PDB and DWARF, so1333 // use a regex and make them optional.1334 category_sp->AddTypeSummary(1335 std::make_shared<lldb_private::TypeNameSpecifierImpl>(1336 llvm::formatv(1337 "^std::basic_string_view<{0}, ?std::char_traits<{0}> ?>$",1338 char_ty)1339 .str(),1340 eFormatterMatchRegex),1341 summary_sp);1342}1343 1344static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {1345 if (!cpp_category_sp)1346 return;1347 1348 TypeSummaryImpl::Flags stl_summary_flags;1349 stl_summary_flags.SetCascades(true)1350 .SetSkipPointers(false)1351 .SetSkipReferences(false)1352 .SetDontShowChildren(true)1353 .SetDontShowValue(false)1354 .SetShowMembersOneLiner(false)1355 .SetHideItemNames(false);1356 1357 lldb::TypeSummaryImplSP string_summary_sp(new CXXFunctionSummaryFormat(1358 stl_summary_flags, LibStdcppStringSummaryProvider,1359 "libstdc++ std::(w)string summary provider"));1360 cpp_category_sp->AddTypeSummary("std::__cxx11::string", eFormatterMatchExact,1361 string_summary_sp);1362 cpp_category_sp->AddTypeSummary(1363 "^std::__cxx11::basic_string<char, std::char_traits<char>,.*>$",1364 eFormatterMatchRegex, string_summary_sp);1365 cpp_category_sp->AddTypeSummary("^std::__cxx11::basic_string<unsigned char, "1366 "std::char_traits<unsigned char>,.*>$",1367 eFormatterMatchRegex, string_summary_sp);1368 1369 cpp_category_sp->AddTypeSummary("std::__cxx11::wstring", eFormatterMatchExact,1370 string_summary_sp);1371 cpp_category_sp->AddTypeSummary(1372 "^std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>,.*>$",1373 eFormatterMatchRegex, string_summary_sp);1374 1375 SyntheticChildren::Flags stl_synth_flags;1376 stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(1377 false);1378 SyntheticChildren::Flags stl_deref_flags = stl_synth_flags;1379 stl_deref_flags.SetFrontEndWantsDereference();1380 1381 cpp_category_sp->AddTypeSynthetic(1382 "^std::__debug::vector<.+>(( )?&)?$", eFormatterMatchRegex,1383 SyntheticChildrenSP(new ScriptedSyntheticChildren(1384 stl_synth_flags,1385 "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));1386 cpp_category_sp->AddTypeSynthetic(1387 "^std::__debug::map<.+> >(( )?&)?$", eFormatterMatchRegex,1388 SyntheticChildrenSP(new ScriptedSyntheticChildren(1389 stl_synth_flags,1390 "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));1391 cpp_category_sp->AddTypeSynthetic(1392 "^std::__debug::deque<.+>(( )?&)?$", eFormatterMatchRegex,1393 SyntheticChildrenSP(new ScriptedSyntheticChildren(1394 stl_deref_flags,1395 "lldb.formatters.cpp.gnu_libstdcpp.StdDequeSynthProvider")));1396 cpp_category_sp->AddTypeSynthetic(1397 "^std::__debug::set<.+> >(( )?&)?$", eFormatterMatchRegex,1398 SyntheticChildrenSP(new ScriptedSyntheticChildren(1399 stl_deref_flags,1400 "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));1401 cpp_category_sp->AddTypeSynthetic(1402 "^std::__debug::multimap<.+> >(( )?&)?$", eFormatterMatchRegex,1403 SyntheticChildrenSP(new ScriptedSyntheticChildren(1404 stl_deref_flags,1405 "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));1406 cpp_category_sp->AddTypeSynthetic(1407 "^std::__debug::multiset<.+> >(( )?&)?$", eFormatterMatchRegex,1408 SyntheticChildrenSP(new ScriptedSyntheticChildren(1409 stl_deref_flags,1410 "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));1411 cpp_category_sp->AddTypeSynthetic(1412 "^std::__debug::unordered_(multi)?(map|set)<.+> >$", eFormatterMatchRegex,1413 SyntheticChildrenSP(new ScriptedSyntheticChildren(1414 stl_deref_flags,1415 "lldb.formatters.cpp.gnu_libstdcpp.StdUnorderedMapSynthProvider")));1416 cpp_category_sp->AddTypeSynthetic(1417 "^std::__(debug|cxx11)::list<.+>(( )?&)?$", eFormatterMatchRegex,1418 SyntheticChildrenSP(new ScriptedSyntheticChildren(1419 stl_deref_flags,1420 "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));1421 cpp_category_sp->AddTypeSynthetic(1422 "^std::__(debug|cxx11)::forward_list<.+>(( )?&)?$", eFormatterMatchRegex,1423 SyntheticChildrenSP(new ScriptedSyntheticChildren(1424 stl_synth_flags,1425 "lldb.formatters.cpp.gnu_libstdcpp.StdForwardListSynthProvider")));1426 1427 stl_summary_flags.SetDontShowChildren(false);1428 stl_summary_flags.SetSkipPointers(false);1429 1430 AddCXXSummary(1431 cpp_category_sp, lldb_private::formatters::ContainerSizeSummaryProvider,1432 "libstdc++ std::bitset summary provider",1433 "^std::(__debug::)?bitset<.+>(( )?&)?$", stl_summary_flags, true);1434 1435 AddCXXSummary(cpp_category_sp,1436 lldb_private::formatters::ContainerSizeSummaryProvider,1437 "libstdc++ std::__debug::vector summary provider",1438 "^std::__debug::vector<.+>(( )?&)?$", stl_summary_flags, true);1439 1440 AddCXXSummary(cpp_category_sp,1441 lldb_private::formatters::ContainerSizeSummaryProvider,1442 "libstdc++ debug std::map summary provider",1443 "^std::__debug::map<.+> >(( )?&)?$", stl_summary_flags, true);1444 1445 AddCXXSummary(cpp_category_sp,1446 lldb_private::formatters::ContainerSizeSummaryProvider,1447 "libstdc++ debug std::set summary provider",1448 "^std::__debug::set<.+> >(( )?&)?$", stl_summary_flags, true);1449 1450 AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,1451 "libstdc++ debug std::deque summary provider",1452 "^std::__debug::deque<.+>(( )?&)?$", stl_summary_flags, true);1453 1454 AddCXXSummary(1455 cpp_category_sp, lldb_private::formatters::ContainerSizeSummaryProvider,1456 "libstdc++ debug std::multimap summary provider",1457 "^std::__debug::multimap<.+> >(( )?&)?$", stl_summary_flags, true);1458 1459 AddCXXSummary(1460 cpp_category_sp, lldb_private::formatters::ContainerSizeSummaryProvider,1461 "libstdc++ debug std::multiset summary provider",1462 "^std::__debug::multiset<.+> >(( )?&)?$", stl_summary_flags, true);1463 1464 AddCXXSummary(cpp_category_sp,1465 lldb_private::formatters::ContainerSizeSummaryProvider,1466 "libstdc++ debug std unordered container summary provider",1467 "^std::__debug::unordered_(multi)?(map|set)<.+> >$",1468 stl_summary_flags, true);1469 1470 AddCXXSummary(1471 cpp_category_sp, lldb_private::formatters::ContainerSizeSummaryProvider,1472 "libstdc++ debug std::list summary provider",1473 "^std::__(debug|cxx11)::list<.+>(( )?&)?$", stl_summary_flags, true);1474 1475 cpp_category_sp->AddTypeSummary(1476 "^std::__(debug|cxx11)::forward_list<.+>(( )?&)?$", eFormatterMatchRegex,1477 TypeSummaryImplSP(new ScriptSummaryFormat(1478 stl_summary_flags,1479 "lldb.formatters.cpp.gnu_libstdcpp.ForwardListSummaryProvider")));1480 1481 AddCXXSynthetic(1482 cpp_category_sp,1483 lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator,1484 "std::vector iterator synthetic children",1485 "^__gnu_cxx::__normal_iterator<.+>$", stl_synth_flags, true);1486 1487 AddCXXSynthetic(1488 cpp_category_sp,1489 lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator,1490 "std::map iterator synthetic children",1491 "^std::_Rb_tree_(const_)?iterator<.+>$", stl_synth_flags, true);1492 1493 AddCXXSynthetic(1494 cpp_category_sp,1495 lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator,1496 "std::unique_ptr synthetic children", "^std::unique_ptr<.+>(( )?&)?$",1497 stl_synth_flags, true);1498 1499 static constexpr const char *const libstdcpp_std_coroutine_handle_regex =1500 "^std::coroutine_handle<.+>(( )?&)?$";1501 AddCXXSynthetic(1502 cpp_category_sp,1503 lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEndCreator,1504 "std::coroutine_handle synthetic children",1505 libstdcpp_std_coroutine_handle_regex, stl_deref_flags, true);1506 1507 AddCXXSynthetic(1508 cpp_category_sp,1509 lldb_private::formatters::LibStdcppBitsetSyntheticFrontEndCreator,1510 "std::bitset synthetic child", "^std::(__debug::)?bitset<.+>(( )?&)?$",1511 stl_deref_flags, true);1512 1513 AddCXXSummary(cpp_category_sp,1514 lldb_private::formatters::StdlibCoroutineHandleSummaryProvider,1515 "libstdc++ std::coroutine_handle summary provider",1516 libstdcpp_std_coroutine_handle_regex, stl_summary_flags, true);1517}1518 1519static lldb_private::SyntheticChildrenFrontEnd *1520GenericSmartPointerSyntheticFrontEndCreator(CXXSyntheticChildren *children,1521 lldb::ValueObjectSP valobj_sp) {1522 if (!valobj_sp)1523 return nullptr;1524 1525 if (IsMsvcStlSmartPointer(*valobj_sp))1526 return MsvcStlSmartPointerSyntheticFrontEndCreator(valobj_sp);1527 return LibStdcppSharedPtrSyntheticFrontEndCreator(children, valobj_sp);1528}1529 1530static bool1531GenericSmartPointerSummaryProvider(ValueObject &valobj, Stream &stream,1532 const TypeSummaryOptions &options) {1533 if (IsMsvcStlSmartPointer(valobj))1534 return MsvcStlSmartPointerSummaryProvider(valobj, stream, options);1535 return LibStdcppSmartPointerSummaryProvider(valobj, stream, options);1536}1537 1538static lldb_private::SyntheticChildrenFrontEnd *1539GenericUniquePtrSyntheticFrontEndCreator(CXXSyntheticChildren *children,1540 lldb::ValueObjectSP valobj_sp) {1541 if (!valobj_sp)1542 return nullptr;1543 1544 if (IsMsvcStlUniquePtr(*valobj_sp))1545 return MsvcStlUniquePtrSyntheticFrontEndCreator(valobj_sp);1546 return LibStdcppUniquePtrSyntheticFrontEndCreator(children, valobj_sp);1547}1548 1549static bool GenericUniquePtrSummaryProvider(ValueObject &valobj, Stream &stream,1550 const TypeSummaryOptions &options) {1551 if (IsMsvcStlUniquePtr(valobj))1552 return MsvcStlUniquePtrSummaryProvider(valobj, stream, options);1553 return LibStdcppUniquePointerSummaryProvider(valobj, stream, options);1554}1555 1556static SyntheticChildrenFrontEnd *1557GenericTupleSyntheticFrontEndCreator(CXXSyntheticChildren *children,1558 lldb::ValueObjectSP valobj_sp) {1559 if (!valobj_sp)1560 return nullptr;1561 1562 if (IsMsvcStlTuple(*valobj_sp))1563 return MsvcStlTupleSyntheticFrontEndCreator(children, valobj_sp);1564 return LibStdcppTupleSyntheticFrontEndCreator(children, valobj_sp);1565}1566 1567static SyntheticChildrenFrontEnd *1568GenericVectorSyntheticFrontEndCreator(CXXSyntheticChildren *children,1569 lldb::ValueObjectSP valobj_sp) {1570 if (!valobj_sp)1571 return nullptr;1572 1573 // checks for vector<T> and vector<bool>1574 if (auto *msvc = MsvcStlVectorSyntheticFrontEndCreator(valobj_sp))1575 return msvc;1576 1577 return new ScriptedSyntheticChildren::FrontEnd(1578 "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider", *valobj_sp);1579}1580 1581static SyntheticChildrenFrontEnd *1582GenericListSyntheticFrontEndCreator(CXXSyntheticChildren *children,1583 lldb::ValueObjectSP valobj_sp) {1584 if (!valobj_sp)1585 return nullptr;1586 1587 if (IsMsvcStlList(*valobj_sp))1588 return MsvcStlListSyntheticFrontEndCreator(children, valobj_sp);1589 return new ScriptedSyntheticChildren::FrontEnd(1590 "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider", *valobj_sp);1591}1592 1593static SyntheticChildrenFrontEnd *1594GenericForwardListSyntheticFrontEndCreator(CXXSyntheticChildren *children,1595 lldb::ValueObjectSP valobj_sp) {1596 if (!valobj_sp)1597 return nullptr;1598 1599 if (IsMsvcStlList(*valobj_sp))1600 return MsvcStlForwardListSyntheticFrontEndCreator(children, valobj_sp);1601 return new ScriptedSyntheticChildren::FrontEnd(1602 "lldb.formatters.cpp.gnu_libstdcpp.StdForwardListSynthProvider",1603 *valobj_sp);1604}1605 1606static SyntheticChildrenFrontEnd *1607GenericOptionalSyntheticFrontEndCreator(CXXSyntheticChildren *children,1608 lldb::ValueObjectSP valobj_sp) {1609 if (!valobj_sp)1610 return nullptr;1611 1612 if (IsMsvcStlOptional(*valobj_sp))1613 return MsvcStlOptionalSyntheticFrontEndCreator(children, valobj_sp);1614 return LibStdcppOptionalSyntheticFrontEndCreator(children, valobj_sp);1615}1616 1617static SyntheticChildrenFrontEnd *1618GenericVariantSyntheticFrontEndCreator(CXXSyntheticChildren *children,1619 lldb::ValueObjectSP valobj_sp) {1620 if (!valobj_sp)1621 return nullptr;1622 1623 if (IsMsvcStlVariant(*valobj_sp))1624 return MsvcStlVariantSyntheticFrontEndCreator(children, valobj_sp);1625 return new ScriptedSyntheticChildren::FrontEnd(1626 "lldb.formatters.cpp.gnu_libstdcpp.VariantSynthProvider", *valobj_sp);1627}1628 1629static bool GenericVariantSummaryProvider(ValueObject &valobj, Stream &stream,1630 const TypeSummaryOptions &options) {1631 if (IsMsvcStlVariant(valobj))1632 return MsvcStlVariantSummaryProvider(valobj, stream, options);1633 return LibStdcppVariantSummaryProvider(valobj, stream, options);1634}1635 1636static SyntheticChildrenFrontEnd *1637GenericUnorderedSyntheticFrontEndCreator(CXXSyntheticChildren *children,1638 ValueObjectSP valobj_sp) {1639 if (!valobj_sp)1640 return nullptr;1641 1642 if (IsMsvcStlUnordered(*valobj_sp))1643 return MsvcStlUnorderedSyntheticFrontEndCreator(children, valobj_sp);1644 return new ScriptedSyntheticChildren::FrontEnd(1645 "lldb.formatters.cpp.gnu_libstdcpp.StdUnorderedMapSynthProvider",1646 *valobj_sp);1647}1648 1649static SyntheticChildrenFrontEnd *1650GenericMapLikeSyntheticFrontEndCreator(CXXSyntheticChildren *children,1651 ValueObjectSP valobj_sp) {1652 if (!valobj_sp)1653 return nullptr;1654 1655 if (IsMsvcStlMapLike(*valobj_sp))1656 return MsvcStlMapLikeSyntheticFrontEndCreator(valobj_sp);1657 return new ScriptedSyntheticChildren::FrontEnd(1658 "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider", *valobj_sp);1659}1660 1661static SyntheticChildrenFrontEnd *1662GenericDequeSyntheticFrontEndCreator(CXXSyntheticChildren *children,1663 ValueObjectSP valobj_sp) {1664 if (!valobj_sp)1665 return nullptr;1666 1667 if (IsMsvcStlDeque(*valobj_sp))1668 return MsvcStlDequeSyntheticFrontEndCreator(children, valobj_sp);1669 return new ScriptedSyntheticChildren::FrontEnd(1670 "lldb.formatters.cpp.gnu_libstdcpp.StdDequeSynthProvider", *valobj_sp);1671}1672 1673/// Load formatters that are formatting types from more than one STL1674static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {1675 if (!cpp_category_sp)1676 return;1677 1678 TypeSummaryImpl::Flags stl_summary_flags;1679 stl_summary_flags.SetCascades(true)1680 .SetSkipPointers(false)1681 .SetSkipReferences(false)1682 .SetDontShowChildren(true)1683 .SetDontShowValue(false)1684 .SetShowMembersOneLiner(false)1685 .SetHideItemNames(false);1686 SyntheticChildren::Flags stl_synth_flags;1687 stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(1688 false);1689 1690 using StringElementType = StringPrinter::StringElementType;1691 1692 RegisterStdStringSummaryProvider(1693 cpp_category_sp, "std::string", "char",1694 std::make_shared<CXXFunctionSummaryFormat>(1695 stl_summary_flags,1696 [](ValueObject &valobj, Stream &stream,1697 const TypeSummaryOptions &options) {1698 if (IsMsvcStlStringType(valobj))1699 return MsvcStlStringSummaryProvider<StringElementType::ASCII>(1700 valobj, stream, options);1701 return LibStdcppStringSummaryProvider(valobj, stream, options);1702 },1703 "MSVC STL/libstdc++ std::string summary provider"));1704 RegisterStdStringSummaryProvider(1705 cpp_category_sp, "std::wstring", "wchar_t",1706 std::make_shared<CXXFunctionSummaryFormat>(1707 stl_summary_flags,1708 [](ValueObject &valobj, Stream &stream,1709 const TypeSummaryOptions &options) {1710 if (IsMsvcStlStringType(valobj))1711 return MsvcStlWStringSummaryProvider(valobj, stream, options);1712 return LibStdcppStringSummaryProvider(valobj, stream, options);1713 },1714 "MSVC STL/libstdc++ std::wstring summary provider"));1715 1716 // NOTE: it is loaded as a common formatter because the libc++ version is not1717 // in the `__1` namespace, hence we need to dispatch based on the class1718 // layout.1719 AddCXXSynthetic(cpp_category_sp,1720 GenericInitializerListSyntheticFrontEndCreator,1721 "std::initializer_list synthetic children",1722 "^std::initializer_list<.+>$", stl_synth_flags, true);1723 1724 stl_summary_flags.SetDontShowChildren(false);1725 stl_summary_flags.SetSkipPointers(false);1726 1727 AddCXXSynthetic(cpp_category_sp, GenericSmartPointerSyntheticFrontEndCreator,1728 "std::shared_ptr synthetic children",1729 "^std::shared_ptr<.+>(( )?&)?$", stl_synth_flags, true);1730 AddCXXSynthetic(cpp_category_sp, GenericSmartPointerSyntheticFrontEndCreator,1731 "std::weak_ptr synthetic children",1732 "^std::weak_ptr<.+>(( )?&)?$", stl_synth_flags, true);1733 AddCXXSynthetic(cpp_category_sp, GenericUniquePtrSyntheticFrontEndCreator,1734 "std::unique_ptr synthetic children",1735 "^std::unique_ptr<.+>(( )?&)?$", stl_synth_flags, true);1736 AddCXXSynthetic(cpp_category_sp, GenericTupleSyntheticFrontEndCreator,1737 "std::tuple synthetic children", "^std::tuple<.*>(( )?&)?$",1738 stl_synth_flags, true);1739 AddCXXSynthetic(cpp_category_sp, GenericListSyntheticFrontEndCreator,1740 "std::list synthetic children", "^std::list<.+>(( )?&)?$",1741 stl_synth_flags, true);1742 AddCXXSynthetic(cpp_category_sp, GenericForwardListSyntheticFrontEndCreator,1743 "std::forward_list synthetic children",1744 "^std::forward_list<.+>(( )?&)?$", stl_synth_flags, true);1745 AddCXXSynthetic(cpp_category_sp, GenericVariantSyntheticFrontEndCreator,1746 "std::variant synthetic children", "^std::variant<.*>$",1747 stl_synth_flags, true);1748 AddCXXSynthetic(cpp_category_sp, GenericUnorderedSyntheticFrontEndCreator,1749 "std::unordered container synthetic children",1750 "^std::unordered_(multi)?(map|set)<.+> ?>$", stl_synth_flags,1751 true);1752 1753 SyntheticChildren::Flags stl_deref_flags = stl_synth_flags;1754 stl_deref_flags.SetFrontEndWantsDereference();1755 AddCXXSynthetic(cpp_category_sp, GenericOptionalSyntheticFrontEndCreator,1756 "std::optional synthetic children",1757 "^std::optional<.+>(( )?&)?$", stl_deref_flags, true);1758 AddCXXSynthetic(cpp_category_sp, GenericDequeSyntheticFrontEndCreator,1759 "std::deque container synthetic children",1760 "^std::deque<.+>(( )?&)?$", stl_deref_flags, true);1761 1762 AddCXXSynthetic(cpp_category_sp, GenericMapLikeSyntheticFrontEndCreator,1763 "std::(multi)?map/set synthetic children",1764 "^std::(multi)?(map|set)<.+>(( )?&)?$", stl_synth_flags,1765 true);1766 1767 AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,1768 "std::initializer_list summary provider",1769 "^std::initializer_list<.+>$", stl_summary_flags, true);1770 AddCXXSummary(cpp_category_sp, GenericSmartPointerSummaryProvider,1771 "MSVC STL/libstdc++ std::shared_ptr summary provider",1772 "^std::shared_ptr<.+>(( )?&)?$", stl_summary_flags, true);1773 AddCXXSummary(cpp_category_sp, GenericSmartPointerSummaryProvider,1774 "MSVC STL/libstdc++ std::weak_ptr summary provider",1775 "^std::weak_ptr<.+>(( )?&)?$", stl_summary_flags, true);1776 AddCXXSummary(cpp_category_sp, GenericUniquePtrSummaryProvider,1777 "MSVC STL/libstdc++ std::unique_ptr summary provider",1778 "^std::unique_ptr<.+>(( )?&)?$", stl_summary_flags, true);1779 AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,1780 "MSVC STL/libstdc++ std::tuple summary provider",1781 "^std::tuple<.*>(( )?&)?$", stl_summary_flags, true);1782 AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,1783 "MSVC/libstdc++ std::vector summary provider",1784 "^std::vector<.+>(( )?&)?$", stl_summary_flags, true);1785 AddCXXSynthetic(cpp_category_sp, GenericVectorSyntheticFrontEndCreator,1786 "MSVC/libstdc++ std::vector synthetic provider",1787 "^std::vector<.+>(( )?&)?$", stl_synth_flags, true);1788 AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,1789 "MSVC STL/libstdc++ std::list summary provider",1790 "^std::list<.+>(( )?&)?$", stl_summary_flags, true);1791 cpp_category_sp->AddTypeSummary(1792 "^std::forward_list<.+>(( )?&)?$", eFormatterMatchRegex,1793 TypeSummaryImplSP(new ScriptSummaryFormat(1794 stl_summary_flags,1795 "lldb.formatters.cpp.gnu_libstdcpp.ForwardListSummaryProvider")));1796 AddCXXSummary(cpp_category_sp, GenericOptionalSummaryProvider,1797 "MSVC STL/libstd++ std::optional summary provider",1798 "^std::optional<.+>(( )?&)?$", stl_summary_flags, true);1799 AddCXXSummary(cpp_category_sp, GenericVariantSummaryProvider,1800 "MSVC STL/libstdc++ std::variant summary provider",1801 "^std::variant<.*>$", stl_summary_flags, true);1802 AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,1803 "MSVC STL/libstdc++ std unordered container summary provider",1804 "^std::unordered_(multi)?(map|set)<.+> ?>$", stl_summary_flags,1805 true);1806 AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,1807 "MSVC STL/libstdc++ std::(multi)?map/set summary provider",1808 "^std::(multi)?(map|set)<.+>(( )?&)?$", stl_summary_flags,1809 true);1810 AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,1811 "MSVC STL/libstd++ std::deque summary provider",1812 "^std::deque<.+>(( )?&)?$", stl_summary_flags, true);1813}1814 1815static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {1816 if (!cpp_category_sp)1817 return;1818 1819 TypeSummaryImpl::Flags stl_summary_flags;1820 stl_summary_flags.SetCascades(true)1821 .SetSkipPointers(false)1822 .SetSkipReferences(false)1823 .SetDontShowChildren(true)1824 .SetDontShowValue(false)1825 .SetShowMembersOneLiner(false)1826 .SetHideItemNames(false);1827 SyntheticChildren::Flags stl_synth_flags;1828 stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(1829 false);1830 1831 using StringElementType = StringPrinter::StringElementType;1832 1833 RegisterStdStringSummaryProvider(1834 cpp_category_sp, "std::u8string", "char8_t",1835 std::make_shared<CXXFunctionSummaryFormat>(1836 stl_summary_flags,1837 MsvcStlStringSummaryProvider<StringElementType::UTF8>,1838 "MSVC STL std::u8string summary provider"));1839 RegisterStdStringSummaryProvider(1840 cpp_category_sp, "std::u16string", "char16_t",1841 std::make_shared<CXXFunctionSummaryFormat>(1842 stl_summary_flags,1843 MsvcStlStringSummaryProvider<StringElementType::UTF16>,1844 "MSVC STL std::u16string summary provider"));1845 RegisterStdStringSummaryProvider(1846 cpp_category_sp, "std::u32string", "char32_t",1847 std::make_shared<CXXFunctionSummaryFormat>(1848 stl_summary_flags,1849 MsvcStlStringSummaryProvider<StringElementType::UTF32>,1850 "MSVC STL std::u32string summary provider"));1851 1852 RegisterStdStringViewSummaryProvider(1853 cpp_category_sp, "std::string_view", "char",1854 std::make_shared<CXXFunctionSummaryFormat>(1855 stl_summary_flags,1856 MsvcStlStringViewSummaryProvider<StringElementType::ASCII>,1857 "MSVC STL std::string_view summary provider"));1858 RegisterStdStringViewSummaryProvider(1859 cpp_category_sp, "std::u8string_view", "char8_t",1860 std::make_shared<CXXFunctionSummaryFormat>(1861 stl_summary_flags,1862 MsvcStlStringViewSummaryProvider<StringElementType::UTF8>,1863 "MSVC STL std::u8string_view summary provider"));1864 RegisterStdStringViewSummaryProvider(1865 cpp_category_sp, "std::u16string_view", "char16_t",1866 std::make_shared<CXXFunctionSummaryFormat>(1867 stl_summary_flags,1868 MsvcStlStringViewSummaryProvider<StringElementType::UTF16>,1869 "MSVC STL std::u16string_view summary provider"));1870 RegisterStdStringViewSummaryProvider(1871 cpp_category_sp, "std::u32string_view", "char32_t",1872 std::make_shared<CXXFunctionSummaryFormat>(1873 stl_summary_flags,1874 MsvcStlStringViewSummaryProvider<StringElementType::UTF32>,1875 "MSVC STL std::u32string_view summary provider"));1876 RegisterStdStringViewSummaryProvider(1877 cpp_category_sp, "std::wstring_view", "wchar_t",1878 std::make_shared<CXXFunctionSummaryFormat>(1879 stl_summary_flags, MsvcStlWStringViewSummaryProvider,1880 "MSVC STL std::wstring_view summary provider"));1881 1882 stl_summary_flags.SetDontShowChildren(false);1883 1884 AddCXXSynthetic(cpp_category_sp, MsvcStlAtomicSyntheticFrontEndCreator,1885 "MSVC STL std::atomic synthetic children",1886 "^std::atomic<.+>$", stl_synth_flags, true);1887 1888 AddCXXSummary(cpp_category_sp, MsvcStlAtomicSummaryProvider,1889 "MSVC STL std::atomic summary provider", "^std::atomic<.+>$",1890 stl_summary_flags, true);1891 AddCXXSynthetic(cpp_category_sp, MsvcStlTreeIterSyntheticFrontEndCreator,1892 "MSVC STL tree iterator synthetic children",1893 "^std::_Tree(_const)?_iterator<.+>(( )?&)?$", stl_synth_flags,1894 true);1895 AddCXXSummary(cpp_category_sp, MsvcStlTreeIterSummaryProvider,1896 "MSVC STL tree iterator summary",1897 "^std::_Tree(_const)?_iterator<.+>(( )?&)?$", stl_summary_flags,1898 true);1899}1900 1901static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {1902 if (!cpp_category_sp)1903 return;1904 1905 TypeSummaryImpl::Flags string_flags;1906 string_flags.SetCascades(true)1907 .SetSkipPointers(true)1908 .SetSkipReferences(false)1909 .SetDontShowChildren(true)1910 .SetDontShowValue(false)1911 .SetShowMembersOneLiner(false)1912 .SetHideItemNames(false);1913 1914 TypeSummaryImpl::Flags string_array_flags;1915 string_array_flags.SetCascades(true)1916 .SetSkipPointers(true)1917 .SetSkipReferences(false)1918 .SetDontShowChildren(true)1919 .SetDontShowValue(true)1920 .SetShowMembersOneLiner(false)1921 .SetHideItemNames(false);1922 1923 AddCXXSummary(cpp_category_sp,1924 lldb_private::formatters::Char8StringSummaryProvider,1925 "char8_t * summary provider", "char8_t *", string_flags);1926 AddCXXSummary(cpp_category_sp,1927 lldb_private::formatters::Char8StringSummaryProvider,1928 "char8_t [] summary provider", "char8_t ?\\[[0-9]+\\]",1929 string_array_flags, true);1930 1931 AddCXXSummary(cpp_category_sp,1932 lldb_private::formatters::Char16StringSummaryProvider,1933 "char16_t * summary provider", "char16_t *", string_flags);1934 AddCXXSummary(cpp_category_sp,1935 lldb_private::formatters::Char16StringSummaryProvider,1936 "char16_t [] summary provider", "char16_t ?\\[[0-9]+\\]",1937 string_array_flags, true);1938 1939 AddCXXSummary(cpp_category_sp,1940 lldb_private::formatters::Char32StringSummaryProvider,1941 "char32_t * summary provider", "char32_t *", string_flags);1942 AddCXXSummary(cpp_category_sp,1943 lldb_private::formatters::Char32StringSummaryProvider,1944 "char32_t [] summary provider", "char32_t ?\\[[0-9]+\\]",1945 string_array_flags, true);1946 1947 AddCXXSummary(cpp_category_sp,1948 lldb_private::formatters::WCharStringSummaryProvider,1949 "wchar_t * summary provider", "wchar_t *", string_flags);1950 AddCXXSummary(cpp_category_sp,1951 lldb_private::formatters::WCharStringSummaryProvider,1952 "wchar_t * summary provider", "wchar_t ?\\[[0-9]+\\]",1953 string_array_flags, true);1954 1955 AddCXXSummary(cpp_category_sp,1956 lldb_private::formatters::Char16StringSummaryProvider,1957 "unichar * summary provider", "unichar *", string_flags);1958 1959 TypeSummaryImpl::Flags widechar_flags;1960 widechar_flags.SetDontShowValue(true)1961 .SetSkipPointers(true)1962 .SetSkipReferences(false)1963 .SetCascades(true)1964 .SetDontShowChildren(true)1965 .SetHideItemNames(true)1966 .SetShowMembersOneLiner(false);1967 1968 AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char8SummaryProvider,1969 "char8_t summary provider", "char8_t", widechar_flags);1970 AddCXXSummary(cpp_category_sp,1971 lldb_private::formatters::Char16SummaryProvider,1972 "char16_t summary provider", "char16_t", widechar_flags);1973 AddCXXSummary(cpp_category_sp,1974 lldb_private::formatters::Char32SummaryProvider,1975 "char32_t summary provider", "char32_t", widechar_flags);1976 AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharSummaryProvider,1977 "wchar_t summary provider", "wchar_t", widechar_flags);1978 1979 AddCXXSummary(cpp_category_sp,1980 lldb_private::formatters::Char16SummaryProvider,1981 "unichar summary provider", "unichar", widechar_flags);1982}1983 1984std::unique_ptr<Language::TypeScavenger> CPlusPlusLanguage::GetTypeScavenger() {1985 class CPlusPlusTypeScavenger : public Language::ImageListTypeScavenger {1986 public:1987 CompilerType AdjustForInclusion(CompilerType &candidate) override {1988 LanguageType lang_type(candidate.GetMinimumLanguage());1989 if (!Language::LanguageIsC(lang_type) &&1990 !Language::LanguageIsCPlusPlus(lang_type))1991 return CompilerType();1992 if (candidate.IsTypedefType())1993 return candidate.GetTypedefedType();1994 return candidate;1995 }1996 };1997 1998 return std::unique_ptr<TypeScavenger>(new CPlusPlusTypeScavenger());1999}2000 2001lldb::TypeCategoryImplSP CPlusPlusLanguage::GetFormatters() {2002 static llvm::once_flag g_initialize;2003 static TypeCategoryImplSP g_category;2004 2005 llvm::call_once(g_initialize, [this]() -> void {2006 DataVisualization::Categories::GetCategory(ConstString(GetPluginName()),2007 g_category);2008 if (g_category) {2009 // NOTE: the libstdcpp formatters are loaded after libcxx formatters2010 // because we don't want to the libcxx formatters to match the potential2011 // `__debug` inline namespace that libstdcpp may use.2012 // LLDB prioritizes the last loaded matching formatter.2013 LoadLibCxxFormatters(g_category);2014 LoadLibStdcppFormatters(g_category);2015 LoadMsvcStlFormatters(g_category);2016 LoadCommonStlFormatters(g_category);2017 LoadSystemFormatters(g_category);2018 }2019 });2020 return g_category;2021}2022 2023HardcodedFormatters::HardcodedSummaryFinder2024CPlusPlusLanguage::GetHardcodedSummaries() {2025 static llvm::once_flag g_initialize;2026 static ConstString g_vectortypes("VectorTypes");2027 static HardcodedFormatters::HardcodedSummaryFinder g_formatters;2028 2029 llvm::call_once(g_initialize, []() -> void {2030 g_formatters.push_back(2031 [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,2032 FormatManager &) -> TypeSummaryImpl::SharedPointer {2033 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(2034 new CXXFunctionSummaryFormat(2035 TypeSummaryImpl::Flags(),2036 lldb_private::formatters::CXXFunctionPointerSummaryProvider,2037 "Function pointer summary provider"));2038 if (CompilerType CT = valobj.GetCompilerType();2039 CT.IsFunctionPointerType() || CT.IsMemberFunctionPointerType() ||2040 valobj.GetValueType() == lldb::eValueTypeVTableEntry) {2041 return formatter_sp;2042 }2043 return nullptr;2044 });2045 g_formatters.push_back(2046 [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,2047 FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer {2048 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(2049 new CXXFunctionSummaryFormat(2050 TypeSummaryImpl::Flags()2051 .SetCascades(true)2052 .SetDontShowChildren(true)2053 .SetHideItemNames(true)2054 .SetShowMembersOneLiner(true)2055 .SetSkipPointers(true)2056 .SetSkipReferences(false),2057 lldb_private::formatters::VectorTypeSummaryProvider,2058 "vector_type pointer summary provider"));2059 if (valobj.GetCompilerType().IsVectorType()) {2060 if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())2061 return formatter_sp;2062 }2063 return nullptr;2064 });2065 g_formatters.push_back(2066 [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,2067 FormatManager &fmt_mgr) -> TypeSummaryImpl::SharedPointer {2068 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(2069 new CXXFunctionSummaryFormat(2070 TypeSummaryImpl::Flags()2071 .SetCascades(true)2072 .SetDontShowChildren(true)2073 .SetHideItemNames(true)2074 .SetShowMembersOneLiner(true)2075 .SetSkipPointers(true)2076 .SetSkipReferences(false),2077 lldb_private::formatters::BlockPointerSummaryProvider,2078 "block pointer summary provider"));2079 if (valobj.GetCompilerType().IsBlockPointerType()) {2080 return formatter_sp;2081 }2082 return nullptr;2083 });2084 });2085 2086 return g_formatters;2087}2088 2089HardcodedFormatters::HardcodedSyntheticFinder2090CPlusPlusLanguage::GetHardcodedSynthetics() {2091 static llvm::once_flag g_initialize;2092 static ConstString g_vectortypes("VectorTypes");2093 static HardcodedFormatters::HardcodedSyntheticFinder g_formatters;2094 2095 llvm::call_once(g_initialize, []() -> void {2096 g_formatters.push_back([](lldb_private::ValueObject &valobj,2097 lldb::DynamicValueType, FormatManager &fmt_mgr)2098 -> SyntheticChildren::SharedPointer {2099 static CXXSyntheticChildren::SharedPointer formatter_sp(2100 new CXXSyntheticChildren(2101 SyntheticChildren::Flags()2102 .SetCascades(true)2103 .SetSkipPointers(true)2104 .SetSkipReferences(true)2105 .SetNonCacheable(true),2106 "vector_type synthetic children",2107 lldb_private::formatters::VectorTypeSyntheticFrontEndCreator));2108 if (valobj.GetCompilerType().IsVectorType()) {2109 if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())2110 return formatter_sp;2111 }2112 return nullptr;2113 });2114 g_formatters.push_back([](lldb_private::ValueObject &valobj,2115 lldb::DynamicValueType, FormatManager &fmt_mgr)2116 -> SyntheticChildren::SharedPointer {2117 static CXXSyntheticChildren::SharedPointer formatter_sp(2118 new CXXSyntheticChildren(2119 SyntheticChildren::Flags()2120 .SetCascades(true)2121 .SetSkipPointers(true)2122 .SetSkipReferences(true)2123 .SetNonCacheable(true),2124 "block pointer synthetic children",2125 lldb_private::formatters::BlockPointerSyntheticFrontEndCreator));2126 if (valobj.GetCompilerType().IsBlockPointerType()) {2127 return formatter_sp;2128 }2129 return nullptr;2130 });2131 });2132 2133 return g_formatters;2134}2135 2136bool CPlusPlusLanguage::IsNilReference(ValueObject &valobj) {2137 if (!Language::LanguageIsCPlusPlus(valobj.GetObjectRuntimeLanguage()) ||2138 !valobj.IsPointerType())2139 return false;2140 bool canReadValue = true;2141 bool isZero = valobj.GetValueAsUnsigned(0, &canReadValue) == 0;2142 return canReadValue && isZero;2143}2144 2145bool CPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const {2146 const auto suffixes = {".cpp", ".cxx", ".c++", ".cc", ".c",2147 ".h", ".hh", ".hpp", ".hxx", ".h++"};2148 for (auto suffix : suffixes) {2149 if (file_path.ends_with_insensitive(suffix))2150 return true;2151 }2152 2153 // Check if we're in a STL path (where the files usually have no extension2154 // that we could check for.2155 return file_path.contains("/usr/include/c++/");2156}2157 2158static VariableListSP GetFunctionVariableList(const SymbolContext &sc) {2159 assert(sc.function);2160 2161 if (sc.block)2162 if (Block *inline_block = sc.block->GetContainingInlinedBlock())2163 return inline_block->GetBlockVariableList(true);2164 2165 return sc.function->GetBlock(true).GetBlockVariableList(true);2166}2167 2168static bool PrintFunctionNameWithArgs(Stream &s,2169 const ExecutionContext *exe_ctx,2170 const SymbolContext &sc) {2171 assert(sc.function);2172 2173 ExecutionContextScope *exe_scope =2174 exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;2175 2176 const char *cstr = sc.GetPossiblyInlinedFunctionName()2177 .GetName(Mangled::NamePreference::ePreferDemangled)2178 .AsCString();2179 if (!cstr)2180 return false;2181 2182 VariableList args;2183 if (auto variable_list_sp = GetFunctionVariableList(sc))2184 variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument,2185 args);2186 2187 if (args.GetSize() > 0)2188 return PrettyPrintFunctionNameWithArgs(s, cstr, exe_scope, args);2189 2190 // FIXME: can we just unconditionally call PrettyPrintFunctionNameWithArgs?2191 // It should be able to handle the "no arguments" case.2192 s.PutCString(cstr);2193 2194 return true;2195}2196 2197bool CPlusPlusLanguage::GetFunctionDisplayName(2198 const SymbolContext &sc, const ExecutionContext *exe_ctx,2199 FunctionNameRepresentation representation, Stream &s) {2200 switch (representation) {2201 case FunctionNameRepresentation::eNameWithArgs: {2202 // Print the function name with arguments in it2203 if (sc.function)2204 return PrintFunctionNameWithArgs(s, exe_ctx, sc);2205 2206 if (!sc.symbol)2207 return false;2208 2209 const char *cstr = sc.symbol->GetName().AsCString(nullptr);2210 if (!cstr)2211 return false;2212 2213 s.PutCString(cstr);2214 2215 return true;2216 }2217 case FunctionNameRepresentation::eNameWithNoArgs:2218 case FunctionNameRepresentation::eName:2219 return false;2220 }2221 llvm_unreachable("Fully covered switch above");2222}2223 2224bool CPlusPlusLanguage::HandleFrameFormatVariable(2225 const SymbolContext &sc, const ExecutionContext *exe_ctx,2226 FormatEntity::Entry::Type type, Stream &s) {2227 switch (type) {2228 case FormatEntity::Entry::Type::FunctionScope: {2229 auto scope_or_err = ::GetDemangledScope(sc);2230 if (!scope_or_err) {2231 LLDB_LOG_ERROR(2232 GetLog(LLDBLog::Language), scope_or_err.takeError(),2233 "Failed to handle ${{function.scope}} frame-format variable: {0}");2234 return false;2235 }2236 2237 s << *scope_or_err;2238 2239 return true;2240 }2241 2242 case FormatEntity::Entry::Type::FunctionBasename: {2243 auto name_or_err = ::GetDemangledBasename(sc);2244 if (!name_or_err) {2245 LLDB_LOG_ERROR(2246 GetLog(LLDBLog::Language), name_or_err.takeError(),2247 "Failed to handle ${{function.basename}} frame-format variable: {0}");2248 return false;2249 }2250 2251 s << *name_or_err;2252 2253 return true;2254 }2255 2256 case FormatEntity::Entry::Type::FunctionTemplateArguments: {2257 auto template_args_or_err = ::GetDemangledTemplateArguments(sc);2258 if (!template_args_or_err) {2259 LLDB_LOG_ERROR(GetLog(LLDBLog::Language),2260 template_args_or_err.takeError(),2261 "Failed to handle ${{function.template-arguments}} "2262 "frame-format variable: {0}");2263 return false;2264 }2265 2266 s << *template_args_or_err;2267 2268 return true;2269 }2270 2271 case FormatEntity::Entry::Type::FunctionFormattedArguments: {2272 // This ensures we print the arguments even when no debug-info is available.2273 //2274 // FIXME: we should have a Entry::Type::FunctionArguments and2275 // use it in the plugin.cplusplus.display.function-name-format2276 // once we have a "fallback operator" in the frame-format language.2277 if (!sc.function && sc.symbol)2278 return PrintDemangledArgumentList(s, sc);2279 2280 VariableList args;2281 if (auto variable_list_sp = GetFunctionVariableList(sc))2282 variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument,2283 args);2284 2285 ExecutionContextScope *exe_scope =2286 exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;2287 2288 s << '(';2289 FormatEntity::PrettyPrintFunctionArguments(s, args, exe_scope);2290 s << ')';2291 2292 return true;2293 }2294 case FormatEntity::Entry::Type::FunctionReturnRight: {2295 auto return_rhs_or_err = ::GetDemangledReturnTypeRHS(sc);2296 if (!return_rhs_or_err) {2297 LLDB_LOG_ERROR(GetLog(LLDBLog::Language), return_rhs_or_err.takeError(),2298 "Failed to handle ${{function.return-right}} frame-format "2299 "variable: {0}");2300 return false;2301 }2302 2303 s << *return_rhs_or_err;2304 2305 return true;2306 }2307 case FormatEntity::Entry::Type::FunctionReturnLeft: {2308 auto return_lhs_or_err = ::GetDemangledReturnTypeLHS(sc);2309 if (!return_lhs_or_err) {2310 LLDB_LOG_ERROR(GetLog(LLDBLog::Language), return_lhs_or_err.takeError(),2311 "Failed to handle ${{function.return-left}} frame-format "2312 "variable: {0}");2313 return false;2314 }2315 2316 s << *return_lhs_or_err;2317 2318 return true;2319 }2320 case FormatEntity::Entry::Type::FunctionQualifiers: {2321 auto quals_or_err = ::GetDemangledFunctionQualifiers(sc);2322 if (!quals_or_err) {2323 LLDB_LOG_ERROR(GetLog(LLDBLog::Language), quals_or_err.takeError(),2324 "Failed to handle ${{function.qualifiers}} frame-format "2325 "variable: {0}");2326 return false;2327 }2328 2329 s << *quals_or_err;2330 2331 return true;2332 }2333 case FormatEntity::Entry::Type::FunctionSuffix: {2334 auto suffix_or_err = ::GetDemangledFunctionSuffix(sc);2335 if (!suffix_or_err) {2336 LLDB_LOG_ERROR(2337 GetLog(LLDBLog::Language), suffix_or_err.takeError(),2338 "Failed to handle ${{function.suffix}} frame-format variable: {0}");2339 return false;2340 }2341 2342 s << *suffix_or_err;2343 2344 return true;2345 }2346 default:2347 return false;2348 }2349}2350 2351namespace {2352class NodeAllocator {2353 llvm::BumpPtrAllocator Alloc;2354 2355public:2356 void reset() { Alloc.Reset(); }2357 2358 template <typename T, typename... Args> T *makeNode(Args &&...args) {2359 return new (Alloc.Allocate(sizeof(T), alignof(T)))2360 T(std::forward<Args>(args)...);2361 }2362 2363 void *allocateNodeArray(size_t sz) {2364 return Alloc.Allocate(sizeof(llvm::itanium_demangle::Node *) * sz,2365 alignof(llvm::itanium_demangle::Node *));2366 }2367};2368 2369template <typename Derived>2370class ManglingSubstitutor2371 : public llvm::itanium_demangle::AbstractManglingParser<Derived,2372 NodeAllocator> {2373 using Base =2374 llvm::itanium_demangle::AbstractManglingParser<Derived, NodeAllocator>;2375 2376public:2377 ManglingSubstitutor() : Base(nullptr, nullptr) {}2378 2379 template <typename... Ts>2380 llvm::Expected<ConstString> substitute(llvm::StringRef Mangled,2381 Ts &&...Vals) {2382 this->getDerived().reset(Mangled, std::forward<Ts>(Vals)...);2383 return substituteImpl(Mangled);2384 }2385 2386protected:2387 void reset(llvm::StringRef Mangled) {2388 Base::reset(Mangled.begin(), Mangled.end());2389 Written = Mangled.begin();2390 Result.clear();2391 Substituted = false;2392 }2393 2394 llvm::Expected<ConstString> substituteImpl(llvm::StringRef Mangled) {2395 if (this->parse() == nullptr)2396 return llvm::createStringError(2397 llvm::formatv("Failed to substitute mangling in '{0}'", Mangled));2398 2399 if (!Substituted)2400 return ConstString();2401 2402 // Append any trailing unmodified input.2403 appendUnchangedInput();2404 return ConstString(Result);2405 }2406 2407 void trySubstitute(llvm::StringRef From, llvm::StringRef To) {2408 if (!llvm::StringRef(currentParserPos(), this->numLeft()).starts_with(From))2409 return;2410 2411 // We found a match. Append unmodified input up to this point.2412 appendUnchangedInput();2413 2414 // And then perform the replacement.2415 Result += To;2416 Written += From.size();2417 Substituted = true;2418 }2419 2420private:2421 /// Input character until which we have constructed the respective output2422 /// already.2423 const char *Written = "";2424 2425 llvm::SmallString<128> Result;2426 2427 /// Whether we have performed any substitutions.2428 bool Substituted = false;2429 2430 const char *currentParserPos() const { return this->First; }2431 2432 void appendUnchangedInput() {2433 Result +=2434 llvm::StringRef(Written, std::distance(Written, currentParserPos()));2435 Written = currentParserPos();2436 }2437};2438 2439/// Given a mangled function `Mangled`, replace all the primitive function type2440/// arguments of `Search` with type `Replace`.2441class TypeSubstitutor : public ManglingSubstitutor<TypeSubstitutor> {2442 llvm::StringRef Search;2443 llvm::StringRef Replace;2444 2445public:2446 void reset(llvm::StringRef Mangled, llvm::StringRef Search,2447 llvm::StringRef Replace) {2448 ManglingSubstitutor::reset(Mangled);2449 this->Search = Search;2450 this->Replace = Replace;2451 }2452 2453 llvm::itanium_demangle::Node *parseType() {2454 trySubstitute(Search, Replace);2455 return ManglingSubstitutor::parseType();2456 }2457};2458 2459class CtorDtorSubstitutor : public ManglingSubstitutor<CtorDtorSubstitutor> {2460 llvm::StringRef Search;2461 llvm::StringRef Replace;2462 2463public:2464 void reset(llvm::StringRef Mangled, llvm::StringRef Search,2465 llvm::StringRef Replace) {2466 ManglingSubstitutor::reset(Mangled);2467 this->Search = Search;2468 this->Replace = Replace;2469 }2470 2471 void reset(llvm::StringRef Mangled) { ManglingSubstitutor::reset(Mangled); }2472 2473 llvm::itanium_demangle::Node *2474 parseCtorDtorName(llvm::itanium_demangle::Node *&SoFar, NameState *State) {2475 if (!Search.empty() && !Replace.empty()) {2476 trySubstitute(Search, Replace);2477 } else {2478 trySubstitute("D1", "D2");2479 trySubstitute("C1", "C2");2480 }2481 return ManglingSubstitutor::parseCtorDtorName(SoFar, State);2482 }2483};2484} // namespace2485 2486llvm::Expected<ConstString>2487CPlusPlusLanguage::SubstituteType_ItaniumMangle(llvm::StringRef mangled_name,2488 llvm::StringRef subst_from,2489 llvm::StringRef subst_to) {2490 return TypeSubstitutor().substitute(mangled_name, subst_from, subst_to);2491}2492 2493llvm::Expected<ConstString> CPlusPlusLanguage::SubstituteStructor_ItaniumMangle(2494 llvm::StringRef mangled_name, llvm::StringRef subst_from,2495 llvm::StringRef subst_to) {2496 return CtorDtorSubstitutor().substitute(mangled_name, subst_from, subst_to);2497}2498 2499llvm::Expected<ConstString>2500CPlusPlusLanguage::SubstituteStructorAliases_ItaniumMangle(2501 llvm::StringRef mangled_name) {2502 return CtorDtorSubstitutor().substitute(mangled_name);2503}2504 2505#define LLDB_PROPERTIES_language_cplusplus2506#include "LanguageCPlusPlusProperties.inc"2507 2508enum {2509#define LLDB_PROPERTIES_language_cplusplus2510#include "LanguageCPlusPlusPropertiesEnum.inc"2511};2512 2513namespace {2514class PluginProperties : public Properties {2515public:2516 static llvm::StringRef GetSettingName() { return "display"; }2517 2518 PluginProperties() {2519 m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());2520 m_collection_sp->Initialize(g_language_cplusplus_properties);2521 }2522 2523 FormatEntity::Entry GetFunctionNameFormat() const {2524 return GetPropertyAtIndexAs<FormatEntity::Entry>(2525 ePropertyFunctionNameFormat, {});2526 }2527};2528} // namespace2529 2530static PluginProperties &GetGlobalPluginProperties() {2531 static PluginProperties g_settings;2532 return g_settings;2533}2534 2535FormatEntity::Entry CPlusPlusLanguage::GetFunctionNameFormat() const {2536 return GetGlobalPluginProperties().GetFunctionNameFormat();2537}2538 2539void CPlusPlusLanguage::DebuggerInitialize(Debugger &debugger) {2540 if (!PluginManager::GetSettingForCPlusPlusLanguagePlugin(2541 debugger, PluginProperties::GetSettingName())) {2542 PluginManager::CreateSettingForCPlusPlusLanguagePlugin(2543 debugger, GetGlobalPluginProperties().GetValueProperties(),2544 "Properties for the CPlusPlus language plug-in.",2545 /*is_global_property=*/true);2546 }2547}2548