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

source code of lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp