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

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

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