ValueObjectPrinter.cpp revision 258054
1262395Sbapt//===-- ValueObjectPrinter.cpp -------------------------------------*- C++ -*-===// 2262395Sbapt// 3262395Sbapt// The LLVM Compiler Infrastructure 4262395Sbapt// 5262395Sbapt// This file is distributed under the University of Illinois Open Source 6262395Sbapt// License. See LICENSE.TXT for details. 7262395Sbapt// 8262395Sbapt//===----------------------------------------------------------------------===// 9262395Sbapt 10262395Sbapt#include "lldb/DataFormatters/ValueObjectPrinter.h" 11262395Sbapt 12262395Sbapt// C Includes 13262395Sbapt// C++ Includes 14262395Sbapt// Other libraries and framework includes 15262395Sbapt// Project includes 16262395Sbapt#include "lldb/Core/Debugger.h" 17262395Sbapt#include "lldb/DataFormatters/DataVisualization.h" 18262395Sbapt#include "lldb/Interpreter/CommandInterpreter.h" 19262395Sbapt#include "lldb/Target/Target.h" 20262395Sbapt 21262395Sbaptusing namespace lldb; 22262395Sbaptusing namespace lldb_private; 23262395Sbapt 24262395SbaptValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, 25262395Sbapt Stream* s, 26262395Sbapt const DumpValueObjectOptions& options) 27262395Sbapt{ 28262395Sbapt Init(valobj,s,options,options.m_max_ptr_depth,0); 29262395Sbapt} 30262395Sbapt 31262395SbaptValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, 32262395Sbapt Stream* s, 33262395Sbapt const DumpValueObjectOptions& options, 34262395Sbapt uint32_t ptr_depth, 35262395Sbapt uint32_t curr_depth) 36262395Sbapt{ 37262395Sbapt Init(valobj,s,options,ptr_depth,curr_depth); 38262395Sbapt} 39262395Sbapt 40262395Sbaptvoid 41262395SbaptValueObjectPrinter::Init (ValueObject* valobj, 42262395Sbapt Stream* s, 43262395Sbapt const DumpValueObjectOptions& options, 44262395Sbapt uint32_t ptr_depth, 45262395Sbapt uint32_t curr_depth) 46262395Sbapt{ 47262395Sbapt m_orig_valobj = valobj; 48262395Sbapt m_valobj = nullptr; 49262395Sbapt m_stream = s; 50262395Sbapt this->options = options; 51262395Sbapt m_ptr_depth = ptr_depth; 52262395Sbapt m_curr_depth = curr_depth; 53262395Sbapt assert (m_orig_valobj && "cannot print a NULL ValueObject"); 54262395Sbapt assert (m_stream && "cannot print to a NULL Stream"); 55262395Sbapt m_should_print = eLazyBoolCalculate; 56262395Sbapt m_is_nil = eLazyBoolCalculate; 57262395Sbapt m_is_ptr = eLazyBoolCalculate; 58262395Sbapt m_is_ref = eLazyBoolCalculate; 59262395Sbapt m_is_aggregate = eLazyBoolCalculate; 60262395Sbapt m_summary_formatter = {nullptr,false}; 61262395Sbapt m_value.assign(""); 62262395Sbapt m_summary.assign(""); 63262395Sbapt m_error.assign(""); 64262395Sbapt} 65262395Sbapt 66262395Sbaptbool 67262395SbaptValueObjectPrinter::PrintValueObject () 68262395Sbapt{ 69262395Sbapt if (!GetDynamicValueIfNeeded () || m_valobj == nullptr) 70262395Sbapt return false; 71262395Sbapt 72262395Sbapt if (ShouldPrintValueObject()) 73262395Sbapt { 74262395Sbapt PrintLocationIfNeeded(); 75262395Sbapt m_stream->Indent(); 76262395Sbapt 77262395Sbapt bool show_type = PrintTypeIfNeeded(); 78262395Sbapt 79262395Sbapt PrintNameIfNeeded(show_type); 80262395Sbapt } 81262395Sbapt 82262395Sbapt bool value_printed = false; 83262395Sbapt bool summary_printed = false; 84262395Sbapt 85262395Sbapt bool val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed); 86262395Sbapt 87262395Sbapt if (val_summary_ok) 88262395Sbapt PrintChildrenIfNeeded (value_printed, summary_printed); 89262395Sbapt else 90262395Sbapt m_stream->EOL(); 91262395Sbapt 92262395Sbapt return true; 93262395Sbapt} 94262395Sbapt 95262395Sbaptbool 96262395SbaptValueObjectPrinter::GetDynamicValueIfNeeded () 97262395Sbapt{ 98262395Sbapt if (m_valobj) 99262395Sbapt return true; 100262395Sbapt bool update_success = m_orig_valobj->UpdateValueIfNeeded (true); 101262395Sbapt if (!update_success) 102262395Sbapt { 103262395Sbapt m_valobj = m_orig_valobj; 104262395Sbapt } 105262395Sbapt else 106262395Sbapt { 107262395Sbapt if (m_orig_valobj->IsDynamic()) 108262395Sbapt { 109262395Sbapt if (options.m_use_dynamic == eNoDynamicValues) 110262395Sbapt { 111262395Sbapt ValueObject *static_value = m_orig_valobj->GetStaticValue().get(); 112262395Sbapt if (static_value) 113262395Sbapt m_valobj = static_value; 114262395Sbapt else 115262395Sbapt m_valobj = m_orig_valobj; 116262395Sbapt } 117262395Sbapt else 118262395Sbapt m_valobj = m_orig_valobj; 119262395Sbapt } 120262395Sbapt else 121262395Sbapt { 122262395Sbapt if (options.m_use_dynamic != eNoDynamicValues) 123262395Sbapt { 124262395Sbapt ValueObject *dynamic_value = m_orig_valobj->GetDynamicValue(options.m_use_dynamic).get(); 125262395Sbapt if (dynamic_value) 126262395Sbapt m_valobj = dynamic_value; 127262395Sbapt else 128262395Sbapt m_valobj = m_orig_valobj; 129262395Sbapt } 130262395Sbapt else 131262395Sbapt m_valobj = m_orig_valobj; 132262395Sbapt } 133262395Sbapt } 134262395Sbapt m_clang_type = m_valobj->GetClangType(); 135262395Sbapt m_type_flags = m_clang_type.GetTypeInfo (); 136262395Sbapt return true; 137262395Sbapt} 138262395Sbapt 139262395Sbaptconst char* 140262395SbaptValueObjectPrinter::GetDescriptionForDisplay () 141262395Sbapt{ 142262395Sbapt const char* str = m_valobj->GetObjectDescription(); 143262395Sbapt if (!str) 144262395Sbapt str = m_valobj->GetSummaryAsCString(); 145262395Sbapt if (!str) 146262395Sbapt str = m_valobj->GetValueAsCString(); 147262395Sbapt return str; 148262395Sbapt} 149262395Sbapt 150262395Sbaptconst char* 151262395SbaptValueObjectPrinter::GetRootNameForDisplay (const char* if_fail) 152262395Sbapt{ 153262395Sbapt const char *root_valobj_name = options.m_root_valobj_name.empty() ? 154262395Sbapt m_valobj->GetName().AsCString() : 155262395Sbapt options.m_root_valobj_name.c_str(); 156262395Sbapt return root_valobj_name ? root_valobj_name : if_fail; 157262395Sbapt} 158262395Sbapt 159262395Sbaptbool 160262395SbaptValueObjectPrinter::ShouldPrintValueObject () 161262395Sbapt{ 162262395Sbapt if (m_should_print == eLazyBoolCalculate) 163262395Sbapt m_should_print = (options.m_flat_output == false || m_type_flags.Test (ClangASTType::eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo; 164262395Sbapt return m_should_print == eLazyBoolYes; 165262395Sbapt} 166262395Sbapt 167262395Sbaptbool 168262395SbaptValueObjectPrinter::IsNil () 169262395Sbapt{ 170262395Sbapt if (m_is_nil == eLazyBoolCalculate) 171262395Sbapt m_is_nil = m_valobj->IsObjCNil() ? eLazyBoolYes : eLazyBoolNo; 172262395Sbapt return m_is_nil == eLazyBoolYes; 173262395Sbapt} 174262395Sbapt 175262395Sbaptbool 176262395SbaptValueObjectPrinter::IsPtr () 177262395Sbapt{ 178262395Sbapt if (m_is_ptr == eLazyBoolCalculate) 179262395Sbapt m_is_ptr = m_type_flags.Test (ClangASTType::eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo; 180262395Sbapt return m_is_ptr == eLazyBoolYes; 181262395Sbapt} 182262395Sbapt 183262395Sbaptbool 184262395SbaptValueObjectPrinter::IsRef () 185262395Sbapt{ 186262395Sbapt if (m_is_ref == eLazyBoolCalculate) 187262395Sbapt m_is_ref = m_type_flags.Test (ClangASTType::eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo; 188262395Sbapt return m_is_ref == eLazyBoolYes; 189262395Sbapt} 190262395Sbapt 191262395Sbaptbool 192262395SbaptValueObjectPrinter::IsAggregate () 193262395Sbapt{ 194262395Sbapt if (m_is_aggregate == eLazyBoolCalculate) 195262395Sbapt m_is_aggregate = m_type_flags.Test (ClangASTType::eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo; 196262395Sbapt return m_is_aggregate == eLazyBoolYes; 197262395Sbapt} 198262395Sbapt 199262395Sbaptbool 200262395SbaptValueObjectPrinter::PrintLocationIfNeeded () 201262395Sbapt{ 202262395Sbapt if (options.m_show_location) 203262395Sbapt { 204262395Sbapt m_stream->Printf("%s: ", m_valobj->GetLocationAsCString()); 205262395Sbapt return true; 206262395Sbapt } 207262395Sbapt return false; 208262395Sbapt} 209262395Sbapt 210262395Sbaptbool 211262395SbaptValueObjectPrinter::PrintTypeIfNeeded () 212262395Sbapt{ 213262395Sbapt bool show_type = true; 214262395Sbapt // if we are at the root-level and been asked to hide the root's type, then hide it 215262395Sbapt if (m_curr_depth == 0 && options.m_hide_root_type) 216262395Sbapt show_type = false; 217262395Sbapt else 218262395Sbapt // otherwise decide according to the usual rules (asked to show types - always at the root level) 219262395Sbapt show_type = options.m_show_types || (m_curr_depth == 0 && !options.m_flat_output); 220262395Sbapt 221262395Sbapt if (show_type) 222262395Sbapt { 223262395Sbapt // Some ValueObjects don't have types (like registers sets). Only print 224262395Sbapt // the type if there is one to print 225262395Sbapt ConstString qualified_type_name(m_valobj->GetQualifiedTypeName()); 226262395Sbapt if (qualified_type_name) 227262395Sbapt m_stream->Printf("(%s) ", qualified_type_name.GetCString()); 228262395Sbapt else 229262395Sbapt show_type = false; 230262395Sbapt } 231262395Sbapt return show_type; 232262395Sbapt} 233262395Sbapt 234262395Sbaptbool 235262395SbaptValueObjectPrinter::PrintNameIfNeeded (bool show_type) 236262395Sbapt{ 237262395Sbapt if (options.m_flat_output) 238262395Sbapt { 239262395Sbapt // If we are showing types, also qualify the C++ base classes 240262395Sbapt const bool qualify_cxx_base_classes = show_type; 241262395Sbapt if (!options.m_hide_name) 242262395Sbapt { 243262395Sbapt m_valobj->GetExpressionPath(*m_stream, qualify_cxx_base_classes); 244262395Sbapt m_stream->PutCString(" ="); 245262395Sbapt return true; 246262395Sbapt } 247262395Sbapt } 248262395Sbapt else if (!options.m_hide_name) 249262395Sbapt { 250262395Sbapt const char *name_cstr = GetRootNameForDisplay(""); 251262395Sbapt m_stream->Printf ("%s =", name_cstr); 252262395Sbapt return true; 253262395Sbapt } 254262395Sbapt return false; 255262395Sbapt} 256262395Sbapt 257262395Sbaptbool 258262395SbaptValueObjectPrinter::CheckScopeIfNeeded () 259262395Sbapt{ 260262395Sbapt if (options.m_scope_already_checked) 261262395Sbapt return true; 262262395Sbapt return m_valobj->IsInScope(); 263262395Sbapt} 264262395Sbapt 265262395SbaptTypeSummaryImpl* 266262395SbaptValueObjectPrinter::GetSummaryFormatter () 267262395Sbapt{ 268262395Sbapt if (m_summary_formatter.second == false) 269262395Sbapt { 270262395Sbapt TypeSummaryImpl* entry = options.m_summary_sp ? options.m_summary_sp.get() : m_valobj->GetSummaryFormat().get(); 271262395Sbapt 272262395Sbapt if (options.m_omit_summary_depth > 0) 273262395Sbapt entry = NULL; 274262395Sbapt m_summary_formatter.first = entry; 275262395Sbapt m_summary_formatter.second = true; 276262395Sbapt } 277262395Sbapt return m_summary_formatter.first; 278262395Sbapt} 279262395Sbapt 280262395Sbaptvoid 281262395SbaptValueObjectPrinter::GetValueSummaryError (std::string& value, 282262395Sbapt std::string& summary, 283262395Sbapt std::string& error) 284262395Sbapt{ 285262395Sbapt if (options.m_format != eFormatDefault && options.m_format != m_valobj->GetFormat()) 286262395Sbapt { 287262395Sbapt m_valobj->GetValueAsCString(options.m_format, 288262395Sbapt value); 289262395Sbapt } 290262395Sbapt else 291262395Sbapt { 292262395Sbapt const char* val_cstr = m_valobj->GetValueAsCString(); 293262395Sbapt if (val_cstr) 294262395Sbapt value.assign(val_cstr); 295262395Sbapt } 296262395Sbapt const char* err_cstr = m_valobj->GetError().AsCString(); 297262395Sbapt if (err_cstr) 298262395Sbapt error.assign(err_cstr); 299262395Sbapt 300262395Sbapt if (ShouldPrintValueObject()) 301262395Sbapt { 302262395Sbapt if (IsNil()) 303262395Sbapt summary.assign("nil"); 304262395Sbapt else if (options.m_omit_summary_depth == 0) 305262395Sbapt { 306262395Sbapt TypeSummaryImpl* entry = GetSummaryFormatter(); 307262395Sbapt if (entry) 308262395Sbapt m_valobj->GetSummaryAsCString(entry, summary); 309262395Sbapt else 310262395Sbapt { 311262395Sbapt const char* sum_cstr = m_valobj->GetSummaryAsCString(); 312262395Sbapt if (sum_cstr) 313262395Sbapt summary.assign(sum_cstr); 314262395Sbapt } 315262395Sbapt } 316262395Sbapt } 317262395Sbapt} 318262395Sbapt 319262395Sbaptbool 320262395SbaptValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed, 321262395Sbapt bool& summary_printed) 322262395Sbapt{ 323262395Sbapt bool error_printed = false; 324262395Sbapt if (ShouldPrintValueObject()) 325262395Sbapt { 326262395Sbapt if (!CheckScopeIfNeeded()) 327262395Sbapt m_error.assign("out of scope"); 328262395Sbapt if (m_error.empty()) 329262395Sbapt { 330262395Sbapt GetValueSummaryError(m_value, m_summary, m_error); 331262395Sbapt } 332262395Sbapt if (m_error.size()) 333262395Sbapt { 334262395Sbapt error_printed = true; 335262395Sbapt m_stream->Printf (" <%s>\n", m_error.c_str()); 336262395Sbapt } 337262395Sbapt else 338262395Sbapt { 339262395Sbapt // Make sure we have a value and make sure the summary didn't 340262395Sbapt // specify that the value should not be printed - and do not print 341262395Sbapt // the value if this thing is nil 342262395Sbapt // (but show the value if the user passes a format explicitly) 343262395Sbapt TypeSummaryImpl* entry = GetSummaryFormatter(); 344262395Sbapt if (!IsNil() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue() || options.m_format != eFormatDefault) || m_summary.empty()) && !options.m_hide_value) 345262395Sbapt { 346262395Sbapt m_stream->Printf(" %s", m_value.c_str()); 347262395Sbapt value_printed = true; 348262395Sbapt } 349262395Sbapt 350262395Sbapt if (m_summary.size()) 351262395Sbapt { 352262395Sbapt m_stream->Printf(" %s", m_summary.c_str()); 353262395Sbapt summary_printed = true; 354262395Sbapt } 355262395Sbapt } 356262395Sbapt } 357262395Sbapt return !error_printed; 358262395Sbapt} 359262395Sbapt 360262395Sbaptbool 361262395SbaptValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed, 362262395Sbapt bool summary_printed) 363262395Sbapt{ 364262395Sbapt if (ShouldPrintValueObject()) 365262395Sbapt { 366262395Sbapt // let's avoid the overly verbose no description error for a nil thing 367262395Sbapt if (options.m_use_objc && !IsNil()) 368262395Sbapt { 369262395Sbapt if (!options.m_hide_value || !options.m_hide_name) 370262395Sbapt m_stream->Printf(" "); 371262395Sbapt const char *object_desc = nullptr; 372262395Sbapt if (value_printed || summary_printed) 373262395Sbapt object_desc = m_valobj->GetObjectDescription(); 374262395Sbapt else 375262395Sbapt object_desc = GetDescriptionForDisplay(); 376262395Sbapt if (object_desc && *object_desc) 377262395Sbapt { 378262395Sbapt m_stream->Printf("%s\n", object_desc); 379262395Sbapt return true; 380262395Sbapt } 381262395Sbapt else if (value_printed == false && summary_printed == false) 382262395Sbapt return true; 383262395Sbapt else 384262395Sbapt return false; 385262395Sbapt } 386262395Sbapt } 387262395Sbapt return true; 388262395Sbapt} 389262395Sbapt 390262395Sbaptbool 391262395SbaptValueObjectPrinter::ShouldPrintChildren (bool is_failed_description, 392262395Sbapt uint32_t& curr_ptr_depth) 393262395Sbapt{ 394262395Sbapt const bool is_ref = IsRef (); 395262395Sbapt const bool is_ptr = IsPtr (); 396262395Sbapt 397262395Sbapt if (is_failed_description || m_curr_depth < options.m_max_depth) 398262395Sbapt { 399262395Sbapt // We will show children for all concrete types. We won't show 400262395Sbapt // pointer contents unless a pointer depth has been specified. 401262395Sbapt // We won't reference contents unless the reference is the 402262395Sbapt // root object (depth of zero). 403262395Sbapt 404262395Sbapt // Use a new temporary pointer depth in case we override the 405262395Sbapt // current pointer depth below... 406262395Sbapt uint32_t curr_ptr_depth = m_ptr_depth; 407262395Sbapt 408262395Sbapt if (is_ptr || is_ref) 409262395Sbapt { 410262395Sbapt // We have a pointer or reference whose value is an address. 411262395Sbapt // Make sure that address is not NULL 412262395Sbapt AddressType ptr_address_type; 413262395Sbapt if (m_valobj->GetPointerValue (&ptr_address_type) == 0) 414262395Sbapt return false; 415262395Sbapt 416262395Sbapt else if (is_ref && m_curr_depth == 0) 417262395Sbapt { 418262395Sbapt // If this is the root object (depth is zero) that we are showing 419262395Sbapt // and it is a reference, and no pointer depth has been supplied 420262395Sbapt // print out what it references. Don't do this at deeper depths 421262395Sbapt // otherwise we can end up with infinite recursion... 422262395Sbapt curr_ptr_depth = 1; 423262395Sbapt } 424262395Sbapt 425262395Sbapt return (curr_ptr_depth > 0); 426262395Sbapt } 427262395Sbapt 428262395Sbapt TypeSummaryImpl* entry = GetSummaryFormatter(); 429262395Sbapt 430262395Sbapt return (!entry || entry->DoesPrintChildren() || m_summary.empty()); 431262395Sbapt } 432262395Sbapt return false; 433262395Sbapt} 434262395Sbapt 435262395SbaptValueObject* 436262395SbaptValueObjectPrinter::GetValueObjectForChildrenGeneration () 437262395Sbapt{ 438262395Sbapt ValueObjectSP synth_valobj_sp = m_valobj->GetSyntheticValue (options.m_use_synthetic); 439262395Sbapt return (synth_valobj_sp ? synth_valobj_sp.get() : m_valobj); 440262395Sbapt} 441262395Sbapt 442262395Sbaptvoid 443262395SbaptValueObjectPrinter::PrintChildrenPreamble () 444262395Sbapt{ 445262395Sbapt if (options.m_flat_output) 446262395Sbapt { 447262395Sbapt if (ShouldPrintValueObject()) 448262395Sbapt m_stream->EOL(); 449262395Sbapt } 450262395Sbapt else 451262395Sbapt { 452262395Sbapt if (ShouldPrintValueObject()) 453262395Sbapt m_stream->PutCString(IsRef () ? ": {\n" : " {\n"); 454262395Sbapt m_stream->IndentMore(); 455262395Sbapt } 456262395Sbapt} 457262395Sbapt 458262395Sbaptvoid 459262395SbaptValueObjectPrinter::PrintChild (ValueObjectSP child_sp, 460262395Sbapt uint32_t curr_ptr_depth) 461262395Sbapt{ 462262395Sbapt DumpValueObjectOptions child_options(options); 463262395Sbapt child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName(); 464262395Sbapt child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(options.m_hide_value) 465262395Sbapt .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0); 466262395Sbapt if (child_sp.get()) 467262395Sbapt { 468262395Sbapt ValueObjectPrinter child_printer(child_sp.get(), 469262395Sbapt m_stream, 470262395Sbapt child_options, 471262395Sbapt (IsPtr() || IsRef()) ? curr_ptr_depth - 1 : curr_ptr_depth, 472262395Sbapt m_curr_depth + 1); 473262395Sbapt child_printer.PrintValueObject(); 474262395Sbapt } 475262395Sbapt 476262395Sbapt} 477262395Sbapt 478262395Sbaptuint32_t 479262395SbaptValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot) 480262395Sbapt{ 481262395Sbapt ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 482262395Sbapt 483262395Sbapt size_t num_children = synth_m_valobj->GetNumChildren(); 484262395Sbapt print_dotdotdot = false; 485262395Sbapt if (num_children) 486262395Sbapt { 487262395Sbapt const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 488262395Sbapt 489262395Sbapt if (num_children > max_num_children && !options.m_ignore_cap) 490262395Sbapt { 491262395Sbapt print_dotdotdot = true; 492262395Sbapt return max_num_children; 493262395Sbapt } 494262395Sbapt } 495262395Sbapt return num_children; 496262395Sbapt} 497262395Sbapt 498262395Sbaptvoid 499262395SbaptValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot) 500262395Sbapt{ 501262395Sbapt if (!options.m_flat_output) 502262395Sbapt { 503262395Sbapt if (print_dotdotdot) 504262395Sbapt { 505262395Sbapt m_valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().ChildrenTruncated(); 506262395Sbapt m_stream->Indent("...\n"); 507262395Sbapt } 508262395Sbapt m_stream->IndentLess(); 509262395Sbapt m_stream->Indent("}\n"); 510262395Sbapt } 511262395Sbapt} 512262395Sbapt 513262395Sbaptvoid 514262395SbaptValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth) 515262395Sbapt{ 516262395Sbapt ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 517262395Sbapt 518262395Sbapt bool print_dotdotdot = false; 519262395Sbapt size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); 520262395Sbapt if (num_children) 521262395Sbapt { 522262395Sbapt PrintChildrenPreamble (); 523262395Sbapt 524262395Sbapt for (size_t idx=0; idx<num_children; ++idx) 525262395Sbapt { 526262395Sbapt ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); 527262395Sbapt PrintChild (child_sp, curr_ptr_depth); 528262395Sbapt } 529262395Sbapt 530262395Sbapt PrintChildrenPostamble (print_dotdotdot); 531262395Sbapt } 532262395Sbapt else if (IsAggregate()) 533262395Sbapt { 534262395Sbapt // Aggregate, no children... 535262395Sbapt if (ShouldPrintValueObject()) 536262395Sbapt m_stream->PutCString(" {}\n"); 537262395Sbapt } 538262395Sbapt else 539262395Sbapt { 540262395Sbapt if (ShouldPrintValueObject()) 541262395Sbapt m_stream->EOL(); 542262395Sbapt } 543262395Sbapt} 544262395Sbapt 545262395Sbaptbool 546262395SbaptValueObjectPrinter::PrintChildrenOneLiner (bool hide_names) 547263648Sbapt{ 548263648Sbapt if (!GetDynamicValueIfNeeded () || m_valobj == nullptr) 549263648Sbapt return false; 550263648Sbapt 551262395Sbapt ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 552262395Sbapt 553262395Sbapt bool print_dotdotdot = false; 554262395Sbapt size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); 555262395Sbapt 556262395Sbapt if (num_children) 557262395Sbapt { 558262395Sbapt m_stream->PutChar('('); 559262395Sbapt 560262395Sbapt for (uint32_t idx=0; idx<num_children; ++idx) 561263648Sbapt { 562263648Sbapt lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); 563262395Sbapt lldb::ValueObjectSP child_dyn_sp = child_sp.get() ? child_sp->GetDynamicValue(options.m_use_dynamic) : child_sp; 564262395Sbapt if (child_dyn_sp) 565262395Sbapt child_sp = child_dyn_sp; 566262395Sbapt if (child_sp) 567263648Sbapt { 568262395Sbapt if (idx) 569262395Sbapt m_stream->PutCString(", "); 570262395Sbapt if (!hide_names) 571262395Sbapt { 572262395Sbapt const char* name = child_sp.get()->GetName().AsCString(); 573262395Sbapt if (name && *name) 574262395Sbapt { 575262395Sbapt m_stream->PutCString(name); 576262395Sbapt m_stream->PutCString(" = "); 577262395Sbapt } 578262395Sbapt } 579262395Sbapt child_sp->DumpPrintableRepresentation(*m_stream, 580262395Sbapt ValueObject::eValueObjectRepresentationStyleSummary, 581262395Sbapt lldb::eFormatInvalid, 582262395Sbapt ValueObject::ePrintableRepresentationSpecialCasesDisable); 583262395Sbapt } 584262395Sbapt } 585262395Sbapt 586262395Sbapt if (print_dotdotdot) 587262395Sbapt m_stream->PutCString(", ...)"); 588262395Sbapt else 589262395Sbapt m_stream->PutChar(')'); 590262395Sbapt } 591262395Sbapt return true; 592262395Sbapt} 593262395Sbapt 594262395Sbaptvoid 595262395SbaptValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed, 596262395Sbapt bool summary_printed) 597262395Sbapt{ 598262395Sbapt // this flag controls whether we tried to display a description for this object and failed 599262395Sbapt // if that happens, we want to display the children, if any 600262395Sbapt bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed); 601262395Sbapt 602262395Sbapt uint32_t curr_ptr_depth = m_ptr_depth; 603262395Sbapt bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth); 604262395Sbapt bool print_oneline = (curr_ptr_depth > 0 || options.m_show_types || options.m_be_raw) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj); 605262395Sbapt 606262395Sbapt if (print_children) 607262395Sbapt { 608262395Sbapt if (print_oneline) 609262395Sbapt { 610262395Sbapt m_stream->PutChar(' '); 611262395Sbapt PrintChildrenOneLiner (false); 612262395Sbapt m_stream->EOL(); 613262395Sbapt } 614262395Sbapt else 615262395Sbapt PrintChildren (curr_ptr_depth); 616262395Sbapt } 617262395Sbapt else if (m_curr_depth >= options.m_max_depth && IsAggregate() && ShouldPrintValueObject()) 618262395Sbapt { 619262395Sbapt m_stream->PutCString("{...}\n"); 620262395Sbapt } 621262395Sbapt else 622262395Sbapt m_stream->EOL(); 623262395Sbapt} 624262395Sbapt