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