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