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