]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/DataFormatters/ValueObjectPrinter.cpp
Vendor import of lldb release_39 branch r276489:
[FreeBSD/FreeBSD.git] / source / DataFormatters / ValueObjectPrinter.cpp
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_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
89 bool
90 ValueObjectPrinter::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
120 bool
121 ValueObjectPrinter::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
183 const char*
184 ValueObjectPrinter::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
194 const char*
195 ValueObjectPrinter::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
203 bool
204 ValueObjectPrinter::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
211 bool
212 ValueObjectPrinter::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
219 bool
220 ValueObjectPrinter::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
227 bool
228 ValueObjectPrinter::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
235 bool
236 ValueObjectPrinter::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
243 bool
244 ValueObjectPrinter::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
251 bool
252 ValueObjectPrinter::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
262 bool
263 ValueObjectPrinter::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
273 void
274 ValueObjectPrinter::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
380 bool
381 ValueObjectPrinter::CheckScopeIfNeeded ()
382 {
383     if (m_options.m_scope_already_checked)
384         return true;
385     return m_valobj->IsInScope();
386 }
387
388 TypeSummaryImpl*
389 ValueObjectPrinter::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
405 static bool
406 IsPointerValue (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
414 void
415 ValueObjectPrinter::GetValueSummaryError (std::string& value,
416                                           std::string& summary,
417                                           std::string& error)
418 {
419     lldb::Format format = m_options.m_format;
420     // if I am printing synthetized elements, apply the format to those elements only
421     if (m_options.m_element_count > 0)
422         m_valobj->GetValueAsCString(lldb::eFormatDefault, value);
423     else if (format != eFormatDefault && format != m_valobj->GetFormat())
424         m_valobj->GetValueAsCString(format, value);
425     else
426     {
427         const char* val_cstr = m_valobj->GetValueAsCString();
428         if (val_cstr)
429             value.assign(val_cstr);
430     }
431     const char* err_cstr = m_valobj->GetError().AsCString();
432     if (err_cstr)
433         error.assign(err_cstr);
434     
435     if (ShouldPrintValueObject())
436     {
437         if (IsNil())
438             summary.assign("nil");
439         else if (IsUninitialized())
440             summary.assign("<uninitialized>");
441         else if (m_options.m_omit_summary_depth == 0)
442         {
443             TypeSummaryImpl* entry = GetSummaryFormatter();
444             if (entry)
445                 m_valobj->GetSummaryAsCString(entry, summary, m_options.m_varformat_language);
446             else
447             {
448                 const char* sum_cstr = m_valobj->GetSummaryAsCString(m_options.m_varformat_language);
449                 if (sum_cstr)
450                     summary.assign(sum_cstr);
451             }
452         }
453     }
454 }
455
456 bool
457 ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed,
458                                                   bool& summary_printed)
459 {
460     bool error_printed = false;
461     if (ShouldPrintValueObject())
462     {
463         if (!CheckScopeIfNeeded())
464             m_error.assign("out of scope");
465         if (m_error.empty())
466         {
467             GetValueSummaryError(m_value, m_summary, m_error);
468         }
469         if (m_error.size())
470         {
471             // we need to support scenarios in which it is actually fine for a value to have no type
472             // but - on the other hand - if we get an error *AND* have no type, we try to get out
473             // gracefully, since most often that combination means "could not resolve a type"
474             // and the default failure mode is quite ugly
475             if (!m_compiler_type.IsValid())
476             {
477                 m_stream->Printf(" <could not resolve type>");
478                 return false;
479             }
480             
481             error_printed = true;
482             m_stream->Printf (" <%s>\n", m_error.c_str());
483         }
484         else
485         {
486             // Make sure we have a value and make sure the summary didn't
487             // specify that the value should not be printed - and do not print
488             // the value if this thing is nil
489             // (but show the value if the user passes a format explicitly)
490             TypeSummaryImpl* entry = GetSummaryFormatter();
491             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)
492             {
493                 if (m_options.m_hide_pointer_value && IsPointerValue(m_valobj->GetCompilerType())) {}
494                 else
495                 {
496                     m_stream->Printf(" %s", m_value.c_str());
497                     value_printed = true;
498                 }
499             }
500             
501             if (m_summary.size())
502             {
503                 m_stream->Printf(" %s", m_summary.c_str());
504                 summary_printed = true;
505             }
506         }
507     }
508     return !error_printed;
509 }
510
511 bool
512 ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed,
513                                                     bool summary_printed)
514 {
515     if (ShouldPrintValueObject())
516     {
517         // let's avoid the overly verbose no description error for a nil thing
518         if (m_options.m_use_objc && !IsNil() && !IsUninitialized() && (m_options.m_element_count == 0))
519         {
520             if (!m_options.m_hide_value || !m_options.m_hide_name)
521                 m_stream->Printf(" ");
522             const char *object_desc = nullptr;
523             if (value_printed || summary_printed)
524                 object_desc = m_valobj->GetObjectDescription();
525             else
526                 object_desc = GetDescriptionForDisplay();
527             if (object_desc && *object_desc)
528             {
529                 m_stream->Printf("%s\n", object_desc);
530                 return true;
531             }
532             else if (value_printed == false && summary_printed == false)
533                 return true;
534             else
535                 return false;
536         }
537     }
538     return true;
539 }
540
541 bool
542 DumpValueObjectOptions::PointerDepth::CanAllowExpansion (bool is_root,
543                                                          TypeSummaryImpl* entry,
544                                                          ValueObject *valobj,
545                                                          const std::string& summary)
546 {
547     switch (m_mode)
548     {
549         case Mode::Always:
550             return (m_count > 0);
551         case Mode::Never:
552             return false;
553         case Mode::Default:
554             if (is_root)
555                 m_count = std::min<decltype(m_count)>(m_count,1);
556             return m_count > 0;
557         case Mode::Formatters:
558             if (!entry || entry->DoesPrintChildren(valobj) || summary.empty())
559                 return m_count > 0;
560             return false;
561     }
562     return false;
563 }
564
565 bool
566 DumpValueObjectOptions::PointerDepth::CanAllowExpansion () const
567 {
568     switch (m_mode)
569     {
570         case Mode::Always:
571         case Mode::Default:
572         case Mode::Formatters:
573             return (m_count > 0);
574         case Mode::Never:
575             return false;
576     }
577     return false;
578 }
579
580 bool
581 ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description,
582                                          DumpValueObjectOptions::PointerDepth& curr_ptr_depth)
583 {
584     const bool is_ref = IsRef ();
585     const bool is_ptr = IsPtr ();
586     const bool is_uninit = IsUninitialized();
587     
588     if (is_uninit)
589         return false;
590     
591     // if the user has specified an element count, always print children
592     // as it is explicit user demand being honored
593     if (m_options.m_element_count > 0)
594         return true;
595     
596     TypeSummaryImpl* entry = GetSummaryFormatter();
597     
598     if (m_options.m_use_objc)
599         return false;
600     
601     if (is_failed_description || m_curr_depth < m_options.m_max_depth)
602     {
603         // We will show children for all concrete types. We won't show
604         // pointer contents unless a pointer depth has been specified.
605         // We won't reference contents unless the reference is the
606         // root object (depth of zero).
607         
608         // Use a new temporary pointer depth in case we override the
609         // current pointer depth below...
610         
611         if (is_ptr || is_ref)
612         {
613             // We have a pointer or reference whose value is an address.
614             // Make sure that address is not NULL
615             AddressType ptr_address_type;
616             if (m_valobj->GetPointerValue (&ptr_address_type) == 0)
617                 return false;
618             
619             const bool is_root_level = m_curr_depth == 0;
620             
621             if (is_ref &&
622                 is_root_level)
623             {
624                 // If this is the root object (depth is zero) that we are showing
625                 // and it is a reference, and no pointer depth has been supplied
626                 // print out what it references. Don't do this at deeper depths
627                 // otherwise we can end up with infinite recursion...
628                 return true;
629             }
630             
631             return curr_ptr_depth.CanAllowExpansion(false, entry, m_valobj, m_summary);
632         }
633         
634         return (!entry || entry->DoesPrintChildren(m_valobj) || m_summary.empty());
635     }
636     return false;
637 }
638
639 bool
640 ValueObjectPrinter::ShouldExpandEmptyAggregates ()
641 {
642     TypeSummaryImpl* entry = GetSummaryFormatter();
643     
644     if (!entry)
645         return true;
646     
647     return entry->DoesPrintEmptyAggregates();
648 }
649
650 ValueObject*
651 ValueObjectPrinter::GetValueObjectForChildrenGeneration ()
652 {
653     return m_valobj;
654 }
655
656 void
657 ValueObjectPrinter::PrintChildrenPreamble ()
658 {
659     if (m_options.m_flat_output)
660     {
661         if (ShouldPrintValueObject())
662             m_stream->EOL();
663     }
664     else
665     {
666         if (ShouldPrintValueObject())
667             m_stream->PutCString(IsRef () ? ": {\n" : " {\n");
668         m_stream->IndentMore();
669     }
670 }
671
672 void
673 ValueObjectPrinter::PrintChild (ValueObjectSP child_sp,
674                                 const DumpValueObjectOptions::PointerDepth& curr_ptr_depth)
675 {
676     const uint32_t consumed_depth = (m_options.m_element_count == 0) ? 1 : 0;
677     const bool does_consume_ptr_depth = ((IsPtr() && m_options.m_element_count == 0) || IsRef());
678
679     DumpValueObjectOptions child_options(m_options);
680     child_options.SetFormat(m_options.m_format).SetSummary().SetRootValueObjectName();
681     child_options.SetScopeChecked(true).SetHideName(m_options.m_hide_name).SetHideValue(m_options.m_hide_value)
682     .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - consumed_depth : 0)
683     .SetElementCount(0);
684     
685     if (child_sp.get())
686     {
687         ValueObjectPrinter child_printer(child_sp.get(),
688                                          m_stream,
689                                          child_options,
690                                          does_consume_ptr_depth ? --curr_ptr_depth : curr_ptr_depth,
691                                          m_curr_depth + consumed_depth,
692                                          m_printed_instance_pointers);
693         child_printer.PrintValueObject();
694     }
695 }
696
697 uint32_t
698 ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot)
699 {
700     ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
701     
702     if (m_options.m_element_count > 0)
703         return m_options.m_element_count;
704     
705     size_t num_children = synth_m_valobj->GetNumChildren();
706     print_dotdotdot = false;
707     if (num_children)
708     {
709         const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
710         
711         if (num_children > max_num_children && !m_options.m_ignore_cap)
712         {
713             print_dotdotdot = true;
714             return max_num_children;
715         }
716     }
717     return num_children;
718 }
719
720 void
721 ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot)
722 {
723     if (!m_options.m_flat_output)
724     {
725         if (print_dotdotdot)
726         {
727             m_valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().ChildrenTruncated();
728             m_stream->Indent("...\n");
729         }
730         m_stream->IndentLess();
731         m_stream->Indent("}\n");
732     }
733 }
734
735 bool
736 ValueObjectPrinter::ShouldPrintEmptyBrackets (bool value_printed,
737                                               bool summary_printed)
738 {
739     ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
740     
741     if (!IsAggregate())
742         return false;
743     
744     if (m_options.m_reveal_empty_aggregates == false)
745     {
746         if (value_printed || summary_printed)
747             return false;
748     }
749     
750     if (synth_m_valobj->MightHaveChildren())
751         return true;
752     
753     if (m_val_summary_ok)
754         return false;
755     
756     return true;
757 }
758
759 ValueObjectSP
760 ValueObjectPrinter::GenerateChild (ValueObject* synth_valobj, size_t idx)
761 {
762     if (m_options.m_element_count > 0)
763     {
764         // if generating pointer-as-array children, use GetSyntheticArrayMember
765         return synth_valobj->GetSyntheticArrayMember(idx, true);
766     }
767     else
768     {
769         // otherwise, do the usual thing
770         return synth_valobj->GetChildAtIndex(idx, true);
771     }
772 }
773
774 void
775 ValueObjectPrinter::PrintChildren (bool value_printed,
776                                    bool summary_printed,
777                                    const DumpValueObjectOptions::PointerDepth& curr_ptr_depth)
778 {
779     ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
780     
781     bool print_dotdotdot = false;
782     size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
783     if (num_children)
784     {
785         bool any_children_printed = false;
786         
787         for (size_t idx=0; idx<num_children; ++idx)
788         {
789             if (ValueObjectSP child_sp = GenerateChild(synth_m_valobj, idx))
790             {
791                 if (!any_children_printed)
792                 {
793                     PrintChildrenPreamble ();
794                     any_children_printed = true;
795                 }
796                 PrintChild (child_sp, curr_ptr_depth);
797             }
798         }
799         
800         if (any_children_printed)
801             PrintChildrenPostamble (print_dotdotdot);
802         else
803         {
804             if (ShouldPrintEmptyBrackets(value_printed, summary_printed))
805             {
806                 if (ShouldPrintValueObject())
807                     m_stream->PutCString(" {}\n");
808                 else
809                     m_stream->EOL();
810             }
811             else
812                 m_stream->EOL();
813         }
814     }
815     else if (ShouldPrintEmptyBrackets(value_printed, summary_printed))
816     {
817         // Aggregate, no children...
818         if (ShouldPrintValueObject())
819         {
820             // if it has a synthetic value, then don't print {}, the synthetic children are probably only being used to vend a value
821             if (m_valobj->DoesProvideSyntheticValue() || !ShouldExpandEmptyAggregates())
822                 m_stream->PutCString( "\n");
823             else
824                 m_stream->PutCString(" {}\n");
825         }
826     }
827     else
828     {
829         if (ShouldPrintValueObject())
830             m_stream->EOL();
831     }
832 }
833
834 bool
835 ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names)
836 {
837     if (!GetMostSpecializedValue () || m_valobj == nullptr)
838         return false;
839     
840     ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
841     
842     bool print_dotdotdot = false;
843     size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
844     
845     if (num_children)
846     {
847         m_stream->PutChar('(');
848         
849         for (uint32_t idx=0; idx<num_children; ++idx)
850         {
851             lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
852             if (child_sp)
853                 child_sp = child_sp->GetQualifiedRepresentationIfAvailable(m_options.m_use_dynamic, m_options.m_use_synthetic);
854             if (child_sp)
855             {
856                 if (idx)
857                     m_stream->PutCString(", ");
858                 if (!hide_names)
859                 {
860                     const char* name = child_sp.get()->GetName().AsCString();
861                     if (name && *name)
862                     {
863                         m_stream->PutCString(name);
864                         m_stream->PutCString(" = ");
865                     }
866                 }
867                 child_sp->DumpPrintableRepresentation(*m_stream,
868                                                       ValueObject::eValueObjectRepresentationStyleSummary,
869                                                       m_options.m_format,
870                                                       ValueObject::ePrintableRepresentationSpecialCasesDisable);
871             }
872         }
873         
874         if (print_dotdotdot)
875             m_stream->PutCString(", ...)");
876         else
877             m_stream->PutChar(')');
878     }
879     return true;
880 }
881
882 void
883 ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed,
884                                            bool summary_printed)
885 {
886     // this flag controls whether we tried to display a description for this object and failed
887     // if that happens, we want to display the children, if any
888     bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed);
889     
890     auto curr_ptr_depth = m_ptr_depth;
891     bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth);
892     bool print_oneline = (curr_ptr_depth.CanAllowExpansion() ||
893                           m_options.m_show_types ||
894                           !m_options.m_allow_oneliner_mode ||
895                           m_options.m_flat_output ||
896                           (m_options.m_element_count > 0) ||
897                           m_options.m_show_location) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj);
898     bool is_instance_ptr = IsInstancePointer();
899     uint64_t instance_ptr_value = LLDB_INVALID_ADDRESS;
900     
901     if (print_children && is_instance_ptr)
902     {
903         instance_ptr_value = m_valobj->GetValueAsUnsigned(0);
904         if (m_printed_instance_pointers->count(instance_ptr_value))
905         {
906             // we already printed this instance-is-pointer thing, so don't expand it
907             m_stream->PutCString(" {...}\n");
908             
909             // we're done here - get out fast
910             return;
911         }
912         else
913             m_printed_instance_pointers->emplace(instance_ptr_value); // remember this guy for future reference
914     }
915     
916     if (print_children)
917     {
918         if (print_oneline)
919         {
920             m_stream->PutChar(' ');
921             PrintChildrenOneLiner (false);
922             m_stream->EOL();
923         }
924         else
925             PrintChildren (value_printed, summary_printed, curr_ptr_depth);
926     }
927     else if (m_curr_depth >= m_options.m_max_depth && IsAggregate() && ShouldPrintValueObject())
928     {
929         m_stream->PutCString("{...}\n");
930     }
931     else
932         m_stream->EOL();
933 }
934
935 bool
936 ValueObjectPrinter::ShouldPrintValidation ()
937 {
938     return m_options.m_run_validator;
939 }
940
941 bool
942 ValueObjectPrinter::PrintValidationMarkerIfNeeded ()
943 {
944     if (!ShouldPrintValidation())
945         return false;
946     
947     m_validation = m_valobj->GetValidationStatus();
948     
949     if (TypeValidatorResult::Failure == m_validation.first)
950     {
951         m_stream->Printf("! ");
952         return true;
953     }
954     
955     return false;
956 }
957
958 bool
959 ValueObjectPrinter::PrintValidationErrorIfNeeded ()
960 {
961     if (!ShouldPrintValidation())
962         return false;
963     
964     if (TypeValidatorResult::Success == m_validation.first)
965         return false;
966     
967     if (m_validation.second.empty())
968         m_validation.second.assign("unknown error");
969     
970     m_stream->Printf(" ! validation error: %s", m_validation.second.c_str());
971     m_stream->EOL();
972     
973     return true;
974 }