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