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