ValueObjectPrinter.cpp revision 296417
1//===-- ValueObjectPrinter.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 "lldb/DataFormatters/ValueObjectPrinter.h" 11 12// C Includes 13// C++ Includes 14// Other libraries and framework includes 15// Project includes 16#include "lldb/Core/Stream.h" 17#include "lldb/Core/ValueObject.h" 18#include "lldb/DataFormatters/DataVisualization.h" 19#include "lldb/Interpreter/CommandInterpreter.h" 20#include "lldb/Target/Language.h" 21#include "lldb/Target/Target.h" 22 23using namespace lldb; 24using namespace lldb_private; 25 26ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, 27 Stream* s) 28{ 29 if (valobj) 30 { 31 DumpValueObjectOptions options(*valobj); 32 Init (valobj,s,options,m_options.m_max_ptr_depth,0, nullptr); 33 } 34 else 35 { 36 DumpValueObjectOptions options; 37 Init (valobj,s,options,m_options.m_max_ptr_depth,0, nullptr); 38 } 39} 40 41ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, 42 Stream* s, 43 const DumpValueObjectOptions& options) 44{ 45 Init(valobj,s,options,m_options.m_max_ptr_depth,0, nullptr); 46} 47 48ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, 49 Stream* s, 50 const DumpValueObjectOptions& options, 51 const DumpValueObjectOptions::PointerDepth& ptr_depth, 52 uint32_t curr_depth, 53 InstancePointersSetSP printed_instance_pointers) 54{ 55 Init(valobj,s,options,ptr_depth,curr_depth, printed_instance_pointers); 56} 57 58void 59ValueObjectPrinter::Init (ValueObject* valobj, 60 Stream* s, 61 const DumpValueObjectOptions& options, 62 const DumpValueObjectOptions::PointerDepth& ptr_depth, 63 uint32_t curr_depth, 64 InstancePointersSetSP printed_instance_pointers) 65{ 66 m_orig_valobj = valobj; 67 m_valobj = nullptr; 68 m_stream = s; 69 m_options = options; 70 m_ptr_depth = ptr_depth; 71 m_curr_depth = curr_depth; 72 assert (m_orig_valobj && "cannot print a NULL ValueObject"); 73 assert (m_stream && "cannot print to a NULL Stream"); 74 m_should_print = eLazyBoolCalculate; 75 m_is_nil = eLazyBoolCalculate; 76 m_is_uninit = eLazyBoolCalculate; 77 m_is_ptr = eLazyBoolCalculate; 78 m_is_ref = eLazyBoolCalculate; 79 m_is_aggregate = eLazyBoolCalculate; 80 m_is_instance_ptr = eLazyBoolCalculate; 81 m_summary_formatter = {nullptr,false}; 82 m_value.assign(""); 83 m_summary.assign(""); 84 m_error.assign(""); 85 m_val_summary_ok = false; 86 m_printed_instance_pointers = printed_instance_pointers ? printed_instance_pointers : InstancePointersSetSP(new InstancePointersSet()); 87} 88 89bool 90ValueObjectPrinter::PrintValueObject () 91{ 92 if (!GetMostSpecializedValue () || m_valobj == nullptr) 93 return false; 94 95 if (ShouldPrintValueObject()) 96 { 97 PrintValidationMarkerIfNeeded(); 98 99 PrintLocationIfNeeded(); 100 m_stream->Indent(); 101 102 PrintDecl(); 103 } 104 105 bool value_printed = false; 106 bool summary_printed = false; 107 108 m_val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed); 109 110 if (m_val_summary_ok) 111 PrintChildrenIfNeeded (value_printed, summary_printed); 112 else 113 m_stream->EOL(); 114 115 PrintValidationErrorIfNeeded(); 116 117 return true; 118} 119 120bool 121ValueObjectPrinter::GetMostSpecializedValue () 122{ 123 if (m_valobj) 124 return true; 125 bool update_success = m_orig_valobj->UpdateValueIfNeeded (true); 126 if (!update_success) 127 { 128 m_valobj = m_orig_valobj; 129 } 130 else 131 { 132 if (m_orig_valobj->IsDynamic()) 133 { 134 if (m_options.m_use_dynamic == eNoDynamicValues) 135 { 136 ValueObject *static_value = m_orig_valobj->GetStaticValue().get(); 137 if (static_value) 138 m_valobj = static_value; 139 else 140 m_valobj = m_orig_valobj; 141 } 142 else 143 m_valobj = m_orig_valobj; 144 } 145 else 146 { 147 if (m_options.m_use_dynamic != eNoDynamicValues) 148 { 149 ValueObject *dynamic_value = m_orig_valobj->GetDynamicValue(m_options.m_use_dynamic).get(); 150 if (dynamic_value) 151 m_valobj = dynamic_value; 152 else 153 m_valobj = m_orig_valobj; 154 } 155 else 156 m_valobj = m_orig_valobj; 157 } 158 159 if (m_valobj->IsSynthetic()) 160 { 161 if (m_options.m_use_synthetic == false) 162 { 163 ValueObject *non_synthetic = m_valobj->GetNonSyntheticValue().get(); 164 if (non_synthetic) 165 m_valobj = non_synthetic; 166 } 167 } 168 else 169 { 170 if (m_options.m_use_synthetic == true) 171 { 172 ValueObject *synthetic = m_valobj->GetSyntheticValue().get(); 173 if (synthetic) 174 m_valobj = synthetic; 175 } 176 } 177 } 178 m_compiler_type = m_valobj->GetCompilerType(); 179 m_type_flags = m_compiler_type.GetTypeInfo (); 180 return true; 181} 182 183const char* 184ValueObjectPrinter::GetDescriptionForDisplay () 185{ 186 const char* str = m_valobj->GetObjectDescription(); 187 if (!str) 188 str = m_valobj->GetSummaryAsCString(); 189 if (!str) 190 str = m_valobj->GetValueAsCString(); 191 return str; 192} 193 194const char* 195ValueObjectPrinter::GetRootNameForDisplay (const char* if_fail) 196{ 197 const char *root_valobj_name = m_options.m_root_valobj_name.empty() ? 198 m_valobj->GetName().AsCString() : 199 m_options.m_root_valobj_name.c_str(); 200 return root_valobj_name ? root_valobj_name : if_fail; 201} 202 203bool 204ValueObjectPrinter::ShouldPrintValueObject () 205{ 206 if (m_should_print == eLazyBoolCalculate) 207 m_should_print = (m_options.m_flat_output == false || m_type_flags.Test (eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo; 208 return m_should_print == eLazyBoolYes; 209} 210 211bool 212ValueObjectPrinter::IsNil () 213{ 214 if (m_is_nil == eLazyBoolCalculate) 215 m_is_nil = m_valobj->IsNilReference() ? eLazyBoolYes : eLazyBoolNo; 216 return m_is_nil == eLazyBoolYes; 217} 218 219bool 220ValueObjectPrinter::IsUninitialized () 221{ 222 if (m_is_uninit == eLazyBoolCalculate) 223 m_is_uninit = m_valobj->IsUninitializedReference() ? eLazyBoolYes : eLazyBoolNo; 224 return m_is_uninit == eLazyBoolYes; 225} 226 227bool 228ValueObjectPrinter::IsPtr () 229{ 230 if (m_is_ptr == eLazyBoolCalculate) 231 m_is_ptr = m_type_flags.Test (eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo; 232 return m_is_ptr == eLazyBoolYes; 233} 234 235bool 236ValueObjectPrinter::IsRef () 237{ 238 if (m_is_ref == eLazyBoolCalculate) 239 m_is_ref = m_type_flags.Test (eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo; 240 return m_is_ref == eLazyBoolYes; 241} 242 243bool 244ValueObjectPrinter::IsAggregate () 245{ 246 if (m_is_aggregate == eLazyBoolCalculate) 247 m_is_aggregate = m_type_flags.Test (eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo; 248 return m_is_aggregate == eLazyBoolYes; 249} 250 251bool 252ValueObjectPrinter::IsInstancePointer () 253{ 254 // you need to do this check on the value's clang type 255 if (m_is_instance_ptr == eLazyBoolCalculate) 256 m_is_instance_ptr = (m_valobj->GetValue().GetCompilerType().GetTypeInfo() & eTypeInstanceIsPointer) != 0 ? eLazyBoolYes : eLazyBoolNo; 257 if ((eLazyBoolYes == m_is_instance_ptr) && m_valobj->IsBaseClass()) 258 m_is_instance_ptr = eLazyBoolNo; 259 return m_is_instance_ptr == eLazyBoolYes; 260} 261 262bool 263ValueObjectPrinter::PrintLocationIfNeeded () 264{ 265 if (m_options.m_show_location) 266 { 267 m_stream->Printf("%s: ", m_valobj->GetLocationAsCString()); 268 return true; 269 } 270 return false; 271} 272 273void 274ValueObjectPrinter::PrintDecl () 275{ 276 bool show_type = true; 277 // if we are at the root-level and been asked to hide the root's type, then hide it 278 if (m_curr_depth == 0 && m_options.m_hide_root_type) 279 show_type = false; 280 else 281 // otherwise decide according to the usual rules (asked to show types - always at the root level) 282 show_type = m_options.m_show_types || (m_curr_depth == 0 && !m_options.m_flat_output); 283 284 StreamString typeName; 285 286 // always show the type at the root level if it is invalid 287 if (show_type) 288 { 289 // Some ValueObjects don't have types (like registers sets). Only print 290 // the type if there is one to print 291 ConstString type_name; 292 if (m_compiler_type.IsValid()) 293 { 294 if (m_options.m_use_type_display_name) 295 type_name = m_valobj->GetDisplayTypeName(); 296 else 297 type_name = m_valobj->GetQualifiedTypeName(); 298 } 299 else 300 { 301 // only show an invalid type name if the user explicitly triggered show_type 302 if (m_options.m_show_types) 303 type_name = ConstString("<invalid type>"); 304 else 305 type_name.Clear(); 306 } 307 308 if (type_name) 309 { 310 std::string type_name_str(type_name.GetCString()); 311 if (m_options.m_hide_pointer_value) 312 { 313 for(auto iter = type_name_str.find(" *"); 314 iter != std::string::npos; 315 iter = type_name_str.find(" *")) 316 { 317 type_name_str.erase(iter, 2); 318 } 319 } 320 typeName.Printf("%s", type_name_str.c_str()); 321 } 322 } 323 324 StreamString varName; 325 326 if (m_options.m_flat_output) 327 { 328 // If we are showing types, also qualify the C++ base classes 329 const bool qualify_cxx_base_classes = show_type; 330 if (!m_options.m_hide_name) 331 { 332 m_valobj->GetExpressionPath(varName, qualify_cxx_base_classes); 333 } 334 } 335 else if (!m_options.m_hide_name) 336 { 337 const char *name_cstr = GetRootNameForDisplay(""); 338 varName.Printf ("%s", name_cstr); 339 } 340 341 bool decl_printed = false; 342 if (!m_options.m_decl_printing_helper) 343 { 344 // if the user didn't give us a custom helper, pick one based upon the language, either the one that this printer is bound to, or the preferred one for the ValueObject 345 lldb::LanguageType lang_type = (m_options.m_varformat_language == lldb::eLanguageTypeUnknown) ? m_valobj->GetPreferredDisplayLanguage() : m_options.m_varformat_language; 346 if (Language *lang_plugin = Language::FindPlugin(lang_type)) 347 { 348 m_options.m_decl_printing_helper = lang_plugin->GetDeclPrintingHelper(); 349 } 350 } 351 352 if (m_options.m_decl_printing_helper) 353 { 354 ConstString type_name_cstr(typeName.GetData()); 355 ConstString var_name_cstr(varName.GetData()); 356 357 StreamString dest_stream; 358 if (m_options.m_decl_printing_helper (type_name_cstr, 359 var_name_cstr, 360 m_options, 361 dest_stream)) 362 { 363 decl_printed = true; 364 m_stream->Printf("%s", dest_stream.GetData()); 365 } 366 } 367 368 // if the helper failed, or there is none, do a default thing 369 if (!decl_printed) 370 { 371 if (typeName.GetSize()) 372 m_stream->Printf("(%s) ", typeName.GetData()); 373 if (varName.GetSize()) 374 m_stream->Printf("%s =", varName.GetData()); 375 else if (!m_options.m_hide_name) 376 m_stream->Printf(" ="); 377 } 378} 379 380bool 381ValueObjectPrinter::CheckScopeIfNeeded () 382{ 383 if (m_options.m_scope_already_checked) 384 return true; 385 return m_valobj->IsInScope(); 386} 387 388TypeSummaryImpl* 389ValueObjectPrinter::GetSummaryFormatter (bool null_if_omitted) 390{ 391 if (m_summary_formatter.second == false) 392 { 393 TypeSummaryImpl* entry = m_options.m_summary_sp ? m_options.m_summary_sp.get() : m_valobj->GetSummaryFormat().get(); 394 395 if (m_options.m_omit_summary_depth > 0) 396 entry = NULL; 397 m_summary_formatter.first = entry; 398 m_summary_formatter.second = true; 399 } 400 if (m_options.m_omit_summary_depth > 0 && null_if_omitted) 401 return nullptr; 402 return m_summary_formatter.first; 403} 404 405static bool 406IsPointerValue (const CompilerType &type) 407{ 408 Flags type_flags(type.GetTypeInfo()); 409 if (type_flags.AnySet(eTypeInstanceIsPointer | eTypeIsPointer)) 410 return type_flags.AllClear(eTypeIsBuiltIn); 411 return false; 412} 413 414void 415ValueObjectPrinter::GetValueSummaryError (std::string& value, 416 std::string& summary, 417 std::string& error) 418{ 419 if (m_options.m_format != eFormatDefault && m_options.m_format != m_valobj->GetFormat()) 420 { 421 m_valobj->GetValueAsCString(m_options.m_format, 422 value); 423 } 424 else 425 { 426 const char* val_cstr = m_valobj->GetValueAsCString(); 427 if (val_cstr) 428 value.assign(val_cstr); 429 } 430 const char* err_cstr = m_valobj->GetError().AsCString(); 431 if (err_cstr) 432 error.assign(err_cstr); 433 434 if (ShouldPrintValueObject()) 435 { 436 if (IsNil()) 437 summary.assign("nil"); 438 else if (IsUninitialized()) 439 summary.assign("<uninitialized>"); 440 else if (m_options.m_omit_summary_depth == 0) 441 { 442 TypeSummaryImpl* entry = GetSummaryFormatter(); 443 if (entry) 444 m_valobj->GetSummaryAsCString(entry, summary, m_options.m_varformat_language); 445 else 446 { 447 const char* sum_cstr = m_valobj->GetSummaryAsCString(m_options.m_varformat_language); 448 if (sum_cstr) 449 summary.assign(sum_cstr); 450 } 451 } 452 } 453} 454 455bool 456ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed, 457 bool& summary_printed) 458{ 459 bool error_printed = false; 460 if (ShouldPrintValueObject()) 461 { 462 if (!CheckScopeIfNeeded()) 463 m_error.assign("out of scope"); 464 if (m_error.empty()) 465 { 466 GetValueSummaryError(m_value, m_summary, m_error); 467 } 468 if (m_error.size()) 469 { 470 // we need to support scenarios in which it is actually fine for a value to have no type 471 // but - on the other hand - if we get an error *AND* have no type, we try to get out 472 // gracefully, since most often that combination means "could not resolve a type" 473 // and the default failure mode is quite ugly 474 if (!m_compiler_type.IsValid()) 475 { 476 m_stream->Printf(" <could not resolve type>"); 477 return false; 478 } 479 480 error_printed = true; 481 m_stream->Printf (" <%s>\n", m_error.c_str()); 482 } 483 else 484 { 485 // Make sure we have a value and make sure the summary didn't 486 // specify that the value should not be printed - and do not print 487 // the value if this thing is nil 488 // (but show the value if the user passes a format explicitly) 489 TypeSummaryImpl* entry = GetSummaryFormatter(); 490 if (!IsNil() && !IsUninitialized() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue(m_valobj) || m_options.m_format != eFormatDefault) || m_summary.empty()) && !m_options.m_hide_value) 491 { 492 if (m_options.m_hide_pointer_value && IsPointerValue(m_valobj->GetCompilerType())) {} 493 else 494 { 495 m_stream->Printf(" %s", m_value.c_str()); 496 value_printed = true; 497 } 498 } 499 500 if (m_summary.size()) 501 { 502 m_stream->Printf(" %s", m_summary.c_str()); 503 summary_printed = true; 504 } 505 } 506 } 507 return !error_printed; 508} 509 510bool 511ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed, 512 bool summary_printed) 513{ 514 if (ShouldPrintValueObject()) 515 { 516 // let's avoid the overly verbose no description error for a nil thing 517 if (m_options.m_use_objc && !IsNil() && !IsUninitialized()) 518 { 519 if (!m_options.m_hide_value || !m_options.m_hide_name) 520 m_stream->Printf(" "); 521 const char *object_desc = nullptr; 522 if (value_printed || summary_printed) 523 object_desc = m_valobj->GetObjectDescription(); 524 else 525 object_desc = GetDescriptionForDisplay(); 526 if (object_desc && *object_desc) 527 { 528 m_stream->Printf("%s\n", object_desc); 529 return true; 530 } 531 else if (value_printed == false && summary_printed == false) 532 return true; 533 else 534 return false; 535 } 536 } 537 return true; 538} 539 540bool 541DumpValueObjectOptions::PointerDepth::CanAllowExpansion (bool is_root, 542 TypeSummaryImpl* entry, 543 ValueObject *valobj, 544 const std::string& summary) 545{ 546 switch (m_mode) 547 { 548 case Mode::Always: 549 return (m_count > 0); 550 case Mode::Never: 551 return false; 552 case Mode::Default: 553 if (is_root) 554 m_count = std::min<decltype(m_count)>(m_count,1); 555 return m_count > 0; 556 case Mode::Formatters: 557 if (!entry || entry->DoesPrintChildren(valobj) || summary.empty()) 558 return m_count > 0; 559 return false; 560 } 561 return false; 562} 563 564bool 565DumpValueObjectOptions::PointerDepth::CanAllowExpansion () const 566{ 567 switch (m_mode) 568 { 569 case Mode::Always: 570 case Mode::Default: 571 case Mode::Formatters: 572 return (m_count > 0); 573 case Mode::Never: 574 return false; 575 } 576 return false; 577} 578 579bool 580ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description, 581 DumpValueObjectOptions::PointerDepth& curr_ptr_depth) 582{ 583 const bool is_ref = IsRef (); 584 const bool is_ptr = IsPtr (); 585 const bool is_uninit = IsUninitialized(); 586 587 if (is_uninit) 588 return false; 589 590 TypeSummaryImpl* entry = GetSummaryFormatter(); 591 592 if (m_options.m_use_objc) 593 return false; 594 595 if (is_failed_description || m_curr_depth < m_options.m_max_depth) 596 { 597 // We will show children for all concrete types. We won't show 598 // pointer contents unless a pointer depth has been specified. 599 // We won't reference contents unless the reference is the 600 // root object (depth of zero). 601 602 // Use a new temporary pointer depth in case we override the 603 // current pointer depth below... 604 605 if (is_ptr || is_ref) 606 { 607 // We have a pointer or reference whose value is an address. 608 // Make sure that address is not NULL 609 AddressType ptr_address_type; 610 if (m_valobj->GetPointerValue (&ptr_address_type) == 0) 611 return false; 612 613 const bool is_root_level = m_curr_depth == 0; 614 615 if (is_ref && 616 is_root_level) 617 { 618 // If this is the root object (depth is zero) that we are showing 619 // and it is a reference, and no pointer depth has been supplied 620 // print out what it references. Don't do this at deeper depths 621 // otherwise we can end up with infinite recursion... 622 return true; 623 } 624 625 return curr_ptr_depth.CanAllowExpansion(false, entry, m_valobj, m_summary); 626 } 627 628 return (!entry || entry->DoesPrintChildren(m_valobj) || m_summary.empty()); 629 } 630 return false; 631} 632 633bool 634ValueObjectPrinter::ShouldExpandEmptyAggregates () 635{ 636 TypeSummaryImpl* entry = GetSummaryFormatter(); 637 638 if (!entry) 639 return true; 640 641 return entry->DoesPrintEmptyAggregates(); 642} 643 644ValueObject* 645ValueObjectPrinter::GetValueObjectForChildrenGeneration () 646{ 647 return m_valobj; 648} 649 650void 651ValueObjectPrinter::PrintChildrenPreamble () 652{ 653 if (m_options.m_flat_output) 654 { 655 if (ShouldPrintValueObject()) 656 m_stream->EOL(); 657 } 658 else 659 { 660 if (ShouldPrintValueObject()) 661 m_stream->PutCString(IsRef () ? ": {\n" : " {\n"); 662 m_stream->IndentMore(); 663 } 664} 665 666void 667ValueObjectPrinter::PrintChild (ValueObjectSP child_sp, 668 const DumpValueObjectOptions::PointerDepth& curr_ptr_depth) 669{ 670 DumpValueObjectOptions child_options(m_options); 671 child_options.SetFormat(m_options.m_format).SetSummary().SetRootValueObjectName(); 672 child_options.SetScopeChecked(true).SetHideName(m_options.m_hide_name).SetHideValue(m_options.m_hide_value) 673 .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0); 674 675 if (child_sp.get()) 676 { 677 ValueObjectPrinter child_printer(child_sp.get(), 678 m_stream, 679 child_options, 680 (IsPtr() || IsRef()) ? --curr_ptr_depth : curr_ptr_depth, 681 m_curr_depth + 1, 682 m_printed_instance_pointers); 683 child_printer.PrintValueObject(); 684 } 685} 686 687uint32_t 688ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot) 689{ 690 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 691 692 size_t num_children = synth_m_valobj->GetNumChildren(); 693 print_dotdotdot = false; 694 if (num_children) 695 { 696 const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 697 698 if (num_children > max_num_children && !m_options.m_ignore_cap) 699 { 700 print_dotdotdot = true; 701 return max_num_children; 702 } 703 } 704 return num_children; 705} 706 707void 708ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot) 709{ 710 if (!m_options.m_flat_output) 711 { 712 if (print_dotdotdot) 713 { 714 m_valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().ChildrenTruncated(); 715 m_stream->Indent("...\n"); 716 } 717 m_stream->IndentLess(); 718 m_stream->Indent("}\n"); 719 } 720} 721 722bool 723ValueObjectPrinter::ShouldPrintEmptyBrackets (bool value_printed, 724 bool summary_printed) 725{ 726 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 727 728 if (!IsAggregate()) 729 return false; 730 731 if (m_options.m_reveal_empty_aggregates == false) 732 { 733 if (value_printed || summary_printed) 734 return false; 735 } 736 737 if (synth_m_valobj->MightHaveChildren()) 738 return true; 739 740 if (m_val_summary_ok) 741 return false; 742 743 return true; 744} 745 746void 747ValueObjectPrinter::PrintChildren (bool value_printed, 748 bool summary_printed, 749 const DumpValueObjectOptions::PointerDepth& curr_ptr_depth) 750{ 751 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 752 753 bool print_dotdotdot = false; 754 size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); 755 if (num_children) 756 { 757 bool any_children_printed = false; 758 759 for (size_t idx=0; idx<num_children; ++idx) 760 { 761 ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); 762 if (child_sp) 763 { 764 if (!any_children_printed) 765 { 766 PrintChildrenPreamble (); 767 any_children_printed = true; 768 } 769 PrintChild (child_sp, curr_ptr_depth); 770 } 771 } 772 773 if (any_children_printed) 774 PrintChildrenPostamble (print_dotdotdot); 775 else 776 { 777 if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) 778 { 779 if (ShouldPrintValueObject()) 780 m_stream->PutCString(" {}\n"); 781 else 782 m_stream->EOL(); 783 } 784 else 785 m_stream->EOL(); 786 } 787 } 788 else if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) 789 { 790 // Aggregate, no children... 791 if (ShouldPrintValueObject()) 792 { 793 // if it has a synthetic value, then don't print {}, the synthetic children are probably only being used to vend a value 794 if (m_valobj->DoesProvideSyntheticValue() || !ShouldExpandEmptyAggregates()) 795 m_stream->PutCString( "\n"); 796 else 797 m_stream->PutCString(" {}\n"); 798 } 799 } 800 else 801 { 802 if (ShouldPrintValueObject()) 803 m_stream->EOL(); 804 } 805} 806 807bool 808ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names) 809{ 810 if (!GetMostSpecializedValue () || m_valobj == nullptr) 811 return false; 812 813 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 814 815 bool print_dotdotdot = false; 816 size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); 817 818 if (num_children) 819 { 820 m_stream->PutChar('('); 821 822 for (uint32_t idx=0; idx<num_children; ++idx) 823 { 824 lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); 825 if (child_sp) 826 child_sp = child_sp->GetQualifiedRepresentationIfAvailable(m_options.m_use_dynamic, m_options.m_use_synthetic); 827 if (child_sp) 828 { 829 if (idx) 830 m_stream->PutCString(", "); 831 if (!hide_names) 832 { 833 const char* name = child_sp.get()->GetName().AsCString(); 834 if (name && *name) 835 { 836 m_stream->PutCString(name); 837 m_stream->PutCString(" = "); 838 } 839 } 840 child_sp->DumpPrintableRepresentation(*m_stream, 841 ValueObject::eValueObjectRepresentationStyleSummary, 842 m_options.m_format, 843 ValueObject::ePrintableRepresentationSpecialCasesDisable); 844 } 845 } 846 847 if (print_dotdotdot) 848 m_stream->PutCString(", ...)"); 849 else 850 m_stream->PutChar(')'); 851 } 852 return true; 853} 854 855void 856ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed, 857 bool summary_printed) 858{ 859 // this flag controls whether we tried to display a description for this object and failed 860 // if that happens, we want to display the children, if any 861 bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed); 862 863 auto curr_ptr_depth = m_ptr_depth; 864 bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth); 865 bool print_oneline = (curr_ptr_depth.CanAllowExpansion() || 866 m_options.m_show_types || 867 !m_options.m_allow_oneliner_mode || 868 m_options.m_flat_output || 869 m_options.m_show_location) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj); 870 bool is_instance_ptr = IsInstancePointer(); 871 uint64_t instance_ptr_value = LLDB_INVALID_ADDRESS; 872 873 if (print_children && is_instance_ptr) 874 { 875 instance_ptr_value = m_valobj->GetValueAsUnsigned(0); 876 if (m_printed_instance_pointers->count(instance_ptr_value)) 877 { 878 // we already printed this instance-is-pointer thing, so don't expand it 879 m_stream->PutCString(" {...}\n"); 880 881 // we're done here - get out fast 882 return; 883 } 884 else 885 m_printed_instance_pointers->emplace(instance_ptr_value); // remember this guy for future reference 886 } 887 888 if (print_children) 889 { 890 if (print_oneline) 891 { 892 m_stream->PutChar(' '); 893 PrintChildrenOneLiner (false); 894 m_stream->EOL(); 895 } 896 else 897 PrintChildren (value_printed, summary_printed, curr_ptr_depth); 898 } 899 else if (m_curr_depth >= m_options.m_max_depth && IsAggregate() && ShouldPrintValueObject()) 900 { 901 m_stream->PutCString("{...}\n"); 902 } 903 else 904 m_stream->EOL(); 905} 906 907bool 908ValueObjectPrinter::ShouldPrintValidation () 909{ 910 return m_options.m_run_validator; 911} 912 913bool 914ValueObjectPrinter::PrintValidationMarkerIfNeeded () 915{ 916 if (!ShouldPrintValidation()) 917 return false; 918 919 m_validation = m_valobj->GetValidationStatus(); 920 921 if (TypeValidatorResult::Failure == m_validation.first) 922 { 923 m_stream->Printf("! "); 924 return true; 925 } 926 927 return false; 928} 929 930bool 931ValueObjectPrinter::PrintValidationErrorIfNeeded () 932{ 933 if (!ShouldPrintValidation()) 934 return false; 935 936 if (TypeValidatorResult::Success == m_validation.first) 937 return false; 938 939 if (m_validation.second.empty()) 940 m_validation.second.assign("unknown error"); 941 942 m_stream->Printf(" ! validation error: %s", m_validation.second.c_str()); 943 m_stream->EOL(); 944 945 return true; 946} 947