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 23 using namespace lldb; 24 using namespace lldb_private; 25 26 ValueObjectPrinter::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 41 ValueObjectPrinter::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 48 ValueObjectPrinter::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 58 void 59 ValueObjectPrinter::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 89 bool 90 ValueObjectPrinter::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 120 bool 121 ValueObjectPrinter::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 183 const char* 184 ValueObjectPrinter::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 194 const char* 195 ValueObjectPrinter::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 203 bool 204 ValueObjectPrinter::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 211 bool 212 ValueObjectPrinter::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 219 bool 220 ValueObjectPrinter::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 227 bool 228 ValueObjectPrinter::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 235 bool 236 ValueObjectPrinter::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 243 bool 244 ValueObjectPrinter::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 251 bool 252 ValueObjectPrinter::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 262 bool 263 ValueObjectPrinter::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 273 void 274 ValueObjectPrinter::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 380 bool 381 ValueObjectPrinter::CheckScopeIfNeeded () 382 { 383 if (m_options.m_scope_already_checked) 384 return true; 385 return m_valobj->IsInScope(); 386 } 387 388 TypeSummaryImpl* 389 ValueObjectPrinter::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 405 static bool 406 IsPointerValue (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 414 void 415 ValueObjectPrinter::GetValueSummaryError (std::string& value, 416 std::string& summary, 417 std::string& error) 418 { 419 lldb::Format format = m_options.m_format; 420 // if I am printing synthetized elements, apply the format to those elements only 421 if (m_options.m_element_count > 0) 422 m_valobj->GetValueAsCString(lldb::eFormatDefault, value); 423 else if (format != eFormatDefault && format != m_valobj->GetFormat()) 424 m_valobj->GetValueAsCString(format, value); 425 else 426 { 427 const char* val_cstr = m_valobj->GetValueAsCString(); 428 if (val_cstr) 429 value.assign(val_cstr); 430 } 431 const char* err_cstr = m_valobj->GetError().AsCString(); 432 if (err_cstr) 433 error.assign(err_cstr); 434 435 if (ShouldPrintValueObject()) 436 { 437 if (IsNil()) 438 summary.assign("nil"); 439 else if (IsUninitialized()) 440 summary.assign("<uninitialized>"); 441 else if (m_options.m_omit_summary_depth == 0) 442 { 443 TypeSummaryImpl* entry = GetSummaryFormatter(); 444 if (entry) 445 m_valobj->GetSummaryAsCString(entry, summary, m_options.m_varformat_language); 446 else 447 { 448 const char* sum_cstr = m_valobj->GetSummaryAsCString(m_options.m_varformat_language); 449 if (sum_cstr) 450 summary.assign(sum_cstr); 451 } 452 } 453 } 454 } 455 456 bool 457 ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed, 458 bool& summary_printed) 459 { 460 bool error_printed = false; 461 if (ShouldPrintValueObject()) 462 { 463 if (!CheckScopeIfNeeded()) 464 m_error.assign("out of scope"); 465 if (m_error.empty()) 466 { 467 GetValueSummaryError(m_value, m_summary, m_error); 468 } 469 if (m_error.size()) 470 { 471 // we need to support scenarios in which it is actually fine for a value to have no type 472 // but - on the other hand - if we get an error *AND* have no type, we try to get out 473 // gracefully, since most often that combination means "could not resolve a type" 474 // and the default failure mode is quite ugly 475 if (!m_compiler_type.IsValid()) 476 { 477 m_stream->Printf(" <could not resolve type>"); 478 return false; 479 } 480 481 error_printed = true; 482 m_stream->Printf (" <%s>\n", m_error.c_str()); 483 } 484 else 485 { 486 // Make sure we have a value and make sure the summary didn't 487 // specify that the value should not be printed - and do not print 488 // the value if this thing is nil 489 // (but show the value if the user passes a format explicitly) 490 TypeSummaryImpl* entry = GetSummaryFormatter(); 491 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) 492 { 493 if (m_options.m_hide_pointer_value && IsPointerValue(m_valobj->GetCompilerType())) {} 494 else 495 { 496 m_stream->Printf(" %s", m_value.c_str()); 497 value_printed = true; 498 } 499 } 500 501 if (m_summary.size()) 502 { 503 m_stream->Printf(" %s", m_summary.c_str()); 504 summary_printed = true; 505 } 506 } 507 } 508 return !error_printed; 509 } 510 511 bool 512 ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed, 513 bool summary_printed) 514 { 515 if (ShouldPrintValueObject()) 516 { 517 // let's avoid the overly verbose no description error for a nil thing 518 if (m_options.m_use_objc && !IsNil() && !IsUninitialized() && (m_options.m_element_count == 0)) 519 { 520 if (!m_options.m_hide_value || !m_options.m_hide_name) 521 m_stream->Printf(" "); 522 const char *object_desc = nullptr; 523 if (value_printed || summary_printed) 524 object_desc = m_valobj->GetObjectDescription(); 525 else 526 object_desc = GetDescriptionForDisplay(); 527 if (object_desc && *object_desc) 528 { 529 m_stream->Printf("%s\n", object_desc); 530 return true; 531 } 532 else if (value_printed == false && summary_printed == false) 533 return true; 534 else 535 return false; 536 } 537 } 538 return true; 539 } 540 541 bool 542 DumpValueObjectOptions::PointerDepth::CanAllowExpansion (bool is_root, 543 TypeSummaryImpl* entry, 544 ValueObject *valobj, 545 const std::string& summary) 546 { 547 switch (m_mode) 548 { 549 case Mode::Always: 550 return (m_count > 0); 551 case Mode::Never: 552 return false; 553 case Mode::Default: 554 if (is_root) 555 m_count = std::min<decltype(m_count)>(m_count,1); 556 return m_count > 0; 557 case Mode::Formatters: 558 if (!entry || entry->DoesPrintChildren(valobj) || summary.empty()) 559 return m_count > 0; 560 return false; 561 } 562 return false; 563 } 564 565 bool 566 DumpValueObjectOptions::PointerDepth::CanAllowExpansion () const 567 { 568 switch (m_mode) 569 { 570 case Mode::Always: 571 case Mode::Default: 572 case Mode::Formatters: 573 return (m_count > 0); 574 case Mode::Never: 575 return false; 576 } 577 return false; 578 } 579 580 bool 581 ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description, 582 DumpValueObjectOptions::PointerDepth& curr_ptr_depth) 583 { 584 const bool is_ref = IsRef (); 585 const bool is_ptr = IsPtr (); 586 const bool is_uninit = IsUninitialized(); 587 588 if (is_uninit) 589 return false; 590 591 // if the user has specified an element count, always print children 592 // as it is explicit user demand being honored 593 if (m_options.m_element_count > 0) 594 return true; 595 596 TypeSummaryImpl* entry = GetSummaryFormatter(); 597 598 if (m_options.m_use_objc) 599 return false; 600 601 if (is_failed_description || m_curr_depth < m_options.m_max_depth) 602 { 603 // We will show children for all concrete types. We won't show 604 // pointer contents unless a pointer depth has been specified. 605 // We won't reference contents unless the reference is the 606 // root object (depth of zero). 607 608 // Use a new temporary pointer depth in case we override the 609 // current pointer depth below... 610 611 if (is_ptr || is_ref) 612 { 613 // We have a pointer or reference whose value is an address. 614 // Make sure that address is not NULL 615 AddressType ptr_address_type; 616 if (m_valobj->GetPointerValue (&ptr_address_type) == 0) 617 return false; 618 619 const bool is_root_level = m_curr_depth == 0; 620 621 if (is_ref && 622 is_root_level) 623 { 624 // If this is the root object (depth is zero) that we are showing 625 // and it is a reference, and no pointer depth has been supplied 626 // print out what it references. Don't do this at deeper depths 627 // otherwise we can end up with infinite recursion... 628 return true; 629 } 630 631 return curr_ptr_depth.CanAllowExpansion(false, entry, m_valobj, m_summary); 632 } 633 634 return (!entry || entry->DoesPrintChildren(m_valobj) || m_summary.empty()); 635 } 636 return false; 637 } 638 639 bool 640 ValueObjectPrinter::ShouldExpandEmptyAggregates () 641 { 642 TypeSummaryImpl* entry = GetSummaryFormatter(); 643 644 if (!entry) 645 return true; 646 647 return entry->DoesPrintEmptyAggregates(); 648 } 649 650 ValueObject* 651 ValueObjectPrinter::GetValueObjectForChildrenGeneration () 652 { 653 return m_valobj; 654 } 655 656 void 657 ValueObjectPrinter::PrintChildrenPreamble () 658 { 659 if (m_options.m_flat_output) 660 { 661 if (ShouldPrintValueObject()) 662 m_stream->EOL(); 663 } 664 else 665 { 666 if (ShouldPrintValueObject()) 667 m_stream->PutCString(IsRef () ? ": {\n" : " {\n"); 668 m_stream->IndentMore(); 669 } 670 } 671 672 void 673 ValueObjectPrinter::PrintChild (ValueObjectSP child_sp, 674 const DumpValueObjectOptions::PointerDepth& curr_ptr_depth) 675 { 676 const uint32_t consumed_depth = (m_options.m_element_count == 0) ? 1 : 0; 677 const bool does_consume_ptr_depth = ((IsPtr() && m_options.m_element_count == 0) || IsRef()); 678 679 DumpValueObjectOptions child_options(m_options); 680 child_options.SetFormat(m_options.m_format).SetSummary().SetRootValueObjectName(); 681 child_options.SetScopeChecked(true).SetHideName(m_options.m_hide_name).SetHideValue(m_options.m_hide_value) 682 .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - consumed_depth : 0) 683 .SetElementCount(0); 684 685 if (child_sp.get()) 686 { 687 ValueObjectPrinter child_printer(child_sp.get(), 688 m_stream, 689 child_options, 690 does_consume_ptr_depth ? --curr_ptr_depth : curr_ptr_depth, 691 m_curr_depth + consumed_depth, 692 m_printed_instance_pointers); 693 child_printer.PrintValueObject(); 694 } 695 } 696 697 uint32_t 698 ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot) 699 { 700 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 701 702 if (m_options.m_element_count > 0) 703 return m_options.m_element_count; 704 705 size_t num_children = synth_m_valobj->GetNumChildren(); 706 print_dotdotdot = false; 707 if (num_children) 708 { 709 const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 710 711 if (num_children > max_num_children && !m_options.m_ignore_cap) 712 { 713 print_dotdotdot = true; 714 return max_num_children; 715 } 716 } 717 return num_children; 718 } 719 720 void 721 ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot) 722 { 723 if (!m_options.m_flat_output) 724 { 725 if (print_dotdotdot) 726 { 727 m_valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().ChildrenTruncated(); 728 m_stream->Indent("...\n"); 729 } 730 m_stream->IndentLess(); 731 m_stream->Indent("}\n"); 732 } 733 } 734 735 bool 736 ValueObjectPrinter::ShouldPrintEmptyBrackets (bool value_printed, 737 bool summary_printed) 738 { 739 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 740 741 if (!IsAggregate()) 742 return false; 743 744 if (m_options.m_reveal_empty_aggregates == false) 745 { 746 if (value_printed || summary_printed) 747 return false; 748 } 749 750 if (synth_m_valobj->MightHaveChildren()) 751 return true; 752 753 if (m_val_summary_ok) 754 return false; 755 756 return true; 757 } 758 759 ValueObjectSP 760 ValueObjectPrinter::GenerateChild (ValueObject* synth_valobj, size_t idx) 761 { 762 if (m_options.m_element_count > 0) 763 { 764 // if generating pointer-as-array children, use GetSyntheticArrayMember 765 return synth_valobj->GetSyntheticArrayMember(idx, true); 766 } 767 else 768 { 769 // otherwise, do the usual thing 770 return synth_valobj->GetChildAtIndex(idx, true); 771 } 772 } 773 774 void 775 ValueObjectPrinter::PrintChildren (bool value_printed, 776 bool summary_printed, 777 const DumpValueObjectOptions::PointerDepth& curr_ptr_depth) 778 { 779 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 780 781 bool print_dotdotdot = false; 782 size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); 783 if (num_children) 784 { 785 bool any_children_printed = false; 786 787 for (size_t idx=0; idx<num_children; ++idx) 788 { 789 if (ValueObjectSP child_sp = GenerateChild(synth_m_valobj, idx)) 790 { 791 if (!any_children_printed) 792 { 793 PrintChildrenPreamble (); 794 any_children_printed = true; 795 } 796 PrintChild (child_sp, curr_ptr_depth); 797 } 798 } 799 800 if (any_children_printed) 801 PrintChildrenPostamble (print_dotdotdot); 802 else 803 { 804 if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) 805 { 806 if (ShouldPrintValueObject()) 807 m_stream->PutCString(" {}\n"); 808 else 809 m_stream->EOL(); 810 } 811 else 812 m_stream->EOL(); 813 } 814 } 815 else if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) 816 { 817 // Aggregate, no children... 818 if (ShouldPrintValueObject()) 819 { 820 // if it has a synthetic value, then don't print {}, the synthetic children are probably only being used to vend a value 821 if (m_valobj->DoesProvideSyntheticValue() || !ShouldExpandEmptyAggregates()) 822 m_stream->PutCString( "\n"); 823 else 824 m_stream->PutCString(" {}\n"); 825 } 826 } 827 else 828 { 829 if (ShouldPrintValueObject()) 830 m_stream->EOL(); 831 } 832 } 833 834 bool 835 ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names) 836 { 837 if (!GetMostSpecializedValue () || m_valobj == nullptr) 838 return false; 839 840 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 841 842 bool print_dotdotdot = false; 843 size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); 844 845 if (num_children) 846 { 847 m_stream->PutChar('('); 848 849 for (uint32_t idx=0; idx<num_children; ++idx) 850 { 851 lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); 852 if (child_sp) 853 child_sp = child_sp->GetQualifiedRepresentationIfAvailable(m_options.m_use_dynamic, m_options.m_use_synthetic); 854 if (child_sp) 855 { 856 if (idx) 857 m_stream->PutCString(", "); 858 if (!hide_names) 859 { 860 const char* name = child_sp.get()->GetName().AsCString(); 861 if (name && *name) 862 { 863 m_stream->PutCString(name); 864 m_stream->PutCString(" = "); 865 } 866 } 867 child_sp->DumpPrintableRepresentation(*m_stream, 868 ValueObject::eValueObjectRepresentationStyleSummary, 869 m_options.m_format, 870 ValueObject::ePrintableRepresentationSpecialCasesDisable); 871 } 872 } 873 874 if (print_dotdotdot) 875 m_stream->PutCString(", ...)"); 876 else 877 m_stream->PutChar(')'); 878 } 879 return true; 880 } 881 882 void 883 ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed, 884 bool summary_printed) 885 { 886 // this flag controls whether we tried to display a description for this object and failed 887 // if that happens, we want to display the children, if any 888 bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed); 889 890 auto curr_ptr_depth = m_ptr_depth; 891 bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth); 892 bool print_oneline = (curr_ptr_depth.CanAllowExpansion() || 893 m_options.m_show_types || 894 !m_options.m_allow_oneliner_mode || 895 m_options.m_flat_output || 896 (m_options.m_element_count > 0) || 897 m_options.m_show_location) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj); 898 bool is_instance_ptr = IsInstancePointer(); 899 uint64_t instance_ptr_value = LLDB_INVALID_ADDRESS; 900 901 if (print_children && is_instance_ptr) 902 { 903 instance_ptr_value = m_valobj->GetValueAsUnsigned(0); 904 if (m_printed_instance_pointers->count(instance_ptr_value)) 905 { 906 // we already printed this instance-is-pointer thing, so don't expand it 907 m_stream->PutCString(" {...}\n"); 908 909 // we're done here - get out fast 910 return; 911 } 912 else 913 m_printed_instance_pointers->emplace(instance_ptr_value); // remember this guy for future reference 914 } 915 916 if (print_children) 917 { 918 if (print_oneline) 919 { 920 m_stream->PutChar(' '); 921 PrintChildrenOneLiner (false); 922 m_stream->EOL(); 923 } 924 else 925 PrintChildren (value_printed, summary_printed, curr_ptr_depth); 926 } 927 else if (m_curr_depth >= m_options.m_max_depth && IsAggregate() && ShouldPrintValueObject()) 928 { 929 m_stream->PutCString("{...}\n"); 930 } 931 else 932 m_stream->EOL(); 933 } 934 935 bool 936 ValueObjectPrinter::ShouldPrintValidation () 937 { 938 return m_options.m_run_validator; 939 } 940 941 bool 942 ValueObjectPrinter::PrintValidationMarkerIfNeeded () 943 { 944 if (!ShouldPrintValidation()) 945 return false; 946 947 m_validation = m_valobj->GetValidationStatus(); 948 949 if (TypeValidatorResult::Failure == m_validation.first) 950 { 951 m_stream->Printf("! "); 952 return true; 953 } 954 955 return false; 956 } 957 958 bool 959 ValueObjectPrinter::PrintValidationErrorIfNeeded () 960 { 961 if (!ShouldPrintValidation()) 962 return false; 963 964 if (TypeValidatorResult::Success == m_validation.first) 965 return false; 966 967 if (m_validation.second.empty()) 968 m_validation.second.assign("unknown error"); 969 970 m_stream->Printf(" ! validation error: %s", m_validation.second.c_str()); 971 m_stream->EOL(); 972 973 return true; 974 } 975