1*b9c1b51eSKate Stone //===-- ValueObjectPrinter.cpp -------------------------------------*- C++
2*b9c1b51eSKate Stone //-*-===//
34d93b8cdSEnrico Granata //
44d93b8cdSEnrico Granata //                     The LLVM Compiler Infrastructure
54d93b8cdSEnrico Granata //
64d93b8cdSEnrico Granata // This file is distributed under the University of Illinois Open Source
74d93b8cdSEnrico Granata // License. See LICENSE.TXT for details.
84d93b8cdSEnrico Granata //
94d93b8cdSEnrico Granata //===----------------------------------------------------------------------===//
104d93b8cdSEnrico Granata 
114d93b8cdSEnrico Granata #include "lldb/DataFormatters/ValueObjectPrinter.h"
124d93b8cdSEnrico Granata 
134d93b8cdSEnrico Granata // C Includes
144d93b8cdSEnrico Granata // C++ Includes
154d93b8cdSEnrico Granata // Other libraries and framework includes
164d93b8cdSEnrico Granata // Project includes
17c8e7649aSEnrico Granata #include "lldb/Core/Stream.h"
18c8e7649aSEnrico Granata #include "lldb/Core/ValueObject.h"
19a29cb0baSEnrico Granata #include "lldb/DataFormatters/DataVisualization.h"
204d93b8cdSEnrico Granata #include "lldb/Interpreter/CommandInterpreter.h"
21c8e7649aSEnrico Granata #include "lldb/Target/Language.h"
224d93b8cdSEnrico Granata #include "lldb/Target/Target.h"
234d93b8cdSEnrico Granata 
244d93b8cdSEnrico Granata using namespace lldb;
254d93b8cdSEnrico Granata using namespace lldb_private;
264d93b8cdSEnrico Granata 
27*b9c1b51eSKate Stone ValueObjectPrinter::ValueObjectPrinter(ValueObject *valobj, Stream *s) {
28*b9c1b51eSKate Stone   if (valobj) {
29d5957336SEnrico Granata     DumpValueObjectOptions options(*valobj);
308cf44d96SEnrico Granata     Init(valobj, s, options, m_options.m_max_ptr_depth, 0, nullptr);
31*b9c1b51eSKate Stone   } else {
32d5957336SEnrico Granata     DumpValueObjectOptions options;
338cf44d96SEnrico Granata     Init(valobj, s, options, m_options.m_max_ptr_depth, 0, nullptr);
34d5957336SEnrico Granata   }
35d5957336SEnrico Granata }
36d5957336SEnrico Granata 
37*b9c1b51eSKate Stone ValueObjectPrinter::ValueObjectPrinter(ValueObject *valobj, Stream *s,
38*b9c1b51eSKate Stone                                        const DumpValueObjectOptions &options) {
398cf44d96SEnrico Granata   Init(valobj, s, options, m_options.m_max_ptr_depth, 0, nullptr);
404d93b8cdSEnrico Granata }
414d93b8cdSEnrico Granata 
42*b9c1b51eSKate Stone ValueObjectPrinter::ValueObjectPrinter(
43*b9c1b51eSKate Stone     ValueObject *valobj, Stream *s, const DumpValueObjectOptions &options,
44*b9c1b51eSKate Stone     const DumpValueObjectOptions::PointerDepth &ptr_depth, uint32_t curr_depth,
45*b9c1b51eSKate Stone     InstancePointersSetSP printed_instance_pointers) {
468cf44d96SEnrico Granata   Init(valobj, s, options, ptr_depth, curr_depth, printed_instance_pointers);
47938d1d67SEnrico Granata }
48938d1d67SEnrico Granata 
49*b9c1b51eSKate Stone void ValueObjectPrinter::Init(
50*b9c1b51eSKate Stone     ValueObject *valobj, Stream *s, const DumpValueObjectOptions &options,
51*b9c1b51eSKate Stone     const DumpValueObjectOptions::PointerDepth &ptr_depth, uint32_t curr_depth,
52*b9c1b51eSKate Stone     InstancePointersSetSP printed_instance_pointers) {
53938d1d67SEnrico Granata   m_orig_valobj = valobj;
54938d1d67SEnrico Granata   m_valobj = nullptr;
55938d1d67SEnrico Granata   m_stream = s;
5626014690SGreg Clayton   m_options = options;
57938d1d67SEnrico Granata   m_ptr_depth = ptr_depth;
58938d1d67SEnrico Granata   m_curr_depth = curr_depth;
59938d1d67SEnrico Granata   assert(m_orig_valobj && "cannot print a NULL ValueObject");
60938d1d67SEnrico Granata   assert(m_stream && "cannot print to a NULL Stream");
61938d1d67SEnrico Granata   m_should_print = eLazyBoolCalculate;
62938d1d67SEnrico Granata   m_is_nil = eLazyBoolCalculate;
63608d67c1SEnrico Granata   m_is_uninit = eLazyBoolCalculate;
64938d1d67SEnrico Granata   m_is_ptr = eLazyBoolCalculate;
65938d1d67SEnrico Granata   m_is_ref = eLazyBoolCalculate;
66938d1d67SEnrico Granata   m_is_aggregate = eLazyBoolCalculate;
678cf44d96SEnrico Granata   m_is_instance_ptr = eLazyBoolCalculate;
68938d1d67SEnrico Granata   m_summary_formatter = {nullptr, false};
69938d1d67SEnrico Granata   m_value.assign("");
70938d1d67SEnrico Granata   m_summary.assign("");
71938d1d67SEnrico Granata   m_error.assign("");
728cf44d96SEnrico Granata   m_val_summary_ok = false;
73*b9c1b51eSKate Stone   m_printed_instance_pointers =
74*b9c1b51eSKate Stone       printed_instance_pointers
75*b9c1b51eSKate Stone           ? printed_instance_pointers
76*b9c1b51eSKate Stone           : InstancePointersSetSP(new InstancePointersSet());
77938d1d67SEnrico Granata }
784d93b8cdSEnrico Granata 
79*b9c1b51eSKate Stone bool ValueObjectPrinter::PrintValueObject() {
80d07cfd3aSEnrico Granata   if (!GetMostSpecializedValue() || m_valobj == nullptr)
814d93b8cdSEnrico Granata     return false;
824d93b8cdSEnrico Granata 
83*b9c1b51eSKate Stone   if (ShouldPrintValueObject()) {
840f883ffbSEnrico Granata     PrintValidationMarkerIfNeeded();
850f883ffbSEnrico Granata 
864d93b8cdSEnrico Granata     PrintLocationIfNeeded();
874d93b8cdSEnrico Granata     m_stream->Indent();
884d93b8cdSEnrico Granata 
89e0ee1e1cSEnrico Granata     PrintDecl();
904d93b8cdSEnrico Granata   }
914d93b8cdSEnrico Granata 
924d93b8cdSEnrico Granata   bool value_printed = false;
934d93b8cdSEnrico Granata   bool summary_printed = false;
944d93b8cdSEnrico Granata 
95*b9c1b51eSKate Stone   m_val_summary_ok =
96*b9c1b51eSKate Stone       PrintValueAndSummaryIfNeeded(value_printed, summary_printed);
974d93b8cdSEnrico Granata 
988cf44d96SEnrico Granata   if (m_val_summary_ok)
994d93b8cdSEnrico Granata     PrintChildrenIfNeeded(value_printed, summary_printed);
10039938938SEnrico Granata   else
1014d93b8cdSEnrico Granata     m_stream->EOL();
1024d93b8cdSEnrico Granata 
1030f883ffbSEnrico Granata   PrintValidationErrorIfNeeded();
1040f883ffbSEnrico Granata 
1054d93b8cdSEnrico Granata   return true;
1064d93b8cdSEnrico Granata }
1074d93b8cdSEnrico Granata 
108*b9c1b51eSKate Stone bool ValueObjectPrinter::GetMostSpecializedValue() {
109a29cb0baSEnrico Granata   if (m_valobj)
110a29cb0baSEnrico Granata     return true;
1114d93b8cdSEnrico Granata   bool update_success = m_orig_valobj->UpdateValueIfNeeded(true);
112*b9c1b51eSKate Stone   if (!update_success) {
113106260c5SEnrico Granata     m_valobj = m_orig_valobj;
114*b9c1b51eSKate Stone   } else {
115*b9c1b51eSKate Stone     if (m_orig_valobj->IsDynamic()) {
116*b9c1b51eSKate Stone       if (m_options.m_use_dynamic == eNoDynamicValues) {
117106260c5SEnrico Granata         ValueObject *static_value = m_orig_valobj->GetStaticValue().get();
118106260c5SEnrico Granata         if (static_value)
119106260c5SEnrico Granata           m_valobj = static_value;
120106260c5SEnrico Granata         else
121106260c5SEnrico Granata           m_valobj = m_orig_valobj;
122*b9c1b51eSKate Stone       } else
123106260c5SEnrico Granata         m_valobj = m_orig_valobj;
124*b9c1b51eSKate Stone     } else {
125*b9c1b51eSKate Stone       if (m_options.m_use_dynamic != eNoDynamicValues) {
126*b9c1b51eSKate Stone         ValueObject *dynamic_value =
127*b9c1b51eSKate Stone             m_orig_valobj->GetDynamicValue(m_options.m_use_dynamic).get();
1284d93b8cdSEnrico Granata         if (dynamic_value)
1294d93b8cdSEnrico Granata           m_valobj = dynamic_value;
1304d93b8cdSEnrico Granata         else
1314d93b8cdSEnrico Granata           m_valobj = m_orig_valobj;
132*b9c1b51eSKate Stone       } else
1334d93b8cdSEnrico Granata         m_valobj = m_orig_valobj;
134106260c5SEnrico Granata     }
135d07cfd3aSEnrico Granata 
136*b9c1b51eSKate Stone     if (m_valobj->IsSynthetic()) {
137*b9c1b51eSKate Stone       if (m_options.m_use_synthetic == false) {
138d07cfd3aSEnrico Granata         ValueObject *non_synthetic = m_valobj->GetNonSyntheticValue().get();
139d07cfd3aSEnrico Granata         if (non_synthetic)
140d07cfd3aSEnrico Granata           m_valobj = non_synthetic;
141d07cfd3aSEnrico Granata       }
142*b9c1b51eSKate Stone     } else {
143*b9c1b51eSKate Stone       if (m_options.m_use_synthetic == true) {
144d07cfd3aSEnrico Granata         ValueObject *synthetic = m_valobj->GetSyntheticValue().get();
145d07cfd3aSEnrico Granata         if (synthetic)
146d07cfd3aSEnrico Granata           m_valobj = synthetic;
147d07cfd3aSEnrico Granata       }
148d07cfd3aSEnrico Granata     }
149106260c5SEnrico Granata   }
15059b5a37dSBruce Mitchener   m_compiler_type = m_valobj->GetCompilerType();
15159b5a37dSBruce Mitchener   m_type_flags = m_compiler_type.GetTypeInfo();
1524d93b8cdSEnrico Granata   return true;
1534d93b8cdSEnrico Granata }
1544d93b8cdSEnrico Granata 
155*b9c1b51eSKate Stone const char *ValueObjectPrinter::GetDescriptionForDisplay() {
1564d93b8cdSEnrico Granata   const char *str = m_valobj->GetObjectDescription();
1574d93b8cdSEnrico Granata   if (!str)
1584d93b8cdSEnrico Granata     str = m_valobj->GetSummaryAsCString();
1594d93b8cdSEnrico Granata   if (!str)
1604d93b8cdSEnrico Granata     str = m_valobj->GetValueAsCString();
1614d93b8cdSEnrico Granata   return str;
1624d93b8cdSEnrico Granata }
1634d93b8cdSEnrico Granata 
164*b9c1b51eSKate Stone const char *ValueObjectPrinter::GetRootNameForDisplay(const char *if_fail) {
165*b9c1b51eSKate Stone   const char *root_valobj_name = m_options.m_root_valobj_name.empty()
166*b9c1b51eSKate Stone                                      ? m_valobj->GetName().AsCString()
167*b9c1b51eSKate Stone                                      : m_options.m_root_valobj_name.c_str();
1684d93b8cdSEnrico Granata   return root_valobj_name ? root_valobj_name : if_fail;
1694d93b8cdSEnrico Granata }
1704d93b8cdSEnrico Granata 
171*b9c1b51eSKate Stone bool ValueObjectPrinter::ShouldPrintValueObject() {
1724d93b8cdSEnrico Granata   if (m_should_print == eLazyBoolCalculate)
173*b9c1b51eSKate Stone     m_should_print =
174*b9c1b51eSKate Stone         (m_options.m_flat_output == false || m_type_flags.Test(eTypeHasValue))
175*b9c1b51eSKate Stone             ? eLazyBoolYes
176*b9c1b51eSKate Stone             : eLazyBoolNo;
1774d93b8cdSEnrico Granata   return m_should_print == eLazyBoolYes;
1784d93b8cdSEnrico Granata }
1794d93b8cdSEnrico Granata 
180*b9c1b51eSKate Stone bool ValueObjectPrinter::IsNil() {
1814d93b8cdSEnrico Granata   if (m_is_nil == eLazyBoolCalculate)
182608d67c1SEnrico Granata     m_is_nil = m_valobj->IsNilReference() ? eLazyBoolYes : eLazyBoolNo;
1834d93b8cdSEnrico Granata   return m_is_nil == eLazyBoolYes;
1844d93b8cdSEnrico Granata }
1854d93b8cdSEnrico Granata 
186*b9c1b51eSKate Stone bool ValueObjectPrinter::IsUninitialized() {
187608d67c1SEnrico Granata   if (m_is_uninit == eLazyBoolCalculate)
188*b9c1b51eSKate Stone     m_is_uninit =
189*b9c1b51eSKate Stone         m_valobj->IsUninitializedReference() ? eLazyBoolYes : eLazyBoolNo;
190608d67c1SEnrico Granata   return m_is_uninit == eLazyBoolYes;
191608d67c1SEnrico Granata }
192608d67c1SEnrico Granata 
193*b9c1b51eSKate Stone bool ValueObjectPrinter::IsPtr() {
1944d93b8cdSEnrico Granata   if (m_is_ptr == eLazyBoolCalculate)
195622be238SEnrico Granata     m_is_ptr = m_type_flags.Test(eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo;
1964d93b8cdSEnrico Granata   return m_is_ptr == eLazyBoolYes;
1974d93b8cdSEnrico Granata }
1984d93b8cdSEnrico Granata 
199*b9c1b51eSKate Stone bool ValueObjectPrinter::IsRef() {
2004d93b8cdSEnrico Granata   if (m_is_ref == eLazyBoolCalculate)
201622be238SEnrico Granata     m_is_ref = m_type_flags.Test(eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo;
2024d93b8cdSEnrico Granata   return m_is_ref == eLazyBoolYes;
2034d93b8cdSEnrico Granata }
2044d93b8cdSEnrico Granata 
205*b9c1b51eSKate Stone bool ValueObjectPrinter::IsAggregate() {
2064d93b8cdSEnrico Granata   if (m_is_aggregate == eLazyBoolCalculate)
207*b9c1b51eSKate Stone     m_is_aggregate =
208*b9c1b51eSKate Stone         m_type_flags.Test(eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo;
2094d93b8cdSEnrico Granata   return m_is_aggregate == eLazyBoolYes;
2104d93b8cdSEnrico Granata }
2114d93b8cdSEnrico Granata 
212*b9c1b51eSKate Stone bool ValueObjectPrinter::IsInstancePointer() {
2138cf44d96SEnrico Granata   // you need to do this check on the value's clang type
2148cf44d96SEnrico Granata   if (m_is_instance_ptr == eLazyBoolCalculate)
215*b9c1b51eSKate Stone     m_is_instance_ptr = (m_valobj->GetValue().GetCompilerType().GetTypeInfo() &
216*b9c1b51eSKate Stone                          eTypeInstanceIsPointer) != 0
217*b9c1b51eSKate Stone                             ? eLazyBoolYes
218*b9c1b51eSKate Stone                             : eLazyBoolNo;
2198cf44d96SEnrico Granata   if ((eLazyBoolYes == m_is_instance_ptr) && m_valobj->IsBaseClass())
2208cf44d96SEnrico Granata     m_is_instance_ptr = eLazyBoolNo;
2218cf44d96SEnrico Granata   return m_is_instance_ptr == eLazyBoolYes;
2228cf44d96SEnrico Granata }
2238cf44d96SEnrico Granata 
224*b9c1b51eSKate Stone bool ValueObjectPrinter::PrintLocationIfNeeded() {
225*b9c1b51eSKate Stone   if (m_options.m_show_location) {
2264d93b8cdSEnrico Granata     m_stream->Printf("%s: ", m_valobj->GetLocationAsCString());
2274d93b8cdSEnrico Granata     return true;
2284d93b8cdSEnrico Granata   }
2294d93b8cdSEnrico Granata   return false;
2304d93b8cdSEnrico Granata }
2314d93b8cdSEnrico Granata 
232*b9c1b51eSKate Stone void ValueObjectPrinter::PrintDecl() {
2334d93b8cdSEnrico Granata   bool show_type = true;
234*b9c1b51eSKate Stone   // if we are at the root-level and been asked to hide the root's type, then
235*b9c1b51eSKate Stone   // hide it
23626014690SGreg Clayton   if (m_curr_depth == 0 && m_options.m_hide_root_type)
2374d93b8cdSEnrico Granata     show_type = false;
2384d93b8cdSEnrico Granata   else
239*b9c1b51eSKate Stone     // otherwise decide according to the usual rules (asked to show types -
240*b9c1b51eSKate Stone     // always at the root level)
241*b9c1b51eSKate Stone     show_type = m_options.m_show_types ||
242*b9c1b51eSKate Stone                 (m_curr_depth == 0 && !m_options.m_flat_output);
2434d93b8cdSEnrico Granata 
244e0ee1e1cSEnrico Granata   StreamString typeName;
245e0ee1e1cSEnrico Granata 
246e0ee1e1cSEnrico Granata   // always show the type at the root level if it is invalid
247*b9c1b51eSKate Stone   if (show_type) {
2484d93b8cdSEnrico Granata     // Some ValueObjects don't have types (like registers sets). Only print
2494d93b8cdSEnrico Granata     // the type if there is one to print
250a126e462SEnrico Granata     ConstString type_name;
251*b9c1b51eSKate Stone     if (m_compiler_type.IsValid()) {
25226014690SGreg Clayton       if (m_options.m_use_type_display_name)
253a126e462SEnrico Granata         type_name = m_valobj->GetDisplayTypeName();
254e8daa2f8SEnrico Granata       else
255a126e462SEnrico Granata         type_name = m_valobj->GetQualifiedTypeName();
256*b9c1b51eSKate Stone     } else {
257*b9c1b51eSKate Stone       // only show an invalid type name if the user explicitly triggered
258*b9c1b51eSKate Stone       // show_type
25926014690SGreg Clayton       if (m_options.m_show_types)
260e0ee1e1cSEnrico Granata         type_name = ConstString("<invalid type>");
261e0ee1e1cSEnrico Granata       else
262e0ee1e1cSEnrico Granata         type_name.Clear();
2634d93b8cdSEnrico Granata     }
2644d93b8cdSEnrico Granata 
265*b9c1b51eSKate Stone     if (type_name) {
266e0ee1e1cSEnrico Granata       std::string type_name_str(type_name.GetCString());
267*b9c1b51eSKate Stone       if (m_options.m_hide_pointer_value) {
268*b9c1b51eSKate Stone         for (auto iter = type_name_str.find(" *"); iter != std::string::npos;
269*b9c1b51eSKate Stone              iter = type_name_str.find(" *")) {
270e0ee1e1cSEnrico Granata           type_name_str.erase(iter, 2);
271e0ee1e1cSEnrico Granata         }
272e0ee1e1cSEnrico Granata       }
273c8e7649aSEnrico Granata       typeName.Printf("%s", type_name_str.c_str());
274e0ee1e1cSEnrico Granata     }
275e0ee1e1cSEnrico Granata   }
276e0ee1e1cSEnrico Granata 
277e0ee1e1cSEnrico Granata   StreamString varName;
278e0ee1e1cSEnrico Granata 
279*b9c1b51eSKate Stone   if (m_options.m_flat_output) {
2804d93b8cdSEnrico Granata     // If we are showing types, also qualify the C++ base classes
2814d93b8cdSEnrico Granata     const bool qualify_cxx_base_classes = show_type;
282*b9c1b51eSKate Stone     if (!m_options.m_hide_name) {
283e0ee1e1cSEnrico Granata       m_valobj->GetExpressionPath(varName, qualify_cxx_base_classes);
2844d93b8cdSEnrico Granata     }
285*b9c1b51eSKate Stone   } else if (!m_options.m_hide_name) {
2864d93b8cdSEnrico Granata     const char *name_cstr = GetRootNameForDisplay("");
287e0ee1e1cSEnrico Granata     varName.Printf("%s", name_cstr);
2884d93b8cdSEnrico Granata   }
289e0ee1e1cSEnrico Granata 
290e0ee1e1cSEnrico Granata   bool decl_printed = false;
291*b9c1b51eSKate Stone   if (!m_options.m_decl_printing_helper) {
292*b9c1b51eSKate Stone     // if the user didn't give us a custom helper, pick one based upon the
293*b9c1b51eSKate Stone     // language, either the one that this printer is bound to, or the preferred
294*b9c1b51eSKate Stone     // one for the ValueObject
295*b9c1b51eSKate Stone     lldb::LanguageType lang_type =
296*b9c1b51eSKate Stone         (m_options.m_varformat_language == lldb::eLanguageTypeUnknown)
297*b9c1b51eSKate Stone             ? m_valobj->GetPreferredDisplayLanguage()
298*b9c1b51eSKate Stone             : m_options.m_varformat_language;
299*b9c1b51eSKate Stone     if (Language *lang_plugin = Language::FindPlugin(lang_type)) {
30026014690SGreg Clayton       m_options.m_decl_printing_helper = lang_plugin->GetDeclPrintingHelper();
301c8e7649aSEnrico Granata     }
302c8e7649aSEnrico Granata   }
303c8e7649aSEnrico Granata 
304*b9c1b51eSKate Stone   if (m_options.m_decl_printing_helper) {
305e0ee1e1cSEnrico Granata     ConstString type_name_cstr(typeName.GetData());
306e0ee1e1cSEnrico Granata     ConstString var_name_cstr(varName.GetData());
307e0ee1e1cSEnrico Granata 
308e0ee1e1cSEnrico Granata     StreamString dest_stream;
309*b9c1b51eSKate Stone     if (m_options.m_decl_printing_helper(type_name_cstr, var_name_cstr,
310*b9c1b51eSKate Stone                                          m_options, dest_stream)) {
311e0ee1e1cSEnrico Granata       decl_printed = true;
312e0ee1e1cSEnrico Granata       m_stream->Printf("%s", dest_stream.GetData());
313e0ee1e1cSEnrico Granata     }
314e0ee1e1cSEnrico Granata   }
315e0ee1e1cSEnrico Granata 
316c8e7649aSEnrico Granata   // if the helper failed, or there is none, do a default thing
317*b9c1b51eSKate Stone   if (!decl_printed) {
318e0ee1e1cSEnrico Granata     if (typeName.GetSize())
319c8e7649aSEnrico Granata       m_stream->Printf("(%s) ", typeName.GetData());
320e0ee1e1cSEnrico Granata     if (varName.GetSize())
321e0ee1e1cSEnrico Granata       m_stream->Printf("%s =", varName.GetData());
32226014690SGreg Clayton     else if (!m_options.m_hide_name)
323e0ee1e1cSEnrico Granata       m_stream->Printf(" =");
324e0ee1e1cSEnrico Granata   }
3254d93b8cdSEnrico Granata }
3264d93b8cdSEnrico Granata 
327*b9c1b51eSKate Stone bool ValueObjectPrinter::CheckScopeIfNeeded() {
32826014690SGreg Clayton   if (m_options.m_scope_already_checked)
3294d93b8cdSEnrico Granata     return true;
3304d93b8cdSEnrico Granata   return m_valobj->IsInScope();
3314d93b8cdSEnrico Granata }
3324d93b8cdSEnrico Granata 
333*b9c1b51eSKate Stone TypeSummaryImpl *ValueObjectPrinter::GetSummaryFormatter(bool null_if_omitted) {
334*b9c1b51eSKate Stone   if (m_summary_formatter.second == false) {
335*b9c1b51eSKate Stone     TypeSummaryImpl *entry = m_options.m_summary_sp
336*b9c1b51eSKate Stone                                  ? m_options.m_summary_sp.get()
337*b9c1b51eSKate Stone                                  : m_valobj->GetSummaryFormat().get();
3384d93b8cdSEnrico Granata 
33926014690SGreg Clayton     if (m_options.m_omit_summary_depth > 0)
3404d93b8cdSEnrico Granata       entry = NULL;
3414d93b8cdSEnrico Granata     m_summary_formatter.first = entry;
3424d93b8cdSEnrico Granata     m_summary_formatter.second = true;
3434d93b8cdSEnrico Granata   }
3448cf44d96SEnrico Granata   if (m_options.m_omit_summary_depth > 0 && null_if_omitted)
3458cf44d96SEnrico Granata     return nullptr;
3464d93b8cdSEnrico Granata   return m_summary_formatter.first;
3474d93b8cdSEnrico Granata }
3484d93b8cdSEnrico Granata 
349*b9c1b51eSKate Stone static bool IsPointerValue(const CompilerType &type) {
350e0ee1e1cSEnrico Granata   Flags type_flags(type.GetTypeInfo());
3518cf44d96SEnrico Granata   if (type_flags.AnySet(eTypeInstanceIsPointer | eTypeIsPointer))
352e0ee1e1cSEnrico Granata     return type_flags.AllClear(eTypeIsBuiltIn);
353e0ee1e1cSEnrico Granata   return false;
354e0ee1e1cSEnrico Granata }
355e0ee1e1cSEnrico Granata 
356*b9c1b51eSKate Stone void ValueObjectPrinter::GetValueSummaryError(std::string &value,
3574d93b8cdSEnrico Granata                                               std::string &summary,
358*b9c1b51eSKate Stone                                               std::string &error) {
359520a422bSEnrico Granata   lldb::Format format = m_options.m_format;
360*b9c1b51eSKate Stone   // if I am printing synthetized elements, apply the format to those elements
361*b9c1b51eSKate Stone   // only
362520a422bSEnrico Granata   if (m_options.m_element_count > 0)
363520a422bSEnrico Granata     m_valobj->GetValueAsCString(lldb::eFormatDefault, value);
364520a422bSEnrico Granata   else if (format != eFormatDefault && format != m_valobj->GetFormat())
365520a422bSEnrico Granata     m_valobj->GetValueAsCString(format, value);
366*b9c1b51eSKate Stone   else {
3674d93b8cdSEnrico Granata     const char *val_cstr = m_valobj->GetValueAsCString();
368465f4bc2SEnrico Granata     if (val_cstr)
369465f4bc2SEnrico Granata       value.assign(val_cstr);
370465f4bc2SEnrico Granata   }
3714d93b8cdSEnrico Granata   const char *err_cstr = m_valobj->GetError().AsCString();
3724d93b8cdSEnrico Granata   if (err_cstr)
3734d93b8cdSEnrico Granata     error.assign(err_cstr);
3744d93b8cdSEnrico Granata 
375*b9c1b51eSKate Stone   if (ShouldPrintValueObject()) {
3764d93b8cdSEnrico Granata     if (IsNil())
3774d93b8cdSEnrico Granata       summary.assign("nil");
378608d67c1SEnrico Granata     else if (IsUninitialized())
379608d67c1SEnrico Granata       summary.assign("<uninitialized>");
380*b9c1b51eSKate Stone     else if (m_options.m_omit_summary_depth == 0) {
3814d93b8cdSEnrico Granata       TypeSummaryImpl *entry = GetSummaryFormatter();
3824d93b8cdSEnrico Granata       if (entry)
383*b9c1b51eSKate Stone         m_valobj->GetSummaryAsCString(entry, summary,
384*b9c1b51eSKate Stone                                       m_options.m_varformat_language);
385*b9c1b51eSKate Stone       else {
386*b9c1b51eSKate Stone         const char *sum_cstr =
387*b9c1b51eSKate Stone             m_valobj->GetSummaryAsCString(m_options.m_varformat_language);
3884d93b8cdSEnrico Granata         if (sum_cstr)
3894d93b8cdSEnrico Granata           summary.assign(sum_cstr);
3904d93b8cdSEnrico Granata       }
3914d93b8cdSEnrico Granata     }
3924d93b8cdSEnrico Granata   }
3934d93b8cdSEnrico Granata }
3944d93b8cdSEnrico Granata 
395*b9c1b51eSKate Stone bool ValueObjectPrinter::PrintValueAndSummaryIfNeeded(bool &value_printed,
396*b9c1b51eSKate Stone                                                       bool &summary_printed) {
3974d93b8cdSEnrico Granata   bool error_printed = false;
398*b9c1b51eSKate Stone   if (ShouldPrintValueObject()) {
3994d93b8cdSEnrico Granata     if (!CheckScopeIfNeeded())
4004d93b8cdSEnrico Granata       m_error.assign("out of scope");
401*b9c1b51eSKate Stone     if (m_error.empty()) {
4024d93b8cdSEnrico Granata       GetValueSummaryError(m_value, m_summary, m_error);
4034d93b8cdSEnrico Granata     }
404*b9c1b51eSKate Stone     if (m_error.size()) {
405*b9c1b51eSKate Stone       // we need to support scenarios in which it is actually fine for a value
406*b9c1b51eSKate Stone       // to have no type
407*b9c1b51eSKate Stone       // but - on the other hand - if we get an error *AND* have no type, we try
408*b9c1b51eSKate Stone       // to get out
409*b9c1b51eSKate Stone       // gracefully, since most often that combination means "could not resolve
410*b9c1b51eSKate Stone       // a type"
4118cf44d96SEnrico Granata       // and the default failure mode is quite ugly
412*b9c1b51eSKate Stone       if (!m_compiler_type.IsValid()) {
4138cf44d96SEnrico Granata         m_stream->Printf(" <could not resolve type>");
4148cf44d96SEnrico Granata         return false;
4158cf44d96SEnrico Granata       }
4168cf44d96SEnrico Granata 
4174d93b8cdSEnrico Granata       error_printed = true;
4184d93b8cdSEnrico Granata       m_stream->Printf(" <%s>\n", m_error.c_str());
419*b9c1b51eSKate Stone     } else {
4204d93b8cdSEnrico Granata       // Make sure we have a value and make sure the summary didn't
4214d93b8cdSEnrico Granata       // specify that the value should not be printed - and do not print
4224d93b8cdSEnrico Granata       // the value if this thing is nil
4234d93b8cdSEnrico Granata       // (but show the value if the user passes a format explicitly)
4244d93b8cdSEnrico Granata       TypeSummaryImpl *entry = GetSummaryFormatter();
425*b9c1b51eSKate Stone       if (!IsNil() && !IsUninitialized() && !m_value.empty() &&
426*b9c1b51eSKate Stone           (entry == NULL || (entry->DoesPrintValue(m_valobj) ||
427*b9c1b51eSKate Stone                              m_options.m_format != eFormatDefault) ||
428*b9c1b51eSKate Stone            m_summary.empty()) &&
429*b9c1b51eSKate Stone           !m_options.m_hide_value) {
430*b9c1b51eSKate Stone         if (m_options.m_hide_pointer_value &&
431*b9c1b51eSKate Stone             IsPointerValue(m_valobj->GetCompilerType())) {
432*b9c1b51eSKate Stone         } else {
4334d93b8cdSEnrico Granata           m_stream->Printf(" %s", m_value.c_str());
4344d93b8cdSEnrico Granata           value_printed = true;
4354d93b8cdSEnrico Granata         }
436e0ee1e1cSEnrico Granata       }
4374d93b8cdSEnrico Granata 
438*b9c1b51eSKate Stone       if (m_summary.size()) {
4394d93b8cdSEnrico Granata         m_stream->Printf(" %s", m_summary.c_str());
4404d93b8cdSEnrico Granata         summary_printed = true;
4414d93b8cdSEnrico Granata       }
4424d93b8cdSEnrico Granata     }
4434d93b8cdSEnrico Granata   }
4444d93b8cdSEnrico Granata   return !error_printed;
4454d93b8cdSEnrico Granata }
4464d93b8cdSEnrico Granata 
447*b9c1b51eSKate Stone bool ValueObjectPrinter::PrintObjectDescriptionIfNeeded(bool value_printed,
448*b9c1b51eSKate Stone                                                         bool summary_printed) {
449*b9c1b51eSKate Stone   if (ShouldPrintValueObject()) {
4504d93b8cdSEnrico Granata     // let's avoid the overly verbose no description error for a nil thing
451*b9c1b51eSKate Stone     if (m_options.m_use_objc && !IsNil() && !IsUninitialized() &&
452*b9c1b51eSKate Stone         (m_options.m_element_count == 0)) {
45326014690SGreg Clayton       if (!m_options.m_hide_value || !m_options.m_hide_name)
4544d93b8cdSEnrico Granata         m_stream->Printf(" ");
4554d93b8cdSEnrico Granata       const char *object_desc = nullptr;
4564d93b8cdSEnrico Granata       if (value_printed || summary_printed)
4574d93b8cdSEnrico Granata         object_desc = m_valobj->GetObjectDescription();
4584d93b8cdSEnrico Granata       else
4594d93b8cdSEnrico Granata         object_desc = GetDescriptionForDisplay();
460*b9c1b51eSKate Stone       if (object_desc && *object_desc) {
4614d93b8cdSEnrico Granata         m_stream->Printf("%s\n", object_desc);
4624d93b8cdSEnrico Granata         return true;
463*b9c1b51eSKate Stone       } else if (value_printed == false && summary_printed == false)
4644d93b8cdSEnrico Granata         return true;
4654d93b8cdSEnrico Granata       else
4664d93b8cdSEnrico Granata         return false;
4674d93b8cdSEnrico Granata     }
4684d93b8cdSEnrico Granata   }
4694d93b8cdSEnrico Granata   return true;
4704d93b8cdSEnrico Granata }
4714d93b8cdSEnrico Granata 
472*b9c1b51eSKate Stone bool DumpValueObjectOptions::PointerDepth::CanAllowExpansion(
473*b9c1b51eSKate Stone     bool is_root, TypeSummaryImpl *entry, ValueObject *valobj,
474*b9c1b51eSKate Stone     const std::string &summary) {
475*b9c1b51eSKate Stone   switch (m_mode) {
476c1b7c09aSEnrico Granata   case Mode::Always:
477c1b7c09aSEnrico Granata     return (m_count > 0);
478c1b7c09aSEnrico Granata   case Mode::Never:
479c1b7c09aSEnrico Granata     return false;
480c1b7c09aSEnrico Granata   case Mode::Default:
481c1b7c09aSEnrico Granata     if (is_root)
482c1b7c09aSEnrico Granata       m_count = std::min<decltype(m_count)>(m_count, 1);
483c1b7c09aSEnrico Granata     return m_count > 0;
484c1b7c09aSEnrico Granata   case Mode::Formatters:
485c1b7c09aSEnrico Granata     if (!entry || entry->DoesPrintChildren(valobj) || summary.empty())
486c1b7c09aSEnrico Granata       return m_count > 0;
487c1b7c09aSEnrico Granata     return false;
488c1b7c09aSEnrico Granata   }
48984f5b0dfSZachary Turner   return false;
490c1b7c09aSEnrico Granata }
491c1b7c09aSEnrico Granata 
492*b9c1b51eSKate Stone bool DumpValueObjectOptions::PointerDepth::CanAllowExpansion() const {
493*b9c1b51eSKate Stone   switch (m_mode) {
494c1b7c09aSEnrico Granata   case Mode::Always:
495c1b7c09aSEnrico Granata   case Mode::Default:
496c1b7c09aSEnrico Granata   case Mode::Formatters:
497c1b7c09aSEnrico Granata     return (m_count > 0);
498c1b7c09aSEnrico Granata   case Mode::Never:
499c1b7c09aSEnrico Granata     return false;
500c1b7c09aSEnrico Granata   }
50184f5b0dfSZachary Turner   return false;
502c1b7c09aSEnrico Granata }
503c1b7c09aSEnrico Granata 
504*b9c1b51eSKate Stone bool ValueObjectPrinter::ShouldPrintChildren(
505*b9c1b51eSKate Stone     bool is_failed_description,
506*b9c1b51eSKate Stone     DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {
5074d93b8cdSEnrico Granata   const bool is_ref = IsRef();
5084d93b8cdSEnrico Granata   const bool is_ptr = IsPtr();
509608d67c1SEnrico Granata   const bool is_uninit = IsUninitialized();
510608d67c1SEnrico Granata 
511608d67c1SEnrico Granata   if (is_uninit)
512608d67c1SEnrico Granata     return false;
5134d93b8cdSEnrico Granata 
514520a422bSEnrico Granata   // if the user has specified an element count, always print children
515520a422bSEnrico Granata   // as it is explicit user demand being honored
516520a422bSEnrico Granata   if (m_options.m_element_count > 0)
517520a422bSEnrico Granata     return true;
518520a422bSEnrico Granata 
519c1b7c09aSEnrico Granata   TypeSummaryImpl *entry = GetSummaryFormatter();
520c1b7c09aSEnrico Granata 
5218cf44d96SEnrico Granata   if (m_options.m_use_objc)
5228cf44d96SEnrico Granata     return false;
5238cf44d96SEnrico Granata 
524*b9c1b51eSKate Stone   if (is_failed_description || m_curr_depth < m_options.m_max_depth) {
5254d93b8cdSEnrico Granata     // We will show children for all concrete types. We won't show
5264d93b8cdSEnrico Granata     // pointer contents unless a pointer depth has been specified.
5274d93b8cdSEnrico Granata     // We won't reference contents unless the reference is the
5284d93b8cdSEnrico Granata     // root object (depth of zero).
5294d93b8cdSEnrico Granata 
5304d93b8cdSEnrico Granata     // Use a new temporary pointer depth in case we override the
5314d93b8cdSEnrico Granata     // current pointer depth below...
5324d93b8cdSEnrico Granata 
533*b9c1b51eSKate Stone     if (is_ptr || is_ref) {
5344d93b8cdSEnrico Granata       // We have a pointer or reference whose value is an address.
5354d93b8cdSEnrico Granata       // Make sure that address is not NULL
5364d93b8cdSEnrico Granata       AddressType ptr_address_type;
5374d93b8cdSEnrico Granata       if (m_valobj->GetPointerValue(&ptr_address_type) == 0)
5384d93b8cdSEnrico Granata         return false;
5394d93b8cdSEnrico Granata 
540c1b7c09aSEnrico Granata       const bool is_root_level = m_curr_depth == 0;
541c1b7c09aSEnrico Granata 
542*b9c1b51eSKate Stone       if (is_ref && is_root_level) {
5434d93b8cdSEnrico Granata         // If this is the root object (depth is zero) that we are showing
5444d93b8cdSEnrico Granata         // and it is a reference, and no pointer depth has been supplied
5454d93b8cdSEnrico Granata         // print out what it references. Don't do this at deeper depths
5464d93b8cdSEnrico Granata         // otherwise we can end up with infinite recursion...
547c1b7c09aSEnrico Granata         return true;
5484d93b8cdSEnrico Granata       }
5494d93b8cdSEnrico Granata 
550*b9c1b51eSKate Stone       return curr_ptr_depth.CanAllowExpansion(false, entry, m_valobj,
551*b9c1b51eSKate Stone                                               m_summary);
5524d93b8cdSEnrico Granata     }
5534d93b8cdSEnrico Granata 
5548a068e6cSEnrico Granata     return (!entry || entry->DoesPrintChildren(m_valobj) || m_summary.empty());
5554d93b8cdSEnrico Granata   }
5564d93b8cdSEnrico Granata   return false;
5574d93b8cdSEnrico Granata }
5584d93b8cdSEnrico Granata 
559*b9c1b51eSKate Stone bool ValueObjectPrinter::ShouldExpandEmptyAggregates() {
560d26eb907SSiva Chandra   TypeSummaryImpl *entry = GetSummaryFormatter();
561d26eb907SSiva Chandra 
562d26eb907SSiva Chandra   if (!entry)
563d26eb907SSiva Chandra     return true;
564d26eb907SSiva Chandra 
565d26eb907SSiva Chandra   return entry->DoesPrintEmptyAggregates();
566d26eb907SSiva Chandra }
567d26eb907SSiva Chandra 
568*b9c1b51eSKate Stone ValueObject *ValueObjectPrinter::GetValueObjectForChildrenGeneration() {
569d07cfd3aSEnrico Granata   return m_valobj;
5704d93b8cdSEnrico Granata }
5714d93b8cdSEnrico Granata 
572*b9c1b51eSKate Stone void ValueObjectPrinter::PrintChildrenPreamble() {
573*b9c1b51eSKate Stone   if (m_options.m_flat_output) {
5744d93b8cdSEnrico Granata     if (ShouldPrintValueObject())
5754d93b8cdSEnrico Granata       m_stream->EOL();
576*b9c1b51eSKate Stone   } else {
5774d93b8cdSEnrico Granata     if (ShouldPrintValueObject())
5784d93b8cdSEnrico Granata       m_stream->PutCString(IsRef() ? ": {\n" : " {\n");
5794d93b8cdSEnrico Granata     m_stream->IndentMore();
5804d93b8cdSEnrico Granata   }
5814d93b8cdSEnrico Granata }
5824d93b8cdSEnrico Granata 
583*b9c1b51eSKate Stone void ValueObjectPrinter::PrintChild(
584*b9c1b51eSKate Stone     ValueObjectSP child_sp,
585*b9c1b51eSKate Stone     const DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {
586520a422bSEnrico Granata   const uint32_t consumed_depth = (m_options.m_element_count == 0) ? 1 : 0;
587*b9c1b51eSKate Stone   const bool does_consume_ptr_depth =
588*b9c1b51eSKate Stone       ((IsPtr() && m_options.m_element_count == 0) || IsRef());
589520a422bSEnrico Granata 
59026014690SGreg Clayton   DumpValueObjectOptions child_options(m_options);
591*b9c1b51eSKate Stone   child_options.SetFormat(m_options.m_format)
592*b9c1b51eSKate Stone       .SetSummary()
593*b9c1b51eSKate Stone       .SetRootValueObjectName();
594*b9c1b51eSKate Stone   child_options.SetScopeChecked(true)
595*b9c1b51eSKate Stone       .SetHideName(m_options.m_hide_name)
596*b9c1b51eSKate Stone       .SetHideValue(m_options.m_hide_value)
597*b9c1b51eSKate Stone       .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1
598*b9c1b51eSKate Stone                                ? child_options.m_omit_summary_depth -
599*b9c1b51eSKate Stone                                      consumed_depth
600*b9c1b51eSKate Stone                                : 0)
601520a422bSEnrico Granata       .SetElementCount(0);
6028cf44d96SEnrico Granata 
603*b9c1b51eSKate Stone   if (child_sp.get()) {
604*b9c1b51eSKate Stone     ValueObjectPrinter child_printer(
605*b9c1b51eSKate Stone         child_sp.get(), m_stream, child_options,
606520a422bSEnrico Granata         does_consume_ptr_depth ? --curr_ptr_depth : curr_ptr_depth,
607*b9c1b51eSKate Stone         m_curr_depth + consumed_depth, m_printed_instance_pointers);
6084d93b8cdSEnrico Granata     child_printer.PrintValueObject();
6094d93b8cdSEnrico Granata   }
6104d93b8cdSEnrico Granata }
6114d93b8cdSEnrico Granata 
612*b9c1b51eSKate Stone uint32_t ValueObjectPrinter::GetMaxNumChildrenToPrint(bool &print_dotdotdot) {
6134d93b8cdSEnrico Granata   ValueObject *synth_m_valobj = GetValueObjectForChildrenGeneration();
6144d93b8cdSEnrico Granata 
615520a422bSEnrico Granata   if (m_options.m_element_count > 0)
616520a422bSEnrico Granata     return m_options.m_element_count;
617520a422bSEnrico Granata 
6184d93b8cdSEnrico Granata   size_t num_children = synth_m_valobj->GetNumChildren();
6194d93b8cdSEnrico Granata   print_dotdotdot = false;
620*b9c1b51eSKate Stone   if (num_children) {
621*b9c1b51eSKate Stone     const size_t max_num_children =
622*b9c1b51eSKate Stone         m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
6234d93b8cdSEnrico Granata 
624*b9c1b51eSKate Stone     if (num_children > max_num_children && !m_options.m_ignore_cap) {
6254d93b8cdSEnrico Granata       print_dotdotdot = true;
6264d93b8cdSEnrico Granata       return max_num_children;
6274d93b8cdSEnrico Granata     }
6284d93b8cdSEnrico Granata   }
6294d93b8cdSEnrico Granata   return num_children;
6304d93b8cdSEnrico Granata }
6314d93b8cdSEnrico Granata 
632*b9c1b51eSKate Stone void ValueObjectPrinter::PrintChildrenPostamble(bool print_dotdotdot) {
633*b9c1b51eSKate Stone   if (!m_options.m_flat_output) {
634*b9c1b51eSKate Stone     if (print_dotdotdot) {
635*b9c1b51eSKate Stone       m_valobj->GetTargetSP()
636*b9c1b51eSKate Stone           ->GetDebugger()
637*b9c1b51eSKate Stone           .GetCommandInterpreter()
638*b9c1b51eSKate Stone           .ChildrenTruncated();
6394d93b8cdSEnrico Granata       m_stream->Indent("...\n");
6404d93b8cdSEnrico Granata     }
6414d93b8cdSEnrico Granata     m_stream->IndentLess();
6424d93b8cdSEnrico Granata     m_stream->Indent("}\n");
6434d93b8cdSEnrico Granata   }
6444d93b8cdSEnrico Granata }
6454d93b8cdSEnrico Granata 
646*b9c1b51eSKate Stone bool ValueObjectPrinter::ShouldPrintEmptyBrackets(bool value_printed,
647*b9c1b51eSKate Stone                                                   bool summary_printed) {
6488cf44d96SEnrico Granata   ValueObject *synth_m_valobj = GetValueObjectForChildrenGeneration();
6498cf44d96SEnrico Granata 
6508cf44d96SEnrico Granata   if (!IsAggregate())
6518cf44d96SEnrico Granata     return false;
6528cf44d96SEnrico Granata 
653*b9c1b51eSKate Stone   if (m_options.m_reveal_empty_aggregates == false) {
6548cf44d96SEnrico Granata     if (value_printed || summary_printed)
6558cf44d96SEnrico Granata       return false;
6568cf44d96SEnrico Granata   }
6578cf44d96SEnrico Granata 
6588cf44d96SEnrico Granata   if (synth_m_valobj->MightHaveChildren())
6598cf44d96SEnrico Granata     return true;
6608cf44d96SEnrico Granata 
6618cf44d96SEnrico Granata   if (m_val_summary_ok)
6628cf44d96SEnrico Granata     return false;
6638cf44d96SEnrico Granata 
6648cf44d96SEnrico Granata   return true;
6658cf44d96SEnrico Granata }
6668cf44d96SEnrico Granata 
667*b9c1b51eSKate Stone ValueObjectSP ValueObjectPrinter::GenerateChild(ValueObject *synth_valobj,
668*b9c1b51eSKate Stone                                                 size_t idx) {
669*b9c1b51eSKate Stone   if (m_options.m_element_count > 0) {
670520a422bSEnrico Granata     // if generating pointer-as-array children, use GetSyntheticArrayMember
671520a422bSEnrico Granata     return synth_valobj->GetSyntheticArrayMember(idx, true);
672*b9c1b51eSKate Stone   } else {
673520a422bSEnrico Granata     // otherwise, do the usual thing
674520a422bSEnrico Granata     return synth_valobj->GetChildAtIndex(idx, true);
675520a422bSEnrico Granata   }
676520a422bSEnrico Granata }
677520a422bSEnrico Granata 
678*b9c1b51eSKate Stone void ValueObjectPrinter::PrintChildren(
679*b9c1b51eSKate Stone     bool value_printed, bool summary_printed,
680*b9c1b51eSKate Stone     const DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {
6814d93b8cdSEnrico Granata   ValueObject *synth_m_valobj = GetValueObjectForChildrenGeneration();
6824d93b8cdSEnrico Granata 
6834d93b8cdSEnrico Granata   bool print_dotdotdot = false;
6844d93b8cdSEnrico Granata   size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
685*b9c1b51eSKate Stone   if (num_children) {
6868cf44d96SEnrico Granata     bool any_children_printed = false;
6874d93b8cdSEnrico Granata 
688*b9c1b51eSKate Stone     for (size_t idx = 0; idx < num_children; ++idx) {
689*b9c1b51eSKate Stone       if (ValueObjectSP child_sp = GenerateChild(synth_m_valobj, idx)) {
690*b9c1b51eSKate Stone         if (!any_children_printed) {
6918cf44d96SEnrico Granata           PrintChildrenPreamble();
6928cf44d96SEnrico Granata           any_children_printed = true;
6938cf44d96SEnrico Granata         }
6944d93b8cdSEnrico Granata         PrintChild(child_sp, curr_ptr_depth);
6954d93b8cdSEnrico Granata       }
6964d93b8cdSEnrico Granata     }
6978cf44d96SEnrico Granata 
6988cf44d96SEnrico Granata     if (any_children_printed)
6998cf44d96SEnrico Granata       PrintChildrenPostamble(print_dotdotdot);
700*b9c1b51eSKate Stone     else {
701*b9c1b51eSKate Stone       if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) {
7028cf44d96SEnrico Granata         if (ShouldPrintValueObject())
7038cf44d96SEnrico Granata           m_stream->PutCString(" {}\n");
7048cf44d96SEnrico Granata         else
7058cf44d96SEnrico Granata           m_stream->EOL();
706*b9c1b51eSKate Stone       } else
7078cf44d96SEnrico Granata         m_stream->EOL();
7088cf44d96SEnrico Granata     }
709*b9c1b51eSKate Stone   } else if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) {
7104d93b8cdSEnrico Granata     // Aggregate, no children...
711*b9c1b51eSKate Stone     if (ShouldPrintValueObject()) {
712*b9c1b51eSKate Stone       // if it has a synthetic value, then don't print {}, the synthetic
713*b9c1b51eSKate Stone       // children are probably only being used to vend a value
714*b9c1b51eSKate Stone       if (m_valobj->DoesProvideSyntheticValue() ||
715*b9c1b51eSKate Stone           !ShouldExpandEmptyAggregates())
716d07cfd3aSEnrico Granata         m_stream->PutCString("\n");
717d07cfd3aSEnrico Granata       else
7184d93b8cdSEnrico Granata         m_stream->PutCString(" {}\n");
7194d93b8cdSEnrico Granata     }
720*b9c1b51eSKate Stone   } else {
7214d93b8cdSEnrico Granata     if (ShouldPrintValueObject())
7224d93b8cdSEnrico Granata       m_stream->EOL();
7234d93b8cdSEnrico Granata   }
7244d93b8cdSEnrico Granata }
7254d93b8cdSEnrico Granata 
726*b9c1b51eSKate Stone bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) {
727d07cfd3aSEnrico Granata   if (!GetMostSpecializedValue() || m_valobj == nullptr)
728a29cb0baSEnrico Granata     return false;
729a29cb0baSEnrico Granata 
730a29cb0baSEnrico Granata   ValueObject *synth_m_valobj = GetValueObjectForChildrenGeneration();
731a29cb0baSEnrico Granata 
732a29cb0baSEnrico Granata   bool print_dotdotdot = false;
733a29cb0baSEnrico Granata   size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
734a29cb0baSEnrico Granata 
735*b9c1b51eSKate Stone   if (num_children) {
736a29cb0baSEnrico Granata     m_stream->PutChar('(');
737a29cb0baSEnrico Granata 
738*b9c1b51eSKate Stone     for (uint32_t idx = 0; idx < num_children; ++idx) {
739a29cb0baSEnrico Granata       lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
740ddac7611SEnrico Granata       if (child_sp)
741*b9c1b51eSKate Stone         child_sp = child_sp->GetQualifiedRepresentationIfAvailable(
742*b9c1b51eSKate Stone             m_options.m_use_dynamic, m_options.m_use_synthetic);
743*b9c1b51eSKate Stone       if (child_sp) {
744a29cb0baSEnrico Granata         if (idx)
745a29cb0baSEnrico Granata           m_stream->PutCString(", ");
746*b9c1b51eSKate Stone         if (!hide_names) {
747a29cb0baSEnrico Granata           const char *name = child_sp.get()->GetName().AsCString();
748*b9c1b51eSKate Stone           if (name && *name) {
749a29cb0baSEnrico Granata             m_stream->PutCString(name);
750a29cb0baSEnrico Granata             m_stream->PutCString(" = ");
751a29cb0baSEnrico Granata           }
752a29cb0baSEnrico Granata         }
753*b9c1b51eSKate Stone         child_sp->DumpPrintableRepresentation(
754*b9c1b51eSKate Stone             *m_stream, ValueObject::eValueObjectRepresentationStyleSummary,
7557aafb6a1SEnrico Granata             m_options.m_format,
756a29cb0baSEnrico Granata             ValueObject::ePrintableRepresentationSpecialCasesDisable);
757a29cb0baSEnrico Granata       }
758a29cb0baSEnrico Granata     }
759a29cb0baSEnrico Granata 
760a29cb0baSEnrico Granata     if (print_dotdotdot)
761a29cb0baSEnrico Granata       m_stream->PutCString(", ...)");
762a29cb0baSEnrico Granata     else
763a29cb0baSEnrico Granata       m_stream->PutChar(')');
764a29cb0baSEnrico Granata   }
765a29cb0baSEnrico Granata   return true;
766a29cb0baSEnrico Granata }
767a29cb0baSEnrico Granata 
768*b9c1b51eSKate Stone void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
769*b9c1b51eSKate Stone                                                bool summary_printed) {
770*b9c1b51eSKate Stone   // this flag controls whether we tried to display a description for this
771*b9c1b51eSKate Stone   // object and failed
7724d93b8cdSEnrico Granata   // if that happens, we want to display the children, if any
773*b9c1b51eSKate Stone   bool is_failed_description =
774*b9c1b51eSKate Stone       !PrintObjectDescriptionIfNeeded(value_printed, summary_printed);
7754d93b8cdSEnrico Granata 
776c1b7c09aSEnrico Granata   auto curr_ptr_depth = m_ptr_depth;
777*b9c1b51eSKate Stone   bool print_children =
778*b9c1b51eSKate Stone       ShouldPrintChildren(is_failed_description, curr_ptr_depth);
779*b9c1b51eSKate Stone   bool print_oneline =
780*b9c1b51eSKate Stone       (curr_ptr_depth.CanAllowExpansion() || m_options.m_show_types ||
781*b9c1b51eSKate Stone        !m_options.m_allow_oneliner_mode || m_options.m_flat_output ||
782*b9c1b51eSKate Stone        (m_options.m_element_count > 0) || m_options.m_show_location)
783*b9c1b51eSKate Stone           ? false
784*b9c1b51eSKate Stone           : DataVisualization::ShouldPrintAsOneLiner(*m_valobj);
7858cf44d96SEnrico Granata   bool is_instance_ptr = IsInstancePointer();
7868cf44d96SEnrico Granata   uint64_t instance_ptr_value = LLDB_INVALID_ADDRESS;
7878cf44d96SEnrico Granata 
788*b9c1b51eSKate Stone   if (print_children && is_instance_ptr) {
7898cf44d96SEnrico Granata     instance_ptr_value = m_valobj->GetValueAsUnsigned(0);
790*b9c1b51eSKate Stone     if (m_printed_instance_pointers->count(instance_ptr_value)) {
7918cf44d96SEnrico Granata       // we already printed this instance-is-pointer thing, so don't expand it
7928cf44d96SEnrico Granata       m_stream->PutCString(" {...}\n");
7938cf44d96SEnrico Granata 
7948cf44d96SEnrico Granata       // we're done here - get out fast
7958cf44d96SEnrico Granata       return;
796*b9c1b51eSKate Stone     } else
797*b9c1b51eSKate Stone       m_printed_instance_pointers->emplace(
798*b9c1b51eSKate Stone           instance_ptr_value); // remember this guy for future reference
7998cf44d96SEnrico Granata   }
8004d93b8cdSEnrico Granata 
801*b9c1b51eSKate Stone   if (print_children) {
802*b9c1b51eSKate Stone     if (print_oneline) {
803a29cb0baSEnrico Granata       m_stream->PutChar(' ');
804a29cb0baSEnrico Granata       PrintChildrenOneLiner(false);
805a29cb0baSEnrico Granata       m_stream->EOL();
806*b9c1b51eSKate Stone     } else
807c1b7c09aSEnrico Granata       PrintChildren(value_printed, summary_printed, curr_ptr_depth);
808*b9c1b51eSKate Stone   } else if (m_curr_depth >= m_options.m_max_depth && IsAggregate() &&
809*b9c1b51eSKate Stone              ShouldPrintValueObject()) {
8104d93b8cdSEnrico Granata     m_stream->PutCString("{...}\n");
811*b9c1b51eSKate Stone   } else
812245b3caaSEnrico Granata     m_stream->EOL();
8134d93b8cdSEnrico Granata }
8140f883ffbSEnrico Granata 
815*b9c1b51eSKate Stone bool ValueObjectPrinter::ShouldPrintValidation() {
81626014690SGreg Clayton   return m_options.m_run_validator;
8170f883ffbSEnrico Granata }
8180f883ffbSEnrico Granata 
819*b9c1b51eSKate Stone bool ValueObjectPrinter::PrintValidationMarkerIfNeeded() {
8200f883ffbSEnrico Granata   if (!ShouldPrintValidation())
8210f883ffbSEnrico Granata     return false;
8220f883ffbSEnrico Granata 
8230f883ffbSEnrico Granata   m_validation = m_valobj->GetValidationStatus();
8240f883ffbSEnrico Granata 
825*b9c1b51eSKate Stone   if (TypeValidatorResult::Failure == m_validation.first) {
8260f883ffbSEnrico Granata     m_stream->Printf("! ");
8270f883ffbSEnrico Granata     return true;
8280f883ffbSEnrico Granata   }
8290f883ffbSEnrico Granata 
8300f883ffbSEnrico Granata   return false;
8310f883ffbSEnrico Granata }
8320f883ffbSEnrico Granata 
833*b9c1b51eSKate Stone bool ValueObjectPrinter::PrintValidationErrorIfNeeded() {
8340f883ffbSEnrico Granata   if (!ShouldPrintValidation())
8350f883ffbSEnrico Granata     return false;
8360f883ffbSEnrico Granata 
8370f883ffbSEnrico Granata   if (TypeValidatorResult::Success == m_validation.first)
8380f883ffbSEnrico Granata     return false;
8390f883ffbSEnrico Granata 
8400f883ffbSEnrico Granata   if (m_validation.second.empty())
8410f883ffbSEnrico Granata     m_validation.second.assign("unknown error");
8420f883ffbSEnrico Granata 
8430f883ffbSEnrico Granata   m_stream->Printf(" ! validation error: %s", m_validation.second.c_str());
8440f883ffbSEnrico Granata   m_stream->EOL();
8450f883ffbSEnrico Granata 
8460f883ffbSEnrico Granata   return true;
8470f883ffbSEnrico Granata }
848