1*80814287SRaphael Isemann //===-- ValueObjectPrinter.cpp --------------------------------------------===//
24d93b8cdSEnrico Granata //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64d93b8cdSEnrico Granata //
74d93b8cdSEnrico Granata //===----------------------------------------------------------------------===//
84d93b8cdSEnrico Granata 
94d93b8cdSEnrico Granata #include "lldb/DataFormatters/ValueObjectPrinter.h"
104d93b8cdSEnrico Granata 
11c8e7649aSEnrico Granata #include "lldb/Core/ValueObject.h"
12a29cb0baSEnrico Granata #include "lldb/DataFormatters/DataVisualization.h"
134d93b8cdSEnrico Granata #include "lldb/Interpreter/CommandInterpreter.h"
14c8e7649aSEnrico Granata #include "lldb/Target/Language.h"
154d93b8cdSEnrico Granata #include "lldb/Target/Target.h"
16bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
174d93b8cdSEnrico Granata 
184d93b8cdSEnrico Granata using namespace lldb;
194d93b8cdSEnrico Granata using namespace lldb_private;
204d93b8cdSEnrico Granata 
21b9c1b51eSKate Stone ValueObjectPrinter::ValueObjectPrinter(ValueObject *valobj, Stream *s) {
22b9c1b51eSKate Stone   if (valobj) {
23d5957336SEnrico Granata     DumpValueObjectOptions options(*valobj);
248cf44d96SEnrico Granata     Init(valobj, s, options, m_options.m_max_ptr_depth, 0, nullptr);
25b9c1b51eSKate Stone   } else {
26d5957336SEnrico Granata     DumpValueObjectOptions options;
278cf44d96SEnrico Granata     Init(valobj, s, options, m_options.m_max_ptr_depth, 0, nullptr);
28d5957336SEnrico Granata   }
29d5957336SEnrico Granata }
30d5957336SEnrico Granata 
31b9c1b51eSKate Stone ValueObjectPrinter::ValueObjectPrinter(ValueObject *valobj, Stream *s,
32b9c1b51eSKate Stone                                        const DumpValueObjectOptions &options) {
338cf44d96SEnrico Granata   Init(valobj, s, options, m_options.m_max_ptr_depth, 0, nullptr);
344d93b8cdSEnrico Granata }
354d93b8cdSEnrico Granata 
36b9c1b51eSKate Stone ValueObjectPrinter::ValueObjectPrinter(
37b9c1b51eSKate Stone     ValueObject *valobj, Stream *s, const DumpValueObjectOptions &options,
38b9c1b51eSKate Stone     const DumpValueObjectOptions::PointerDepth &ptr_depth, uint32_t curr_depth,
39b9c1b51eSKate Stone     InstancePointersSetSP printed_instance_pointers) {
408cf44d96SEnrico Granata   Init(valobj, s, options, ptr_depth, curr_depth, printed_instance_pointers);
41938d1d67SEnrico Granata }
42938d1d67SEnrico Granata 
43b9c1b51eSKate Stone void ValueObjectPrinter::Init(
44b9c1b51eSKate Stone     ValueObject *valobj, Stream *s, const DumpValueObjectOptions &options,
45b9c1b51eSKate Stone     const DumpValueObjectOptions::PointerDepth &ptr_depth, uint32_t curr_depth,
46b9c1b51eSKate Stone     InstancePointersSetSP printed_instance_pointers) {
47938d1d67SEnrico Granata   m_orig_valobj = valobj;
48938d1d67SEnrico Granata   m_valobj = nullptr;
49938d1d67SEnrico Granata   m_stream = s;
5026014690SGreg Clayton   m_options = options;
51938d1d67SEnrico Granata   m_ptr_depth = ptr_depth;
52938d1d67SEnrico Granata   m_curr_depth = curr_depth;
53938d1d67SEnrico Granata   assert(m_orig_valobj && "cannot print a NULL ValueObject");
54938d1d67SEnrico Granata   assert(m_stream && "cannot print to a NULL Stream");
55938d1d67SEnrico Granata   m_should_print = eLazyBoolCalculate;
56938d1d67SEnrico Granata   m_is_nil = eLazyBoolCalculate;
57608d67c1SEnrico Granata   m_is_uninit = eLazyBoolCalculate;
58938d1d67SEnrico Granata   m_is_ptr = eLazyBoolCalculate;
59938d1d67SEnrico Granata   m_is_ref = eLazyBoolCalculate;
60938d1d67SEnrico Granata   m_is_aggregate = eLazyBoolCalculate;
618cf44d96SEnrico Granata   m_is_instance_ptr = eLazyBoolCalculate;
62938d1d67SEnrico Granata   m_summary_formatter = {nullptr, false};
63938d1d67SEnrico Granata   m_value.assign("");
64938d1d67SEnrico Granata   m_summary.assign("");
65938d1d67SEnrico Granata   m_error.assign("");
668cf44d96SEnrico Granata   m_val_summary_ok = false;
67b9c1b51eSKate Stone   m_printed_instance_pointers =
68b9c1b51eSKate Stone       printed_instance_pointers
69b9c1b51eSKate Stone           ? printed_instance_pointers
70b9c1b51eSKate Stone           : InstancePointersSetSP(new InstancePointersSet());
71938d1d67SEnrico Granata }
724d93b8cdSEnrico Granata 
73b9c1b51eSKate Stone bool ValueObjectPrinter::PrintValueObject() {
74d07cfd3aSEnrico Granata   if (!GetMostSpecializedValue() || m_valobj == nullptr)
754d93b8cdSEnrico Granata     return false;
764d93b8cdSEnrico Granata 
77b9c1b51eSKate Stone   if (ShouldPrintValueObject()) {
784d93b8cdSEnrico Granata     PrintLocationIfNeeded();
794d93b8cdSEnrico Granata     m_stream->Indent();
804d93b8cdSEnrico Granata 
81e0ee1e1cSEnrico Granata     PrintDecl();
824d93b8cdSEnrico Granata   }
834d93b8cdSEnrico Granata 
844d93b8cdSEnrico Granata   bool value_printed = false;
854d93b8cdSEnrico Granata   bool summary_printed = false;
864d93b8cdSEnrico Granata 
87b9c1b51eSKate Stone   m_val_summary_ok =
88b9c1b51eSKate Stone       PrintValueAndSummaryIfNeeded(value_printed, summary_printed);
894d93b8cdSEnrico Granata 
908cf44d96SEnrico Granata   if (m_val_summary_ok)
914d93b8cdSEnrico Granata     PrintChildrenIfNeeded(value_printed, summary_printed);
9239938938SEnrico Granata   else
934d93b8cdSEnrico Granata     m_stream->EOL();
944d93b8cdSEnrico Granata 
954d93b8cdSEnrico Granata   return true;
964d93b8cdSEnrico Granata }
974d93b8cdSEnrico Granata 
98b9c1b51eSKate Stone bool ValueObjectPrinter::GetMostSpecializedValue() {
99a29cb0baSEnrico Granata   if (m_valobj)
100a29cb0baSEnrico Granata     return true;
1014d93b8cdSEnrico Granata   bool update_success = m_orig_valobj->UpdateValueIfNeeded(true);
102b9c1b51eSKate Stone   if (!update_success) {
103106260c5SEnrico Granata     m_valobj = m_orig_valobj;
104b9c1b51eSKate Stone   } else {
105b9c1b51eSKate Stone     if (m_orig_valobj->IsDynamic()) {
106b9c1b51eSKate Stone       if (m_options.m_use_dynamic == eNoDynamicValues) {
107106260c5SEnrico Granata         ValueObject *static_value = m_orig_valobj->GetStaticValue().get();
108106260c5SEnrico Granata         if (static_value)
109106260c5SEnrico Granata           m_valobj = static_value;
110106260c5SEnrico Granata         else
111106260c5SEnrico Granata           m_valobj = m_orig_valobj;
112b9c1b51eSKate Stone       } else
113106260c5SEnrico Granata         m_valobj = m_orig_valobj;
114b9c1b51eSKate Stone     } else {
115b9c1b51eSKate Stone       if (m_options.m_use_dynamic != eNoDynamicValues) {
116b9c1b51eSKate Stone         ValueObject *dynamic_value =
117b9c1b51eSKate Stone             m_orig_valobj->GetDynamicValue(m_options.m_use_dynamic).get();
1184d93b8cdSEnrico Granata         if (dynamic_value)
1194d93b8cdSEnrico Granata           m_valobj = dynamic_value;
1204d93b8cdSEnrico Granata         else
1214d93b8cdSEnrico Granata           m_valobj = m_orig_valobj;
122b9c1b51eSKate Stone       } else
1234d93b8cdSEnrico Granata         m_valobj = m_orig_valobj;
124106260c5SEnrico Granata     }
125d07cfd3aSEnrico Granata 
126b9c1b51eSKate Stone     if (m_valobj->IsSynthetic()) {
127a6682a41SJonas Devlieghere       if (!m_options.m_use_synthetic) {
128d07cfd3aSEnrico Granata         ValueObject *non_synthetic = m_valobj->GetNonSyntheticValue().get();
129d07cfd3aSEnrico Granata         if (non_synthetic)
130d07cfd3aSEnrico Granata           m_valobj = non_synthetic;
131d07cfd3aSEnrico Granata       }
132b9c1b51eSKate Stone     } else {
133a6682a41SJonas Devlieghere       if (m_options.m_use_synthetic) {
134d07cfd3aSEnrico Granata         ValueObject *synthetic = m_valobj->GetSyntheticValue().get();
135d07cfd3aSEnrico Granata         if (synthetic)
136d07cfd3aSEnrico Granata           m_valobj = synthetic;
137d07cfd3aSEnrico Granata       }
138d07cfd3aSEnrico Granata     }
139106260c5SEnrico Granata   }
14059b5a37dSBruce Mitchener   m_compiler_type = m_valobj->GetCompilerType();
14159b5a37dSBruce Mitchener   m_type_flags = m_compiler_type.GetTypeInfo();
1424d93b8cdSEnrico Granata   return true;
1434d93b8cdSEnrico Granata }
1444d93b8cdSEnrico Granata 
145b9c1b51eSKate Stone const char *ValueObjectPrinter::GetDescriptionForDisplay() {
1464d93b8cdSEnrico Granata   const char *str = m_valobj->GetObjectDescription();
1474d93b8cdSEnrico Granata   if (!str)
1484d93b8cdSEnrico Granata     str = m_valobj->GetSummaryAsCString();
1494d93b8cdSEnrico Granata   if (!str)
1504d93b8cdSEnrico Granata     str = m_valobj->GetValueAsCString();
1514d93b8cdSEnrico Granata   return str;
1524d93b8cdSEnrico Granata }
1534d93b8cdSEnrico Granata 
154b9c1b51eSKate Stone const char *ValueObjectPrinter::GetRootNameForDisplay(const char *if_fail) {
155b9c1b51eSKate Stone   const char *root_valobj_name = m_options.m_root_valobj_name.empty()
156b9c1b51eSKate Stone                                      ? m_valobj->GetName().AsCString()
157b9c1b51eSKate Stone                                      : m_options.m_root_valobj_name.c_str();
1584d93b8cdSEnrico Granata   return root_valobj_name ? root_valobj_name : if_fail;
1594d93b8cdSEnrico Granata }
1604d93b8cdSEnrico Granata 
161b9c1b51eSKate Stone bool ValueObjectPrinter::ShouldPrintValueObject() {
1624d93b8cdSEnrico Granata   if (m_should_print == eLazyBoolCalculate)
163b9c1b51eSKate Stone     m_should_print =
164a6682a41SJonas Devlieghere         (!m_options.m_flat_output || m_type_flags.Test(eTypeHasValue))
165b9c1b51eSKate Stone             ? eLazyBoolYes
166b9c1b51eSKate Stone             : eLazyBoolNo;
1674d93b8cdSEnrico Granata   return m_should_print == eLazyBoolYes;
1684d93b8cdSEnrico Granata }
1694d93b8cdSEnrico Granata 
170b9c1b51eSKate Stone bool ValueObjectPrinter::IsNil() {
1714d93b8cdSEnrico Granata   if (m_is_nil == eLazyBoolCalculate)
172608d67c1SEnrico Granata     m_is_nil = m_valobj->IsNilReference() ? eLazyBoolYes : eLazyBoolNo;
1734d93b8cdSEnrico Granata   return m_is_nil == eLazyBoolYes;
1744d93b8cdSEnrico Granata }
1754d93b8cdSEnrico Granata 
176b9c1b51eSKate Stone bool ValueObjectPrinter::IsUninitialized() {
177608d67c1SEnrico Granata   if (m_is_uninit == eLazyBoolCalculate)
178b9c1b51eSKate Stone     m_is_uninit =
179b9c1b51eSKate Stone         m_valobj->IsUninitializedReference() ? eLazyBoolYes : eLazyBoolNo;
180608d67c1SEnrico Granata   return m_is_uninit == eLazyBoolYes;
181608d67c1SEnrico Granata }
182608d67c1SEnrico Granata 
183b9c1b51eSKate Stone bool ValueObjectPrinter::IsPtr() {
1844d93b8cdSEnrico Granata   if (m_is_ptr == eLazyBoolCalculate)
185622be238SEnrico Granata     m_is_ptr = m_type_flags.Test(eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo;
1864d93b8cdSEnrico Granata   return m_is_ptr == eLazyBoolYes;
1874d93b8cdSEnrico Granata }
1884d93b8cdSEnrico Granata 
189b9c1b51eSKate Stone bool ValueObjectPrinter::IsRef() {
1904d93b8cdSEnrico Granata   if (m_is_ref == eLazyBoolCalculate)
191622be238SEnrico Granata     m_is_ref = m_type_flags.Test(eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo;
1924d93b8cdSEnrico Granata   return m_is_ref == eLazyBoolYes;
1934d93b8cdSEnrico Granata }
1944d93b8cdSEnrico Granata 
195b9c1b51eSKate Stone bool ValueObjectPrinter::IsAggregate() {
1964d93b8cdSEnrico Granata   if (m_is_aggregate == eLazyBoolCalculate)
197b9c1b51eSKate Stone     m_is_aggregate =
198b9c1b51eSKate Stone         m_type_flags.Test(eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo;
1994d93b8cdSEnrico Granata   return m_is_aggregate == eLazyBoolYes;
2004d93b8cdSEnrico Granata }
2014d93b8cdSEnrico Granata 
202b9c1b51eSKate Stone bool ValueObjectPrinter::IsInstancePointer() {
2038cf44d96SEnrico Granata   // you need to do this check on the value's clang type
2048cf44d96SEnrico Granata   if (m_is_instance_ptr == eLazyBoolCalculate)
205b9c1b51eSKate Stone     m_is_instance_ptr = (m_valobj->GetValue().GetCompilerType().GetTypeInfo() &
206b9c1b51eSKate Stone                          eTypeInstanceIsPointer) != 0
207b9c1b51eSKate Stone                             ? eLazyBoolYes
208b9c1b51eSKate Stone                             : eLazyBoolNo;
2098cf44d96SEnrico Granata   if ((eLazyBoolYes == m_is_instance_ptr) && m_valobj->IsBaseClass())
2108cf44d96SEnrico Granata     m_is_instance_ptr = eLazyBoolNo;
2118cf44d96SEnrico Granata   return m_is_instance_ptr == eLazyBoolYes;
2128cf44d96SEnrico Granata }
2138cf44d96SEnrico Granata 
214b9c1b51eSKate Stone bool ValueObjectPrinter::PrintLocationIfNeeded() {
215b9c1b51eSKate Stone   if (m_options.m_show_location) {
2164d93b8cdSEnrico Granata     m_stream->Printf("%s: ", m_valobj->GetLocationAsCString());
2174d93b8cdSEnrico Granata     return true;
2184d93b8cdSEnrico Granata   }
2194d93b8cdSEnrico Granata   return false;
2204d93b8cdSEnrico Granata }
2214d93b8cdSEnrico Granata 
222b9c1b51eSKate Stone void ValueObjectPrinter::PrintDecl() {
2234d93b8cdSEnrico Granata   bool show_type = true;
224b9c1b51eSKate Stone   // if we are at the root-level and been asked to hide the root's type, then
225b9c1b51eSKate Stone   // hide it
22626014690SGreg Clayton   if (m_curr_depth == 0 && m_options.m_hide_root_type)
2274d93b8cdSEnrico Granata     show_type = false;
2284d93b8cdSEnrico Granata   else
229b9c1b51eSKate Stone     // otherwise decide according to the usual rules (asked to show types -
230b9c1b51eSKate Stone     // always at the root level)
231b9c1b51eSKate Stone     show_type = m_options.m_show_types ||
232b9c1b51eSKate Stone                 (m_curr_depth == 0 && !m_options.m_flat_output);
2334d93b8cdSEnrico Granata 
234e0ee1e1cSEnrico Granata   StreamString typeName;
235e0ee1e1cSEnrico Granata 
236e0ee1e1cSEnrico Granata   // always show the type at the root level if it is invalid
237b9c1b51eSKate Stone   if (show_type) {
23805097246SAdrian Prantl     // Some ValueObjects don't have types (like registers sets). Only print the
23905097246SAdrian Prantl     // type if there is one to print
240a126e462SEnrico Granata     ConstString type_name;
241b9c1b51eSKate Stone     if (m_compiler_type.IsValid()) {
24226014690SGreg Clayton       if (m_options.m_use_type_display_name)
243a126e462SEnrico Granata         type_name = m_valobj->GetDisplayTypeName();
244e8daa2f8SEnrico Granata       else
245a126e462SEnrico Granata         type_name = m_valobj->GetQualifiedTypeName();
246b9c1b51eSKate Stone     } else {
247b9c1b51eSKate Stone       // only show an invalid type name if the user explicitly triggered
248b9c1b51eSKate Stone       // show_type
24926014690SGreg Clayton       if (m_options.m_show_types)
250e0ee1e1cSEnrico Granata         type_name = ConstString("<invalid type>");
251e0ee1e1cSEnrico Granata       else
252e0ee1e1cSEnrico Granata         type_name.Clear();
2534d93b8cdSEnrico Granata     }
2544d93b8cdSEnrico Granata 
255b9c1b51eSKate Stone     if (type_name) {
256e0ee1e1cSEnrico Granata       std::string type_name_str(type_name.GetCString());
257b9c1b51eSKate Stone       if (m_options.m_hide_pointer_value) {
258b9c1b51eSKate Stone         for (auto iter = type_name_str.find(" *"); iter != std::string::npos;
259b9c1b51eSKate Stone              iter = type_name_str.find(" *")) {
260e0ee1e1cSEnrico Granata           type_name_str.erase(iter, 2);
261e0ee1e1cSEnrico Granata         }
262e0ee1e1cSEnrico Granata       }
263c8e7649aSEnrico Granata       typeName.Printf("%s", type_name_str.c_str());
264e0ee1e1cSEnrico Granata     }
265e0ee1e1cSEnrico Granata   }
266e0ee1e1cSEnrico Granata 
267e0ee1e1cSEnrico Granata   StreamString varName;
268e0ee1e1cSEnrico Granata 
269b9c1b51eSKate Stone   if (m_options.m_flat_output) {
2704d93b8cdSEnrico Granata     // If we are showing types, also qualify the C++ base classes
2714d93b8cdSEnrico Granata     const bool qualify_cxx_base_classes = show_type;
272b9c1b51eSKate Stone     if (!m_options.m_hide_name) {
273e0ee1e1cSEnrico Granata       m_valobj->GetExpressionPath(varName, qualify_cxx_base_classes);
2744d93b8cdSEnrico Granata     }
275b9c1b51eSKate Stone   } else if (!m_options.m_hide_name) {
2764d93b8cdSEnrico Granata     const char *name_cstr = GetRootNameForDisplay("");
277e0ee1e1cSEnrico Granata     varName.Printf("%s", name_cstr);
2784d93b8cdSEnrico Granata   }
279e0ee1e1cSEnrico Granata 
280e0ee1e1cSEnrico Granata   bool decl_printed = false;
281b9c1b51eSKate Stone   if (!m_options.m_decl_printing_helper) {
282b9c1b51eSKate Stone     // if the user didn't give us a custom helper, pick one based upon the
283b9c1b51eSKate Stone     // language, either the one that this printer is bound to, or the preferred
284b9c1b51eSKate Stone     // one for the ValueObject
285b9c1b51eSKate Stone     lldb::LanguageType lang_type =
286b9c1b51eSKate Stone         (m_options.m_varformat_language == lldb::eLanguageTypeUnknown)
287b9c1b51eSKate Stone             ? m_valobj->GetPreferredDisplayLanguage()
288b9c1b51eSKate Stone             : m_options.m_varformat_language;
289b9c1b51eSKate Stone     if (Language *lang_plugin = Language::FindPlugin(lang_type)) {
29026014690SGreg Clayton       m_options.m_decl_printing_helper = lang_plugin->GetDeclPrintingHelper();
291c8e7649aSEnrico Granata     }
292c8e7649aSEnrico Granata   }
293c8e7649aSEnrico Granata 
294b9c1b51eSKate Stone   if (m_options.m_decl_printing_helper) {
295c156427dSZachary Turner     ConstString type_name_cstr(typeName.GetString());
296c156427dSZachary Turner     ConstString var_name_cstr(varName.GetString());
297e0ee1e1cSEnrico Granata 
298e0ee1e1cSEnrico Granata     StreamString dest_stream;
299b9c1b51eSKate Stone     if (m_options.m_decl_printing_helper(type_name_cstr, var_name_cstr,
300b9c1b51eSKate Stone                                          m_options, dest_stream)) {
301e0ee1e1cSEnrico Granata       decl_printed = true;
302c156427dSZachary Turner       m_stream->PutCString(dest_stream.GetString());
303e0ee1e1cSEnrico Granata     }
304e0ee1e1cSEnrico Granata   }
305e0ee1e1cSEnrico Granata 
306c8e7649aSEnrico Granata   // if the helper failed, or there is none, do a default thing
307b9c1b51eSKate Stone   if (!decl_printed) {
308c156427dSZachary Turner     if (!typeName.Empty())
309c8e7649aSEnrico Granata       m_stream->Printf("(%s) ", typeName.GetData());
310c156427dSZachary Turner     if (!varName.Empty())
311e0ee1e1cSEnrico Granata       m_stream->Printf("%s =", varName.GetData());
31226014690SGreg Clayton     else if (!m_options.m_hide_name)
313e0ee1e1cSEnrico Granata       m_stream->Printf(" =");
314e0ee1e1cSEnrico Granata   }
3154d93b8cdSEnrico Granata }
3164d93b8cdSEnrico Granata 
317b9c1b51eSKate Stone bool ValueObjectPrinter::CheckScopeIfNeeded() {
31826014690SGreg Clayton   if (m_options.m_scope_already_checked)
3194d93b8cdSEnrico Granata     return true;
3204d93b8cdSEnrico Granata   return m_valobj->IsInScope();
3214d93b8cdSEnrico Granata }
3224d93b8cdSEnrico Granata 
323b9c1b51eSKate Stone TypeSummaryImpl *ValueObjectPrinter::GetSummaryFormatter(bool null_if_omitted) {
324a6682a41SJonas Devlieghere   if (!m_summary_formatter.second) {
325b9c1b51eSKate Stone     TypeSummaryImpl *entry = m_options.m_summary_sp
326b9c1b51eSKate Stone                                  ? m_options.m_summary_sp.get()
327b9c1b51eSKate Stone                                  : m_valobj->GetSummaryFormat().get();
3284d93b8cdSEnrico Granata 
32926014690SGreg Clayton     if (m_options.m_omit_summary_depth > 0)
330248a1305SKonrad Kleine       entry = nullptr;
3314d93b8cdSEnrico Granata     m_summary_formatter.first = entry;
3324d93b8cdSEnrico Granata     m_summary_formatter.second = true;
3334d93b8cdSEnrico Granata   }
3348cf44d96SEnrico Granata   if (m_options.m_omit_summary_depth > 0 && null_if_omitted)
3358cf44d96SEnrico Granata     return nullptr;
3364d93b8cdSEnrico Granata   return m_summary_formatter.first;
3374d93b8cdSEnrico Granata }
3384d93b8cdSEnrico Granata 
339b9c1b51eSKate Stone static bool IsPointerValue(const CompilerType &type) {
340e0ee1e1cSEnrico Granata   Flags type_flags(type.GetTypeInfo());
3418cf44d96SEnrico Granata   if (type_flags.AnySet(eTypeInstanceIsPointer | eTypeIsPointer))
342e0ee1e1cSEnrico Granata     return type_flags.AllClear(eTypeIsBuiltIn);
343e0ee1e1cSEnrico Granata   return false;
344e0ee1e1cSEnrico Granata }
345e0ee1e1cSEnrico Granata 
346b9c1b51eSKate Stone void ValueObjectPrinter::GetValueSummaryError(std::string &value,
3474d93b8cdSEnrico Granata                                               std::string &summary,
348b9c1b51eSKate Stone                                               std::string &error) {
349520a422bSEnrico Granata   lldb::Format format = m_options.m_format;
350b9c1b51eSKate Stone   // if I am printing synthetized elements, apply the format to those elements
351b9c1b51eSKate Stone   // only
3529ac0dac1SEnrico Granata   if (m_options.m_pointer_as_array)
353520a422bSEnrico Granata     m_valobj->GetValueAsCString(lldb::eFormatDefault, value);
354520a422bSEnrico Granata   else if (format != eFormatDefault && format != m_valobj->GetFormat())
355520a422bSEnrico Granata     m_valobj->GetValueAsCString(format, value);
356b9c1b51eSKate Stone   else {
3574d93b8cdSEnrico Granata     const char *val_cstr = m_valobj->GetValueAsCString();
358465f4bc2SEnrico Granata     if (val_cstr)
359465f4bc2SEnrico Granata       value.assign(val_cstr);
360465f4bc2SEnrico Granata   }
3614d93b8cdSEnrico Granata   const char *err_cstr = m_valobj->GetError().AsCString();
3624d93b8cdSEnrico Granata   if (err_cstr)
3634d93b8cdSEnrico Granata     error.assign(err_cstr);
3644d93b8cdSEnrico Granata 
365b9c1b51eSKate Stone   if (ShouldPrintValueObject()) {
3664d93b8cdSEnrico Granata     if (IsNil())
3674d93b8cdSEnrico Granata       summary.assign("nil");
368608d67c1SEnrico Granata     else if (IsUninitialized())
369608d67c1SEnrico Granata       summary.assign("<uninitialized>");
370b9c1b51eSKate Stone     else if (m_options.m_omit_summary_depth == 0) {
3714d93b8cdSEnrico Granata       TypeSummaryImpl *entry = GetSummaryFormatter();
3724d93b8cdSEnrico Granata       if (entry)
373b9c1b51eSKate Stone         m_valobj->GetSummaryAsCString(entry, summary,
374b9c1b51eSKate Stone                                       m_options.m_varformat_language);
375b9c1b51eSKate Stone       else {
376b9c1b51eSKate Stone         const char *sum_cstr =
377b9c1b51eSKate Stone             m_valobj->GetSummaryAsCString(m_options.m_varformat_language);
3784d93b8cdSEnrico Granata         if (sum_cstr)
3794d93b8cdSEnrico Granata           summary.assign(sum_cstr);
3804d93b8cdSEnrico Granata       }
3814d93b8cdSEnrico Granata     }
3824d93b8cdSEnrico Granata   }
3834d93b8cdSEnrico Granata }
3844d93b8cdSEnrico Granata 
385b9c1b51eSKate Stone bool ValueObjectPrinter::PrintValueAndSummaryIfNeeded(bool &value_printed,
386b9c1b51eSKate Stone                                                       bool &summary_printed) {
3874d93b8cdSEnrico Granata   bool error_printed = false;
388b9c1b51eSKate Stone   if (ShouldPrintValueObject()) {
3894d93b8cdSEnrico Granata     if (!CheckScopeIfNeeded())
3904d93b8cdSEnrico Granata       m_error.assign("out of scope");
391b9c1b51eSKate Stone     if (m_error.empty()) {
3924d93b8cdSEnrico Granata       GetValueSummaryError(m_value, m_summary, m_error);
3934d93b8cdSEnrico Granata     }
394b9c1b51eSKate Stone     if (m_error.size()) {
395b9c1b51eSKate Stone       // we need to support scenarios in which it is actually fine for a value
39605097246SAdrian Prantl       // to have no type but - on the other hand - if we get an error *AND*
39705097246SAdrian Prantl       // have no type, we try to get out gracefully, since most often that
39805097246SAdrian Prantl       // combination means "could not resolve a type" and the default failure
39905097246SAdrian Prantl       // mode is quite ugly
400b9c1b51eSKate Stone       if (!m_compiler_type.IsValid()) {
4018cf44d96SEnrico Granata         m_stream->Printf(" <could not resolve type>");
4028cf44d96SEnrico Granata         return false;
4038cf44d96SEnrico Granata       }
4048cf44d96SEnrico Granata 
4054d93b8cdSEnrico Granata       error_printed = true;
4064d93b8cdSEnrico Granata       m_stream->Printf(" <%s>\n", m_error.c_str());
407b9c1b51eSKate Stone     } else {
40805097246SAdrian Prantl       // Make sure we have a value and make sure the summary didn't specify
40905097246SAdrian Prantl       // that the value should not be printed - and do not print the value if
41005097246SAdrian Prantl       // this thing is nil (but show the value if the user passes a format
41105097246SAdrian Prantl       // explicitly)
4124d93b8cdSEnrico Granata       TypeSummaryImpl *entry = GetSummaryFormatter();
413b9c1b51eSKate Stone       if (!IsNil() && !IsUninitialized() && !m_value.empty() &&
414248a1305SKonrad Kleine           (entry == nullptr ||
415248a1305SKonrad Kleine            (entry->DoesPrintValue(m_valobj) ||
416b9c1b51eSKate Stone             m_options.m_format != eFormatDefault) ||
417b9c1b51eSKate Stone            m_summary.empty()) &&
418b9c1b51eSKate Stone           !m_options.m_hide_value) {
419b9c1b51eSKate Stone         if (m_options.m_hide_pointer_value &&
420b9c1b51eSKate Stone             IsPointerValue(m_valobj->GetCompilerType())) {
421b9c1b51eSKate Stone         } else {
4224d93b8cdSEnrico Granata           m_stream->Printf(" %s", m_value.c_str());
4234d93b8cdSEnrico Granata           value_printed = true;
4244d93b8cdSEnrico Granata         }
425e0ee1e1cSEnrico Granata       }
4264d93b8cdSEnrico Granata 
427b9c1b51eSKate Stone       if (m_summary.size()) {
4284d93b8cdSEnrico Granata         m_stream->Printf(" %s", m_summary.c_str());
4294d93b8cdSEnrico Granata         summary_printed = true;
4304d93b8cdSEnrico Granata       }
4314d93b8cdSEnrico Granata     }
4324d93b8cdSEnrico Granata   }
4334d93b8cdSEnrico Granata   return !error_printed;
4344d93b8cdSEnrico Granata }
4354d93b8cdSEnrico Granata 
436b9c1b51eSKate Stone bool ValueObjectPrinter::PrintObjectDescriptionIfNeeded(bool value_printed,
437b9c1b51eSKate Stone                                                         bool summary_printed) {
438b9c1b51eSKate Stone   if (ShouldPrintValueObject()) {
4394d93b8cdSEnrico Granata     // let's avoid the overly verbose no description error for a nil thing
440b9c1b51eSKate Stone     if (m_options.m_use_objc && !IsNil() && !IsUninitialized() &&
4419ac0dac1SEnrico Granata         (!m_options.m_pointer_as_array)) {
44226014690SGreg Clayton       if (!m_options.m_hide_value || !m_options.m_hide_name)
4434d93b8cdSEnrico Granata         m_stream->Printf(" ");
4444d93b8cdSEnrico Granata       const char *object_desc = nullptr;
4454d93b8cdSEnrico Granata       if (value_printed || summary_printed)
4464d93b8cdSEnrico Granata         object_desc = m_valobj->GetObjectDescription();
4474d93b8cdSEnrico Granata       else
4484d93b8cdSEnrico Granata         object_desc = GetDescriptionForDisplay();
449b9c1b51eSKate Stone       if (object_desc && *object_desc) {
450b9923589SJim Ingham         // If the description already ends with a \n don't add another one.
451b9923589SJim Ingham         size_t object_end = strlen(object_desc) - 1;
452b9923589SJim Ingham         if (object_desc[object_end] == '\n')
453b9923589SJim Ingham             m_stream->Printf("%s", object_desc);
454b9923589SJim Ingham         else
4554d93b8cdSEnrico Granata             m_stream->Printf("%s\n", object_desc);
4564d93b8cdSEnrico Granata         return true;
457a6682a41SJonas Devlieghere       } else if (!value_printed && !summary_printed)
4584d93b8cdSEnrico Granata         return true;
4594d93b8cdSEnrico Granata       else
4604d93b8cdSEnrico Granata         return false;
4614d93b8cdSEnrico Granata     }
4624d93b8cdSEnrico Granata   }
4634d93b8cdSEnrico Granata   return true;
4644d93b8cdSEnrico Granata }
4654d93b8cdSEnrico Granata 
466b9c1b51eSKate Stone bool DumpValueObjectOptions::PointerDepth::CanAllowExpansion() const {
467b9c1b51eSKate Stone   switch (m_mode) {
468c1b7c09aSEnrico Granata   case Mode::Always:
469c1b7c09aSEnrico Granata   case Mode::Default:
470e4e17b8cSTamas Berghammer     return m_count > 0;
471c1b7c09aSEnrico Granata   case Mode::Never:
472c1b7c09aSEnrico Granata     return false;
473c1b7c09aSEnrico Granata   }
47484f5b0dfSZachary Turner   return false;
475c1b7c09aSEnrico Granata }
476c1b7c09aSEnrico Granata 
477b9c1b51eSKate Stone bool ValueObjectPrinter::ShouldPrintChildren(
478b9c1b51eSKate Stone     bool is_failed_description,
479b9c1b51eSKate Stone     DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {
4804d93b8cdSEnrico Granata   const bool is_ref = IsRef();
4814d93b8cdSEnrico Granata   const bool is_ptr = IsPtr();
482608d67c1SEnrico Granata   const bool is_uninit = IsUninitialized();
483608d67c1SEnrico Granata 
484608d67c1SEnrico Granata   if (is_uninit)
485608d67c1SEnrico Granata     return false;
4864d93b8cdSEnrico Granata 
48705097246SAdrian Prantl   // if the user has specified an element count, always print children as it is
48805097246SAdrian Prantl   // explicit user demand being honored
4899ac0dac1SEnrico Granata   if (m_options.m_pointer_as_array)
490520a422bSEnrico Granata     return true;
491520a422bSEnrico Granata 
492c1b7c09aSEnrico Granata   TypeSummaryImpl *entry = GetSummaryFormatter();
493c1b7c09aSEnrico Granata 
4948cf44d96SEnrico Granata   if (m_options.m_use_objc)
4958cf44d96SEnrico Granata     return false;
4968cf44d96SEnrico Granata 
497b9c1b51eSKate Stone   if (is_failed_description || m_curr_depth < m_options.m_max_depth) {
49805097246SAdrian Prantl     // We will show children for all concrete types. We won't show pointer
49905097246SAdrian Prantl     // contents unless a pointer depth has been specified. We won't reference
50005097246SAdrian Prantl     // contents unless the reference is the root object (depth of zero).
5014d93b8cdSEnrico Granata 
50205097246SAdrian Prantl     // Use a new temporary pointer depth in case we override the current
50305097246SAdrian Prantl     // pointer depth below...
5044d93b8cdSEnrico Granata 
505b9c1b51eSKate Stone     if (is_ptr || is_ref) {
50605097246SAdrian Prantl       // We have a pointer or reference whose value is an address. Make sure
50705097246SAdrian Prantl       // that address is not NULL
5084d93b8cdSEnrico Granata       AddressType ptr_address_type;
5094d93b8cdSEnrico Granata       if (m_valobj->GetPointerValue(&ptr_address_type) == 0)
5104d93b8cdSEnrico Granata         return false;
5114d93b8cdSEnrico Granata 
512c1b7c09aSEnrico Granata       const bool is_root_level = m_curr_depth == 0;
513c1b7c09aSEnrico Granata 
514b9c1b51eSKate Stone       if (is_ref && is_root_level) {
51505097246SAdrian Prantl         // If this is the root object (depth is zero) that we are showing and
51605097246SAdrian Prantl         // it is a reference, and no pointer depth has been supplied print out
51705097246SAdrian Prantl         // what it references. Don't do this at deeper depths otherwise we can
51805097246SAdrian Prantl         // end up with infinite recursion...
519c1b7c09aSEnrico Granata         return true;
5204d93b8cdSEnrico Granata       }
5214d93b8cdSEnrico Granata 
522e4e17b8cSTamas Berghammer       return curr_ptr_depth.CanAllowExpansion();
5234d93b8cdSEnrico Granata     }
5244d93b8cdSEnrico Granata 
5258a068e6cSEnrico Granata     return (!entry || entry->DoesPrintChildren(m_valobj) || m_summary.empty());
5264d93b8cdSEnrico Granata   }
5274d93b8cdSEnrico Granata   return false;
5284d93b8cdSEnrico Granata }
5294d93b8cdSEnrico Granata 
530b9c1b51eSKate Stone bool ValueObjectPrinter::ShouldExpandEmptyAggregates() {
531d26eb907SSiva Chandra   TypeSummaryImpl *entry = GetSummaryFormatter();
532d26eb907SSiva Chandra 
533d26eb907SSiva Chandra   if (!entry)
534d26eb907SSiva Chandra     return true;
535d26eb907SSiva Chandra 
536d26eb907SSiva Chandra   return entry->DoesPrintEmptyAggregates();
537d26eb907SSiva Chandra }
538d26eb907SSiva Chandra 
539b9c1b51eSKate Stone ValueObject *ValueObjectPrinter::GetValueObjectForChildrenGeneration() {
540d07cfd3aSEnrico Granata   return m_valobj;
5414d93b8cdSEnrico Granata }
5424d93b8cdSEnrico Granata 
543b9c1b51eSKate Stone void ValueObjectPrinter::PrintChildrenPreamble() {
544b9c1b51eSKate Stone   if (m_options.m_flat_output) {
5454d93b8cdSEnrico Granata     if (ShouldPrintValueObject())
5464d93b8cdSEnrico Granata       m_stream->EOL();
547b9c1b51eSKate Stone   } else {
5484d93b8cdSEnrico Granata     if (ShouldPrintValueObject())
5494d93b8cdSEnrico Granata       m_stream->PutCString(IsRef() ? ": {\n" : " {\n");
5504d93b8cdSEnrico Granata     m_stream->IndentMore();
5514d93b8cdSEnrico Granata   }
5524d93b8cdSEnrico Granata }
5534d93b8cdSEnrico Granata 
554b9c1b51eSKate Stone void ValueObjectPrinter::PrintChild(
555b9c1b51eSKate Stone     ValueObjectSP child_sp,
556b9c1b51eSKate Stone     const DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {
5579ac0dac1SEnrico Granata   const uint32_t consumed_depth = (!m_options.m_pointer_as_array) ? 1 : 0;
558b9c1b51eSKate Stone   const bool does_consume_ptr_depth =
5599ac0dac1SEnrico Granata       ((IsPtr() && !m_options.m_pointer_as_array) || IsRef());
560520a422bSEnrico Granata 
56126014690SGreg Clayton   DumpValueObjectOptions child_options(m_options);
562b9c1b51eSKate Stone   child_options.SetFormat(m_options.m_format)
563b9c1b51eSKate Stone       .SetSummary()
564b9c1b51eSKate Stone       .SetRootValueObjectName();
565b9c1b51eSKate Stone   child_options.SetScopeChecked(true)
566b9c1b51eSKate Stone       .SetHideName(m_options.m_hide_name)
567b9c1b51eSKate Stone       .SetHideValue(m_options.m_hide_value)
568b9c1b51eSKate Stone       .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1
569b9c1b51eSKate Stone                                ? child_options.m_omit_summary_depth -
570b9c1b51eSKate Stone                                      consumed_depth
571b9c1b51eSKate Stone                                : 0)
572520a422bSEnrico Granata       .SetElementCount(0);
5738cf44d96SEnrico Granata 
574b9c1b51eSKate Stone   if (child_sp.get()) {
575b9c1b51eSKate Stone     ValueObjectPrinter child_printer(
576b9c1b51eSKate Stone         child_sp.get(), m_stream, child_options,
577520a422bSEnrico Granata         does_consume_ptr_depth ? --curr_ptr_depth : curr_ptr_depth,
578b9c1b51eSKate Stone         m_curr_depth + consumed_depth, m_printed_instance_pointers);
5794d93b8cdSEnrico Granata     child_printer.PrintValueObject();
5804d93b8cdSEnrico Granata   }
5814d93b8cdSEnrico Granata }
5824d93b8cdSEnrico Granata 
583b9c1b51eSKate Stone uint32_t ValueObjectPrinter::GetMaxNumChildrenToPrint(bool &print_dotdotdot) {
5844d93b8cdSEnrico Granata   ValueObject *synth_m_valobj = GetValueObjectForChildrenGeneration();
5854d93b8cdSEnrico Granata 
5869ac0dac1SEnrico Granata   if (m_options.m_pointer_as_array)
5879ac0dac1SEnrico Granata     return m_options.m_pointer_as_array.m_element_count;
588520a422bSEnrico Granata 
5894d93b8cdSEnrico Granata   size_t num_children = synth_m_valobj->GetNumChildren();
5904d93b8cdSEnrico Granata   print_dotdotdot = false;
591b9c1b51eSKate Stone   if (num_children) {
592b9c1b51eSKate Stone     const size_t max_num_children =
593b9c1b51eSKate Stone         m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
5944d93b8cdSEnrico Granata 
595b9c1b51eSKate Stone     if (num_children > max_num_children && !m_options.m_ignore_cap) {
5964d93b8cdSEnrico Granata       print_dotdotdot = true;
5974d93b8cdSEnrico Granata       return max_num_children;
5984d93b8cdSEnrico Granata     }
5994d93b8cdSEnrico Granata   }
6004d93b8cdSEnrico Granata   return num_children;
6014d93b8cdSEnrico Granata }
6024d93b8cdSEnrico Granata 
603b9c1b51eSKate Stone void ValueObjectPrinter::PrintChildrenPostamble(bool print_dotdotdot) {
604b9c1b51eSKate Stone   if (!m_options.m_flat_output) {
605b9c1b51eSKate Stone     if (print_dotdotdot) {
606b9c1b51eSKate Stone       m_valobj->GetTargetSP()
607b9c1b51eSKate Stone           ->GetDebugger()
608b9c1b51eSKate Stone           .GetCommandInterpreter()
609b9c1b51eSKate Stone           .ChildrenTruncated();
6104d93b8cdSEnrico Granata       m_stream->Indent("...\n");
6114d93b8cdSEnrico Granata     }
6124d93b8cdSEnrico Granata     m_stream->IndentLess();
6134d93b8cdSEnrico Granata     m_stream->Indent("}\n");
6144d93b8cdSEnrico Granata   }
6154d93b8cdSEnrico Granata }
6164d93b8cdSEnrico Granata 
617b9c1b51eSKate Stone bool ValueObjectPrinter::ShouldPrintEmptyBrackets(bool value_printed,
618b9c1b51eSKate Stone                                                   bool summary_printed) {
6198cf44d96SEnrico Granata   ValueObject *synth_m_valobj = GetValueObjectForChildrenGeneration();
6208cf44d96SEnrico Granata 
6218cf44d96SEnrico Granata   if (!IsAggregate())
6228cf44d96SEnrico Granata     return false;
6238cf44d96SEnrico Granata 
624a6682a41SJonas Devlieghere   if (!m_options.m_reveal_empty_aggregates) {
6258cf44d96SEnrico Granata     if (value_printed || summary_printed)
6268cf44d96SEnrico Granata       return false;
6278cf44d96SEnrico Granata   }
6288cf44d96SEnrico Granata 
6298cf44d96SEnrico Granata   if (synth_m_valobj->MightHaveChildren())
6308cf44d96SEnrico Granata     return true;
6318cf44d96SEnrico Granata 
6328cf44d96SEnrico Granata   if (m_val_summary_ok)
6338cf44d96SEnrico Granata     return false;
6348cf44d96SEnrico Granata 
6358cf44d96SEnrico Granata   return true;
6368cf44d96SEnrico Granata }
6378cf44d96SEnrico Granata 
6389ac0dac1SEnrico Granata static constexpr size_t PhysicalIndexForLogicalIndex(size_t base, size_t stride,
6399ac0dac1SEnrico Granata                                                      size_t logical) {
6409ac0dac1SEnrico Granata   return base + logical * stride;
6419ac0dac1SEnrico Granata }
6429ac0dac1SEnrico Granata 
643b9c1b51eSKate Stone ValueObjectSP ValueObjectPrinter::GenerateChild(ValueObject *synth_valobj,
644b9c1b51eSKate Stone                                                 size_t idx) {
6459ac0dac1SEnrico Granata   if (m_options.m_pointer_as_array) {
646520a422bSEnrico Granata     // if generating pointer-as-array children, use GetSyntheticArrayMember
6479ac0dac1SEnrico Granata     return synth_valobj->GetSyntheticArrayMember(
6489ac0dac1SEnrico Granata         PhysicalIndexForLogicalIndex(
6499ac0dac1SEnrico Granata             m_options.m_pointer_as_array.m_base_element,
6509ac0dac1SEnrico Granata             m_options.m_pointer_as_array.m_stride, idx),
6519ac0dac1SEnrico Granata         true);
652b9c1b51eSKate Stone   } else {
653520a422bSEnrico Granata     // otherwise, do the usual thing
654520a422bSEnrico Granata     return synth_valobj->GetChildAtIndex(idx, true);
655520a422bSEnrico Granata   }
656520a422bSEnrico Granata }
657520a422bSEnrico Granata 
658b9c1b51eSKate Stone void ValueObjectPrinter::PrintChildren(
659b9c1b51eSKate Stone     bool value_printed, bool summary_printed,
660b9c1b51eSKate Stone     const DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {
6614d93b8cdSEnrico Granata   ValueObject *synth_m_valobj = GetValueObjectForChildrenGeneration();
6624d93b8cdSEnrico Granata 
6634d93b8cdSEnrico Granata   bool print_dotdotdot = false;
6644d93b8cdSEnrico Granata   size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
665b9c1b51eSKate Stone   if (num_children) {
6668cf44d96SEnrico Granata     bool any_children_printed = false;
6674d93b8cdSEnrico Granata 
668b9c1b51eSKate Stone     for (size_t idx = 0; idx < num_children; ++idx) {
669b9c1b51eSKate Stone       if (ValueObjectSP child_sp = GenerateChild(synth_m_valobj, idx)) {
670b9c1b51eSKate Stone         if (!any_children_printed) {
6718cf44d96SEnrico Granata           PrintChildrenPreamble();
6728cf44d96SEnrico Granata           any_children_printed = true;
6738cf44d96SEnrico Granata         }
6744d93b8cdSEnrico Granata         PrintChild(child_sp, curr_ptr_depth);
6754d93b8cdSEnrico Granata       }
6764d93b8cdSEnrico Granata     }
6778cf44d96SEnrico Granata 
6788cf44d96SEnrico Granata     if (any_children_printed)
6798cf44d96SEnrico Granata       PrintChildrenPostamble(print_dotdotdot);
680b9c1b51eSKate Stone     else {
681b9c1b51eSKate Stone       if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) {
6828cf44d96SEnrico Granata         if (ShouldPrintValueObject())
6838cf44d96SEnrico Granata           m_stream->PutCString(" {}\n");
6848cf44d96SEnrico Granata         else
6858cf44d96SEnrico Granata           m_stream->EOL();
686b9c1b51eSKate Stone       } else
6878cf44d96SEnrico Granata         m_stream->EOL();
6888cf44d96SEnrico Granata     }
689b9c1b51eSKate Stone   } else if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) {
6904d93b8cdSEnrico Granata     // Aggregate, no children...
691b9c1b51eSKate Stone     if (ShouldPrintValueObject()) {
692b9c1b51eSKate Stone       // if it has a synthetic value, then don't print {}, the synthetic
693b9c1b51eSKate Stone       // children are probably only being used to vend a value
694b9c1b51eSKate Stone       if (m_valobj->DoesProvideSyntheticValue() ||
695b9c1b51eSKate Stone           !ShouldExpandEmptyAggregates())
696d07cfd3aSEnrico Granata         m_stream->PutCString("\n");
697d07cfd3aSEnrico Granata       else
6984d93b8cdSEnrico Granata         m_stream->PutCString(" {}\n");
6994d93b8cdSEnrico Granata     }
700b9c1b51eSKate Stone   } else {
7014d93b8cdSEnrico Granata     if (ShouldPrintValueObject())
7024d93b8cdSEnrico Granata       m_stream->EOL();
7034d93b8cdSEnrico Granata   }
7044d93b8cdSEnrico Granata }
7054d93b8cdSEnrico Granata 
706b9c1b51eSKate Stone bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) {
707d07cfd3aSEnrico Granata   if (!GetMostSpecializedValue() || m_valobj == nullptr)
708a29cb0baSEnrico Granata     return false;
709a29cb0baSEnrico Granata 
710a29cb0baSEnrico Granata   ValueObject *synth_m_valobj = GetValueObjectForChildrenGeneration();
711a29cb0baSEnrico Granata 
712a29cb0baSEnrico Granata   bool print_dotdotdot = false;
713a29cb0baSEnrico Granata   size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
714a29cb0baSEnrico Granata 
715b9c1b51eSKate Stone   if (num_children) {
716a29cb0baSEnrico Granata     m_stream->PutChar('(');
717a29cb0baSEnrico Granata 
718b9c1b51eSKate Stone     for (uint32_t idx = 0; idx < num_children; ++idx) {
719a29cb0baSEnrico Granata       lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
720ddac7611SEnrico Granata       if (child_sp)
721b9c1b51eSKate Stone         child_sp = child_sp->GetQualifiedRepresentationIfAvailable(
722b9c1b51eSKate Stone             m_options.m_use_dynamic, m_options.m_use_synthetic);
723b9c1b51eSKate Stone       if (child_sp) {
724a29cb0baSEnrico Granata         if (idx)
725a29cb0baSEnrico Granata           m_stream->PutCString(", ");
726b9c1b51eSKate Stone         if (!hide_names) {
727a29cb0baSEnrico Granata           const char *name = child_sp.get()->GetName().AsCString();
728b9c1b51eSKate Stone           if (name && *name) {
729a29cb0baSEnrico Granata             m_stream->PutCString(name);
730a29cb0baSEnrico Granata             m_stream->PutCString(" = ");
731a29cb0baSEnrico Granata           }
732a29cb0baSEnrico Granata         }
733b9c1b51eSKate Stone         child_sp->DumpPrintableRepresentation(
734b9c1b51eSKate Stone             *m_stream, ValueObject::eValueObjectRepresentationStyleSummary,
7357aafb6a1SEnrico Granata             m_options.m_format,
73665d86e4fSEnrico Granata             ValueObject::PrintableRepresentationSpecialCases::eDisable);
737a29cb0baSEnrico Granata       }
738a29cb0baSEnrico Granata     }
739a29cb0baSEnrico Granata 
740a29cb0baSEnrico Granata     if (print_dotdotdot)
741a29cb0baSEnrico Granata       m_stream->PutCString(", ...)");
742a29cb0baSEnrico Granata     else
743a29cb0baSEnrico Granata       m_stream->PutChar(')');
744a29cb0baSEnrico Granata   }
745a29cb0baSEnrico Granata   return true;
746a29cb0baSEnrico Granata }
747a29cb0baSEnrico Granata 
748b9c1b51eSKate Stone void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
749b9c1b51eSKate Stone                                                bool summary_printed) {
750dc333e63SJonas Devlieghere   // This flag controls whether we tried to display a description for this
751dc333e63SJonas Devlieghere   // object and failed if that happens, we want to display the children if any.
752b9c1b51eSKate Stone   bool is_failed_description =
753b9c1b51eSKate Stone       !PrintObjectDescriptionIfNeeded(value_printed, summary_printed);
7544d93b8cdSEnrico Granata 
755dc333e63SJonas Devlieghere   DumpValueObjectOptions::PointerDepth curr_ptr_depth = m_ptr_depth;
756dc333e63SJonas Devlieghere   const bool print_children =
757b9c1b51eSKate Stone       ShouldPrintChildren(is_failed_description, curr_ptr_depth);
758dc333e63SJonas Devlieghere   const bool print_oneline =
759b9c1b51eSKate Stone       (curr_ptr_depth.CanAllowExpansion() || m_options.m_show_types ||
760b9c1b51eSKate Stone        !m_options.m_allow_oneliner_mode || m_options.m_flat_output ||
7619ac0dac1SEnrico Granata        (m_options.m_pointer_as_array) || m_options.m_show_location)
762b9c1b51eSKate Stone           ? false
763b9c1b51eSKate Stone           : DataVisualization::ShouldPrintAsOneLiner(*m_valobj);
764dc333e63SJonas Devlieghere   if (print_children && IsInstancePointer()) {
765dc333e63SJonas Devlieghere     uint64_t instance_ptr_value = m_valobj->GetValueAsUnsigned(0);
766b9c1b51eSKate Stone     if (m_printed_instance_pointers->count(instance_ptr_value)) {
767dc333e63SJonas Devlieghere       // We already printed this instance-is-pointer thing, so don't expand it.
7688cf44d96SEnrico Granata       m_stream->PutCString(" {...}\n");
7698cf44d96SEnrico Granata       return;
770dc333e63SJonas Devlieghere     } else {
771dc333e63SJonas Devlieghere       // Remember this guy for future reference.
772dc333e63SJonas Devlieghere       m_printed_instance_pointers->emplace(instance_ptr_value);
773dc333e63SJonas Devlieghere     }
7748cf44d96SEnrico Granata   }
7754d93b8cdSEnrico Granata 
776b9c1b51eSKate Stone   if (print_children) {
777b9c1b51eSKate Stone     if (print_oneline) {
778a29cb0baSEnrico Granata       m_stream->PutChar(' ');
779a29cb0baSEnrico Granata       PrintChildrenOneLiner(false);
780a29cb0baSEnrico Granata       m_stream->EOL();
781b9c1b51eSKate Stone     } else
782c1b7c09aSEnrico Granata       PrintChildren(value_printed, summary_printed, curr_ptr_depth);
783b9c1b51eSKate Stone   } else if (m_curr_depth >= m_options.m_max_depth && IsAggregate() &&
784b9c1b51eSKate Stone              ShouldPrintValueObject()) {
7854d93b8cdSEnrico Granata     m_stream->PutCString("{...}\n");
786b9c1b51eSKate Stone   } else
787245b3caaSEnrico Granata     m_stream->EOL();
7884d93b8cdSEnrico Granata }
789