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 | |
51 | using namespace lldb; |
52 | using namespace lldb_private; |
53 | using namespace lldb_private::formatters; |
54 | |
55 | LLDB_PLUGIN_DEFINE(CPlusPlusLanguage) |
56 | |
57 | void CPlusPlusLanguage::Initialize() { |
58 | PluginManager::RegisterPlugin(name: GetPluginNameStatic(), description: "C++ Language", |
59 | create_callback: CreateInstance, debugger_init_callback: &DebuggerInitialize); |
60 | } |
61 | |
62 | void CPlusPlusLanguage::Terminate() { |
63 | PluginManager::UnregisterPlugin(create_callback: CreateInstance); |
64 | } |
65 | |
66 | std::unique_ptr<Language::MethodName> |
67 | CPlusPlusLanguage::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 | |
74 | std::pair<FunctionNameType, std::optional<ConstString>> |
75 | CPlusPlusLanguage::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 | |
104 | bool CPlusPlusLanguage::SymbolNameFitsToLanguage(Mangled mangled) const { |
105 | const char *mangled_name = mangled.GetMangledName().GetCString(); |
106 | return mangled_name && Mangled::IsMangledName(name: mangled_name); |
107 | } |
108 | |
109 | ConstString 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 | |
140 | Language *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 | |
148 | static 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 | |
177 | static 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 |
208 | static 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 | |
239 | static std::optional<llvm::StringRef> |
240 | GetDemangledBasename(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 | |
261 | static std::optional<llvm::StringRef> |
262 | GetDemangledTemplateArguments(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 | |
286 | static std::optional<llvm::StringRef> |
287 | GetDemangledReturnTypeLHS(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 | |
310 | static std::optional<llvm::StringRef> |
311 | GetDemangledFunctionQualifiers(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 | |
335 | static std::optional<llvm::StringRef> |
336 | GetDemangledReturnTypeRHS(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 | |
360 | static std::optional<llvm::StringRef> |
361 | GetDemangledScope(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. |
386 | static std::optional<llvm::StringRef> |
387 | GetDemangledFunctionSuffix(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 | |
408 | static 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 | |
436 | bool 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 | |
479 | void 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 | |
507 | llvm::StringRef |
508 | CPlusPlusLanguage::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 | |
518 | bool 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 | |
567 | bool CPlusPlusLanguage::DemangledNameContainsPath(llvm::StringRef path, |
568 | ConstString demangled) const { |
569 | CxxMethodName demangled_name(demangled); |
570 | return demangled_name.ContainsPath(path); |
571 | } |
572 | |
573 | bool 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 | |
588 | namespace { |
589 | class NodeAllocator { |
590 | llvm::BumpPtrAllocator Alloc; |
591 | |
592 | public: |
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 | |
606 | template <typename Derived> |
607 | class ManglingSubstitutor |
608 | : public llvm::itanium_demangle::AbstractManglingParser<Derived, |
609 | NodeAllocator> { |
610 | using Base = |
611 | llvm::itanium_demangle::AbstractManglingParser<Derived, NodeAllocator>; |
612 | |
613 | public: |
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 | |
622 | protected: |
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 | |
658 | private: |
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`. |
679 | class TypeSubstitutor : public ManglingSubstitutor<TypeSubstitutor> { |
680 | llvm::StringRef Search; |
681 | llvm::StringRef Replace; |
682 | |
683 | public: |
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 | |
697 | class CtorDtorSubstitutor : public ManglingSubstitutor<CtorDtorSubstitutor> { |
698 | public: |
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 | |
708 | std::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 | |
762 | ConstString 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 | |
812 | static 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 | |
1375 | static 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 | |
1632 | static 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 | |
1715 | std::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 | |
1732 | lldb::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 | |
1752 | HardcodedFormatters::HardcodedSummaryFinder |
1753 | CPlusPlusLanguage::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 | |
1818 | HardcodedFormatters::HardcodedSyntheticFinder |
1819 | CPlusPlusLanguage::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 | |
1865 | bool 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 | |
1874 | bool 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 | |
1887 | static 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 | |
1897 | static 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 | |
1926 | bool 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 | |
1952 | bool 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 | |
2054 | enum { |
2055 | #define LLDB_PROPERTIES_language_cplusplus |
2056 | #include "LanguageCPlusPlusPropertiesEnum.inc" |
2057 | }; |
2058 | |
2059 | namespace { |
2060 | class PluginProperties : public Properties { |
2061 | public: |
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 | |
2076 | static PluginProperties &GetGlobalPluginProperties() { |
2077 | static PluginProperties g_settings; |
2078 | return g_settings; |
2079 | } |
2080 | |
2081 | FormatEntity::Entry CPlusPlusLanguage::GetFunctionNameFormat() const { |
2082 | return GetGlobalPluginProperties().GetFunctionNameFormat(); |
2083 | } |
2084 | |
2085 | void 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 |
Definitions
- Initialize
- Terminate
- GetMethodName
- GetFunctionNameInfo
- SymbolNameFitsToLanguage
- GetDemangledFunctionNameWithoutArguments
- CreateInstance
- ReverseFindMatchingChars
- IsTrivialBasename
- PrettyPrintFunctionNameWithArgs
- GetDemangledBasename
- GetDemangledTemplateArguments
- GetDemangledReturnTypeLHS
- GetDemangledFunctionQualifiers
- GetDemangledReturnTypeRHS
- GetDemangledScope
- GetDemangledFunctionSuffix
- PrintDemangledArgumentList
- TrySimplifiedParse
- Parse
- GetBasenameNoTemplateParameters
- ContainsPath
- DemangledNameContainsPath
- ExtractContextAndIdentifier
- NodeAllocator
- reset
- makeNode
- allocateNodeArray
- ManglingSubstitutor
- ManglingSubstitutor
- substitute
- reset
- substituteImpl
- trySubstitute
- currentParserPos
- appendUnchangedInput
- TypeSubstitutor
- reset
- parseType
- CtorDtorSubstitutor
- parseCtorDtorName
- GenerateAlternateFunctionManglings
- FindBestAlternateFunctionMangledName
- LoadLibCxxFormatters
- LoadLibStdcppFormatters
- LoadSystemFormatters
- GetTypeScavenger
- GetFormatters
- GetHardcodedSummaries
- GetHardcodedSynthetics
- IsNilReference
- IsSourceFile
- GetFunctionVariableList
- PrintFunctionNameWithArgs
- GetFunctionDisplayName
- HandleFrameFormatVariable
- PluginProperties
- GetSettingName
- PluginProperties
- GetFunctionNameFormat
- GetGlobalPluginProperties
- GetFunctionNameFormat
Improve your Profiling and Debugging skills
Find out more