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