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