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