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