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