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