180814287SRaphael 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
ValueObjectPrinter(ValueObject * valobj,Stream * s)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
ValueObjectPrinter(ValueObject * valobj,Stream * s,const DumpValueObjectOptions & options)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
ValueObjectPrinter(ValueObject * valobj,Stream * s,const DumpValueObjectOptions & options,const DumpValueObjectOptions::PointerDepth & ptr_depth,uint32_t curr_depth,InstancePointersSetSP printed_instance_pointers)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
Init(ValueObject * valobj,Stream * s,const DumpValueObjectOptions & options,const DumpValueObjectOptions::PointerDepth & ptr_depth,uint32_t curr_depth,InstancePointersSetSP printed_instance_pointers)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
PrintValueObject()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
GetMostSpecializedValue()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
GetDescriptionForDisplay()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
GetRootNameForDisplay()15458e34edeSJonas Devlieghere const char *ValueObjectPrinter::GetRootNameForDisplay() {
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();
15858e34edeSJonas Devlieghere return root_valobj_name ? root_valobj_name : "";
1594d93b8cdSEnrico Granata }
1604d93b8cdSEnrico Granata
ShouldPrintValueObject()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
IsNil()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
IsUninitialized()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
IsPtr()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
IsRef()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
IsAggregate()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
IsInstancePointer()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
PrintLocationIfNeeded()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
PrintDecl()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()) {
24258e34edeSJonas Devlieghere type_name = m_options.m_use_type_display_name
24358e34edeSJonas Devlieghere ? m_valobj->GetDisplayTypeName()
24458e34edeSJonas Devlieghere : m_valobj->GetQualifiedTypeName();
245b9c1b51eSKate Stone } else {
246b9c1b51eSKate Stone // only show an invalid type name if the user explicitly triggered
247b9c1b51eSKate Stone // show_type
24826014690SGreg Clayton if (m_options.m_show_types)
249e0ee1e1cSEnrico Granata type_name = ConstString("<invalid type>");
2504d93b8cdSEnrico Granata }
2514d93b8cdSEnrico Granata
252b9c1b51eSKate Stone if (type_name) {
253e0ee1e1cSEnrico Granata std::string type_name_str(type_name.GetCString());
254b9c1b51eSKate Stone if (m_options.m_hide_pointer_value) {
255b9c1b51eSKate Stone for (auto iter = type_name_str.find(" *"); iter != std::string::npos;
256b9c1b51eSKate Stone iter = type_name_str.find(" *")) {
257e0ee1e1cSEnrico Granata type_name_str.erase(iter, 2);
258e0ee1e1cSEnrico Granata }
259e0ee1e1cSEnrico Granata }
26058e34edeSJonas Devlieghere typeName << type_name_str.c_str();
261e0ee1e1cSEnrico Granata }
262e0ee1e1cSEnrico Granata }
263e0ee1e1cSEnrico Granata
264e0ee1e1cSEnrico Granata StreamString varName;
265e0ee1e1cSEnrico Granata
266b9c1b51eSKate Stone if (!m_options.m_hide_name) {
2673014efe0SAlex Langford if (m_options.m_flat_output)
2683014efe0SAlex Langford m_valobj->GetExpressionPath(varName);
26958e34edeSJonas Devlieghere else
27058e34edeSJonas Devlieghere varName << GetRootNameForDisplay();
2713014efe0SAlex Langford }
272e0ee1e1cSEnrico Granata
273e0ee1e1cSEnrico Granata bool decl_printed = false;
274b9c1b51eSKate Stone if (!m_options.m_decl_printing_helper) {
275b9c1b51eSKate Stone // if the user didn't give us a custom helper, pick one based upon the
276b9c1b51eSKate Stone // language, either the one that this printer is bound to, or the preferred
277b9c1b51eSKate Stone // one for the ValueObject
278b9c1b51eSKate Stone lldb::LanguageType lang_type =
279b9c1b51eSKate Stone (m_options.m_varformat_language == lldb::eLanguageTypeUnknown)
280b9c1b51eSKate Stone ? m_valobj->GetPreferredDisplayLanguage()
281b9c1b51eSKate Stone : m_options.m_varformat_language;
282b9c1b51eSKate Stone if (Language *lang_plugin = Language::FindPlugin(lang_type)) {
28326014690SGreg Clayton m_options.m_decl_printing_helper = lang_plugin->GetDeclPrintingHelper();
284c8e7649aSEnrico Granata }
285c8e7649aSEnrico Granata }
286c8e7649aSEnrico Granata
287b9c1b51eSKate Stone if (m_options.m_decl_printing_helper) {
288c156427dSZachary Turner ConstString type_name_cstr(typeName.GetString());
289c156427dSZachary Turner ConstString var_name_cstr(varName.GetString());
290e0ee1e1cSEnrico Granata
291e0ee1e1cSEnrico Granata StreamString dest_stream;
292b9c1b51eSKate Stone if (m_options.m_decl_printing_helper(type_name_cstr, var_name_cstr,
293b9c1b51eSKate Stone m_options, dest_stream)) {
294e0ee1e1cSEnrico Granata decl_printed = true;
295c156427dSZachary Turner m_stream->PutCString(dest_stream.GetString());
296e0ee1e1cSEnrico Granata }
297e0ee1e1cSEnrico Granata }
298e0ee1e1cSEnrico Granata
299c8e7649aSEnrico Granata // if the helper failed, or there is none, do a default thing
300b9c1b51eSKate Stone if (!decl_printed) {
301c156427dSZachary Turner if (!typeName.Empty())
302c8e7649aSEnrico Granata m_stream->Printf("(%s) ", typeName.GetData());
303c156427dSZachary Turner if (!varName.Empty())
304e0ee1e1cSEnrico Granata m_stream->Printf("%s =", varName.GetData());
30526014690SGreg Clayton else if (!m_options.m_hide_name)
306e0ee1e1cSEnrico Granata m_stream->Printf(" =");
307e0ee1e1cSEnrico Granata }
3084d93b8cdSEnrico Granata }
3094d93b8cdSEnrico Granata
CheckScopeIfNeeded()310b9c1b51eSKate Stone bool ValueObjectPrinter::CheckScopeIfNeeded() {
31126014690SGreg Clayton if (m_options.m_scope_already_checked)
3124d93b8cdSEnrico Granata return true;
3134d93b8cdSEnrico Granata return m_valobj->IsInScope();
3144d93b8cdSEnrico Granata }
3154d93b8cdSEnrico Granata
GetSummaryFormatter(bool null_if_omitted)316b9c1b51eSKate Stone TypeSummaryImpl *ValueObjectPrinter::GetSummaryFormatter(bool null_if_omitted) {
317a6682a41SJonas Devlieghere if (!m_summary_formatter.second) {
318b9c1b51eSKate Stone TypeSummaryImpl *entry = m_options.m_summary_sp
319b9c1b51eSKate Stone ? m_options.m_summary_sp.get()
320b9c1b51eSKate Stone : m_valobj->GetSummaryFormat().get();
3214d93b8cdSEnrico Granata
32226014690SGreg Clayton if (m_options.m_omit_summary_depth > 0)
323248a1305SKonrad Kleine entry = nullptr;
3244d93b8cdSEnrico Granata m_summary_formatter.first = entry;
3254d93b8cdSEnrico Granata m_summary_formatter.second = true;
3264d93b8cdSEnrico Granata }
3278cf44d96SEnrico Granata if (m_options.m_omit_summary_depth > 0 && null_if_omitted)
3288cf44d96SEnrico Granata return nullptr;
3294d93b8cdSEnrico Granata return m_summary_formatter.first;
3304d93b8cdSEnrico Granata }
3314d93b8cdSEnrico Granata
IsPointerValue(const CompilerType & type)332b9c1b51eSKate Stone static bool IsPointerValue(const CompilerType &type) {
333e0ee1e1cSEnrico Granata Flags type_flags(type.GetTypeInfo());
3348cf44d96SEnrico Granata if (type_flags.AnySet(eTypeInstanceIsPointer | eTypeIsPointer))
335e0ee1e1cSEnrico Granata return type_flags.AllClear(eTypeIsBuiltIn);
336e0ee1e1cSEnrico Granata return false;
337e0ee1e1cSEnrico Granata }
338e0ee1e1cSEnrico Granata
GetValueSummaryError(std::string & value,std::string & summary,std::string & error)339b9c1b51eSKate Stone void ValueObjectPrinter::GetValueSummaryError(std::string &value,
3404d93b8cdSEnrico Granata std::string &summary,
341b9c1b51eSKate Stone std::string &error) {
342520a422bSEnrico Granata lldb::Format format = m_options.m_format;
343b9c1b51eSKate Stone // if I am printing synthetized elements, apply the format to those elements
344b9c1b51eSKate Stone // only
3459ac0dac1SEnrico Granata if (m_options.m_pointer_as_array)
346520a422bSEnrico Granata m_valobj->GetValueAsCString(lldb::eFormatDefault, value);
347520a422bSEnrico Granata else if (format != eFormatDefault && format != m_valobj->GetFormat())
348520a422bSEnrico Granata m_valobj->GetValueAsCString(format, value);
349b9c1b51eSKate Stone else {
3504d93b8cdSEnrico Granata const char *val_cstr = m_valobj->GetValueAsCString();
351465f4bc2SEnrico Granata if (val_cstr)
352465f4bc2SEnrico Granata value.assign(val_cstr);
353465f4bc2SEnrico Granata }
3544d93b8cdSEnrico Granata const char *err_cstr = m_valobj->GetError().AsCString();
3554d93b8cdSEnrico Granata if (err_cstr)
3564d93b8cdSEnrico Granata error.assign(err_cstr);
3574d93b8cdSEnrico Granata
358406ad187SJonas Devlieghere if (!ShouldPrintValueObject())
359406ad187SJonas Devlieghere return;
360406ad187SJonas Devlieghere
361406ad187SJonas Devlieghere if (IsNil()) {
362406ad187SJonas Devlieghere lldb::LanguageType lang_type =
363406ad187SJonas Devlieghere (m_options.m_varformat_language == lldb::eLanguageTypeUnknown)
364406ad187SJonas Devlieghere ? m_valobj->GetPreferredDisplayLanguage()
365406ad187SJonas Devlieghere : m_options.m_varformat_language;
366406ad187SJonas Devlieghere if (Language *lang_plugin = Language::FindPlugin(lang_type)) {
367406ad187SJonas Devlieghere summary.assign(lang_plugin->GetNilReferenceSummaryString().str());
368406ad187SJonas Devlieghere } else {
369406ad187SJonas Devlieghere // We treat C as the fallback language rather than as a separate Language
370406ad187SJonas Devlieghere // plugin.
371406ad187SJonas Devlieghere summary.assign("NULL");
372406ad187SJonas Devlieghere }
373406ad187SJonas Devlieghere } else if (IsUninitialized()) {
374608d67c1SEnrico Granata summary.assign("<uninitialized>");
375406ad187SJonas Devlieghere } else if (m_options.m_omit_summary_depth == 0) {
3764d93b8cdSEnrico Granata TypeSummaryImpl *entry = GetSummaryFormatter();
377406ad187SJonas Devlieghere if (entry) {
378b9c1b51eSKate Stone m_valobj->GetSummaryAsCString(entry, summary,
379b9c1b51eSKate Stone m_options.m_varformat_language);
380406ad187SJonas Devlieghere } else {
381b9c1b51eSKate Stone const char *sum_cstr =
382b9c1b51eSKate Stone m_valobj->GetSummaryAsCString(m_options.m_varformat_language);
3834d93b8cdSEnrico Granata if (sum_cstr)
3844d93b8cdSEnrico Granata summary.assign(sum_cstr);
3854d93b8cdSEnrico Granata }
3864d93b8cdSEnrico Granata }
3874d93b8cdSEnrico Granata }
3884d93b8cdSEnrico Granata
PrintValueAndSummaryIfNeeded(bool & value_printed,bool & summary_printed)389b9c1b51eSKate Stone bool ValueObjectPrinter::PrintValueAndSummaryIfNeeded(bool &value_printed,
390b9c1b51eSKate Stone bool &summary_printed) {
3914d93b8cdSEnrico Granata bool error_printed = false;
392b9c1b51eSKate Stone if (ShouldPrintValueObject()) {
3934d93b8cdSEnrico Granata if (!CheckScopeIfNeeded())
3944d93b8cdSEnrico Granata m_error.assign("out of scope");
395b9c1b51eSKate Stone if (m_error.empty()) {
3964d93b8cdSEnrico Granata GetValueSummaryError(m_value, m_summary, m_error);
3974d93b8cdSEnrico Granata }
398b9c1b51eSKate Stone if (m_error.size()) {
399b9c1b51eSKate Stone // we need to support scenarios in which it is actually fine for a value
40005097246SAdrian Prantl // to have no type but - on the other hand - if we get an error *AND*
40105097246SAdrian Prantl // have no type, we try to get out gracefully, since most often that
40205097246SAdrian Prantl // combination means "could not resolve a type" and the default failure
40305097246SAdrian Prantl // mode is quite ugly
404b9c1b51eSKate Stone if (!m_compiler_type.IsValid()) {
4058cf44d96SEnrico Granata m_stream->Printf(" <could not resolve type>");
4068cf44d96SEnrico Granata return false;
4078cf44d96SEnrico Granata }
4088cf44d96SEnrico Granata
4094d93b8cdSEnrico Granata error_printed = true;
4104d93b8cdSEnrico Granata m_stream->Printf(" <%s>\n", m_error.c_str());
411b9c1b51eSKate Stone } else {
41205097246SAdrian Prantl // Make sure we have a value and make sure the summary didn't specify
41305097246SAdrian Prantl // that the value should not be printed - and do not print the value if
41405097246SAdrian Prantl // this thing is nil (but show the value if the user passes a format
41505097246SAdrian Prantl // explicitly)
4164d93b8cdSEnrico Granata TypeSummaryImpl *entry = GetSummaryFormatter();
417406ad187SJonas Devlieghere const bool has_nil_or_uninitialized_summary =
418406ad187SJonas Devlieghere (IsNil() || IsUninitialized()) && !m_summary.empty();
419406ad187SJonas Devlieghere if (!has_nil_or_uninitialized_summary && !m_value.empty() &&
420248a1305SKonrad Kleine (entry == nullptr ||
421248a1305SKonrad Kleine (entry->DoesPrintValue(m_valobj) ||
422b9c1b51eSKate Stone m_options.m_format != eFormatDefault) ||
423b9c1b51eSKate Stone m_summary.empty()) &&
424b9c1b51eSKate Stone !m_options.m_hide_value) {
425b9c1b51eSKate Stone if (m_options.m_hide_pointer_value &&
426b9c1b51eSKate Stone IsPointerValue(m_valobj->GetCompilerType())) {
427b9c1b51eSKate Stone } else {
4284d93b8cdSEnrico Granata m_stream->Printf(" %s", m_value.c_str());
4294d93b8cdSEnrico Granata value_printed = true;
4304d93b8cdSEnrico Granata }
431e0ee1e1cSEnrico Granata }
4324d93b8cdSEnrico Granata
433b9c1b51eSKate Stone if (m_summary.size()) {
4344d93b8cdSEnrico Granata m_stream->Printf(" %s", m_summary.c_str());
4354d93b8cdSEnrico Granata summary_printed = true;
4364d93b8cdSEnrico Granata }
4374d93b8cdSEnrico Granata }
4384d93b8cdSEnrico Granata }
4394d93b8cdSEnrico Granata return !error_printed;
4404d93b8cdSEnrico Granata }
4414d93b8cdSEnrico Granata
PrintObjectDescriptionIfNeeded(bool value_printed,bool summary_printed)442b9c1b51eSKate Stone bool ValueObjectPrinter::PrintObjectDescriptionIfNeeded(bool value_printed,
443b9c1b51eSKate Stone bool summary_printed) {
444b9c1b51eSKate Stone if (ShouldPrintValueObject()) {
4454d93b8cdSEnrico Granata // let's avoid the overly verbose no description error for a nil thing
446b9c1b51eSKate Stone if (m_options.m_use_objc && !IsNil() && !IsUninitialized() &&
4479ac0dac1SEnrico Granata (!m_options.m_pointer_as_array)) {
44826014690SGreg Clayton if (!m_options.m_hide_value || !m_options.m_hide_name)
4494d93b8cdSEnrico Granata m_stream->Printf(" ");
4504d93b8cdSEnrico Granata const char *object_desc = nullptr;
4514d93b8cdSEnrico Granata if (value_printed || summary_printed)
4524d93b8cdSEnrico Granata object_desc = m_valobj->GetObjectDescription();
4534d93b8cdSEnrico Granata else
4544d93b8cdSEnrico Granata object_desc = GetDescriptionForDisplay();
455b9c1b51eSKate Stone if (object_desc && *object_desc) {
456b9923589SJim Ingham // If the description already ends with a \n don't add another one.
457b9923589SJim Ingham size_t object_end = strlen(object_desc) - 1;
458b9923589SJim Ingham if (object_desc[object_end] == '\n')
459b9923589SJim Ingham m_stream->Printf("%s", object_desc);
460b9923589SJim Ingham else
4614d93b8cdSEnrico Granata m_stream->Printf("%s\n", object_desc);
4624d93b8cdSEnrico Granata return true;
463a6682a41SJonas Devlieghere } else if (!value_printed && !summary_printed)
4644d93b8cdSEnrico Granata return true;
4654d93b8cdSEnrico Granata else
4664d93b8cdSEnrico Granata return false;
4674d93b8cdSEnrico Granata }
4684d93b8cdSEnrico Granata }
4694d93b8cdSEnrico Granata return true;
4704d93b8cdSEnrico Granata }
4714d93b8cdSEnrico Granata
CanAllowExpansion() const472b9c1b51eSKate Stone bool DumpValueObjectOptions::PointerDepth::CanAllowExpansion() const {
473b9c1b51eSKate Stone switch (m_mode) {
474c1b7c09aSEnrico Granata case Mode::Always:
475c1b7c09aSEnrico Granata case Mode::Default:
476e4e17b8cSTamas Berghammer return m_count > 0;
477c1b7c09aSEnrico Granata case Mode::Never:
478c1b7c09aSEnrico Granata return false;
479c1b7c09aSEnrico Granata }
48084f5b0dfSZachary Turner return false;
481c1b7c09aSEnrico Granata }
482c1b7c09aSEnrico Granata
ShouldPrintChildren(bool is_failed_description,DumpValueObjectOptions::PointerDepth & curr_ptr_depth)483b9c1b51eSKate Stone bool ValueObjectPrinter::ShouldPrintChildren(
484b9c1b51eSKate Stone bool is_failed_description,
485b9c1b51eSKate Stone DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {
4864d93b8cdSEnrico Granata const bool is_ref = IsRef();
4874d93b8cdSEnrico Granata const bool is_ptr = IsPtr();
488608d67c1SEnrico Granata const bool is_uninit = IsUninitialized();
489608d67c1SEnrico Granata
490608d67c1SEnrico Granata if (is_uninit)
491608d67c1SEnrico Granata return false;
4924d93b8cdSEnrico Granata
49305097246SAdrian Prantl // if the user has specified an element count, always print children as it is
49405097246SAdrian Prantl // explicit user demand being honored
4959ac0dac1SEnrico Granata if (m_options.m_pointer_as_array)
496520a422bSEnrico Granata return true;
497520a422bSEnrico Granata
498c1b7c09aSEnrico Granata TypeSummaryImpl *entry = GetSummaryFormatter();
499c1b7c09aSEnrico Granata
5008cf44d96SEnrico Granata if (m_options.m_use_objc)
5018cf44d96SEnrico Granata return false;
5028cf44d96SEnrico Granata
503*2f9fc576SDave Lee if (is_failed_description || !HasReachedMaximumDepth()) {
50405097246SAdrian Prantl // We will show children for all concrete types. We won't show pointer
50505097246SAdrian Prantl // contents unless a pointer depth has been specified. We won't reference
50605097246SAdrian Prantl // contents unless the reference is the root object (depth of zero).
5074d93b8cdSEnrico Granata
50805097246SAdrian Prantl // Use a new temporary pointer depth in case we override the current
50905097246SAdrian Prantl // pointer depth below...
5104d93b8cdSEnrico Granata
511b9c1b51eSKate Stone if (is_ptr || is_ref) {
51205097246SAdrian Prantl // We have a pointer or reference whose value is an address. Make sure
51305097246SAdrian Prantl // that address is not NULL
5144d93b8cdSEnrico Granata AddressType ptr_address_type;
5154d93b8cdSEnrico Granata if (m_valobj->GetPointerValue(&ptr_address_type) == 0)
5164d93b8cdSEnrico Granata return false;
5174d93b8cdSEnrico Granata
518c1b7c09aSEnrico Granata const bool is_root_level = m_curr_depth == 0;
519c1b7c09aSEnrico Granata
520b9c1b51eSKate Stone if (is_ref && is_root_level) {
52105097246SAdrian Prantl // If this is the root object (depth is zero) that we are showing and
52205097246SAdrian Prantl // it is a reference, and no pointer depth has been supplied print out
52305097246SAdrian Prantl // what it references. Don't do this at deeper depths otherwise we can
52405097246SAdrian Prantl // end up with infinite recursion...
525c1b7c09aSEnrico Granata return true;
5264d93b8cdSEnrico Granata }
5274d93b8cdSEnrico Granata
528e4e17b8cSTamas Berghammer return curr_ptr_depth.CanAllowExpansion();
5294d93b8cdSEnrico Granata }
5304d93b8cdSEnrico Granata
5318a068e6cSEnrico Granata return (!entry || entry->DoesPrintChildren(m_valobj) || m_summary.empty());
5324d93b8cdSEnrico Granata }
5334d93b8cdSEnrico Granata return false;
5344d93b8cdSEnrico Granata }
5354d93b8cdSEnrico Granata
ShouldExpandEmptyAggregates()536b9c1b51eSKate Stone bool ValueObjectPrinter::ShouldExpandEmptyAggregates() {
537d26eb907SSiva Chandra TypeSummaryImpl *entry = GetSummaryFormatter();
538d26eb907SSiva Chandra
539d26eb907SSiva Chandra if (!entry)
540d26eb907SSiva Chandra return true;
541d26eb907SSiva Chandra
542d26eb907SSiva Chandra return entry->DoesPrintEmptyAggregates();
543d26eb907SSiva Chandra }
544d26eb907SSiva Chandra
GetValueObjectForChildrenGeneration()545b9c1b51eSKate Stone ValueObject *ValueObjectPrinter::GetValueObjectForChildrenGeneration() {
546d07cfd3aSEnrico Granata return m_valobj;
5474d93b8cdSEnrico Granata }
5484d93b8cdSEnrico Granata
PrintChildrenPreamble()549b9c1b51eSKate Stone void ValueObjectPrinter::PrintChildrenPreamble() {
550b9c1b51eSKate Stone if (m_options.m_flat_output) {
5514d93b8cdSEnrico Granata if (ShouldPrintValueObject())
5524d93b8cdSEnrico Granata m_stream->EOL();
553b9c1b51eSKate Stone } else {
5544d93b8cdSEnrico Granata if (ShouldPrintValueObject())
5554d93b8cdSEnrico Granata m_stream->PutCString(IsRef() ? ": {\n" : " {\n");
5564d93b8cdSEnrico Granata m_stream->IndentMore();
5574d93b8cdSEnrico Granata }
5584d93b8cdSEnrico Granata }
5594d93b8cdSEnrico Granata
PrintChild(ValueObjectSP child_sp,const DumpValueObjectOptions::PointerDepth & curr_ptr_depth)560b9c1b51eSKate Stone void ValueObjectPrinter::PrintChild(
561b9c1b51eSKate Stone ValueObjectSP child_sp,
562b9c1b51eSKate Stone const DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {
5639ac0dac1SEnrico Granata const uint32_t consumed_depth = (!m_options.m_pointer_as_array) ? 1 : 0;
564b9c1b51eSKate Stone const bool does_consume_ptr_depth =
5659ac0dac1SEnrico Granata ((IsPtr() && !m_options.m_pointer_as_array) || IsRef());
566520a422bSEnrico Granata
56726014690SGreg Clayton DumpValueObjectOptions child_options(m_options);
568b9c1b51eSKate Stone child_options.SetFormat(m_options.m_format)
569b9c1b51eSKate Stone .SetSummary()
570b9c1b51eSKate Stone .SetRootValueObjectName();
571b9c1b51eSKate Stone child_options.SetScopeChecked(true)
572b9c1b51eSKate Stone .SetHideName(m_options.m_hide_name)
573b9c1b51eSKate Stone .SetHideValue(m_options.m_hide_value)
574b9c1b51eSKate Stone .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1
575b9c1b51eSKate Stone ? child_options.m_omit_summary_depth -
576b9c1b51eSKate Stone consumed_depth
577b9c1b51eSKate Stone : 0)
578520a422bSEnrico Granata .SetElementCount(0);
5798cf44d96SEnrico Granata
580b9c1b51eSKate Stone if (child_sp.get()) {
581b9c1b51eSKate Stone ValueObjectPrinter child_printer(
582b9c1b51eSKate Stone child_sp.get(), m_stream, child_options,
583520a422bSEnrico Granata does_consume_ptr_depth ? --curr_ptr_depth : curr_ptr_depth,
584b9c1b51eSKate Stone m_curr_depth + consumed_depth, m_printed_instance_pointers);
5854d93b8cdSEnrico Granata child_printer.PrintValueObject();
5864d93b8cdSEnrico Granata }
5874d93b8cdSEnrico Granata }
5884d93b8cdSEnrico Granata
GetMaxNumChildrenToPrint(bool & print_dotdotdot)589b9c1b51eSKate Stone uint32_t ValueObjectPrinter::GetMaxNumChildrenToPrint(bool &print_dotdotdot) {
5904d93b8cdSEnrico Granata ValueObject *synth_m_valobj = GetValueObjectForChildrenGeneration();
5914d93b8cdSEnrico Granata
5929ac0dac1SEnrico Granata if (m_options.m_pointer_as_array)
5939ac0dac1SEnrico Granata return m_options.m_pointer_as_array.m_element_count;
594520a422bSEnrico Granata
5954d93b8cdSEnrico Granata size_t num_children = synth_m_valobj->GetNumChildren();
5964d93b8cdSEnrico Granata print_dotdotdot = false;
597b9c1b51eSKate Stone if (num_children) {
598b9c1b51eSKate Stone const size_t max_num_children =
599b9c1b51eSKate Stone m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
6004d93b8cdSEnrico Granata
601b9c1b51eSKate Stone if (num_children > max_num_children && !m_options.m_ignore_cap) {
6024d93b8cdSEnrico Granata print_dotdotdot = true;
6034d93b8cdSEnrico Granata return max_num_children;
6044d93b8cdSEnrico Granata }
6054d93b8cdSEnrico Granata }
6064d93b8cdSEnrico Granata return num_children;
6074d93b8cdSEnrico Granata }
6084d93b8cdSEnrico Granata
PrintChildrenPostamble(bool print_dotdotdot)609b9c1b51eSKate Stone void ValueObjectPrinter::PrintChildrenPostamble(bool print_dotdotdot) {
610b9c1b51eSKate Stone if (!m_options.m_flat_output) {
611b9c1b51eSKate Stone if (print_dotdotdot) {
612b9c1b51eSKate Stone m_valobj->GetTargetSP()
613b9c1b51eSKate Stone ->GetDebugger()
614b9c1b51eSKate Stone .GetCommandInterpreter()
615b9c1b51eSKate Stone .ChildrenTruncated();
6164d93b8cdSEnrico Granata m_stream->Indent("...\n");
6174d93b8cdSEnrico Granata }
6184d93b8cdSEnrico Granata m_stream->IndentLess();
6194d93b8cdSEnrico Granata m_stream->Indent("}\n");
6204d93b8cdSEnrico Granata }
6214d93b8cdSEnrico Granata }
6224d93b8cdSEnrico Granata
ShouldPrintEmptyBrackets(bool value_printed,bool summary_printed)623b9c1b51eSKate Stone bool ValueObjectPrinter::ShouldPrintEmptyBrackets(bool value_printed,
624b9c1b51eSKate Stone bool summary_printed) {
6258cf44d96SEnrico Granata ValueObject *synth_m_valobj = GetValueObjectForChildrenGeneration();
6268cf44d96SEnrico Granata
6278cf44d96SEnrico Granata if (!IsAggregate())
6288cf44d96SEnrico Granata return false;
6298cf44d96SEnrico Granata
630a6682a41SJonas Devlieghere if (!m_options.m_reveal_empty_aggregates) {
6318cf44d96SEnrico Granata if (value_printed || summary_printed)
6328cf44d96SEnrico Granata return false;
6338cf44d96SEnrico Granata }
6348cf44d96SEnrico Granata
6358cf44d96SEnrico Granata if (synth_m_valobj->MightHaveChildren())
6368cf44d96SEnrico Granata return true;
6378cf44d96SEnrico Granata
6388cf44d96SEnrico Granata if (m_val_summary_ok)
6398cf44d96SEnrico Granata return false;
6408cf44d96SEnrico Granata
6418cf44d96SEnrico Granata return true;
6428cf44d96SEnrico Granata }
6438cf44d96SEnrico Granata
PhysicalIndexForLogicalIndex(size_t base,size_t stride,size_t logical)6449ac0dac1SEnrico Granata static constexpr size_t PhysicalIndexForLogicalIndex(size_t base, size_t stride,
6459ac0dac1SEnrico Granata size_t logical) {
6469ac0dac1SEnrico Granata return base + logical * stride;
6479ac0dac1SEnrico Granata }
6489ac0dac1SEnrico Granata
GenerateChild(ValueObject * synth_valobj,size_t idx)649b9c1b51eSKate Stone ValueObjectSP ValueObjectPrinter::GenerateChild(ValueObject *synth_valobj,
650b9c1b51eSKate Stone size_t idx) {
6519ac0dac1SEnrico Granata if (m_options.m_pointer_as_array) {
652520a422bSEnrico Granata // if generating pointer-as-array children, use GetSyntheticArrayMember
6539ac0dac1SEnrico Granata return synth_valobj->GetSyntheticArrayMember(
6549ac0dac1SEnrico Granata PhysicalIndexForLogicalIndex(
6559ac0dac1SEnrico Granata m_options.m_pointer_as_array.m_base_element,
6569ac0dac1SEnrico Granata m_options.m_pointer_as_array.m_stride, idx),
6579ac0dac1SEnrico Granata true);
658b9c1b51eSKate Stone } else {
659520a422bSEnrico Granata // otherwise, do the usual thing
660520a422bSEnrico Granata return synth_valobj->GetChildAtIndex(idx, true);
661520a422bSEnrico Granata }
662520a422bSEnrico Granata }
663520a422bSEnrico Granata
PrintChildren(bool value_printed,bool summary_printed,const DumpValueObjectOptions::PointerDepth & curr_ptr_depth)664b9c1b51eSKate Stone void ValueObjectPrinter::PrintChildren(
665b9c1b51eSKate Stone bool value_printed, bool summary_printed,
666b9c1b51eSKate Stone const DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {
6674d93b8cdSEnrico Granata ValueObject *synth_m_valobj = GetValueObjectForChildrenGeneration();
6684d93b8cdSEnrico Granata
6694d93b8cdSEnrico Granata bool print_dotdotdot = false;
6704d93b8cdSEnrico Granata size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
671b9c1b51eSKate Stone if (num_children) {
6728cf44d96SEnrico Granata bool any_children_printed = false;
6734d93b8cdSEnrico Granata
674b9c1b51eSKate Stone for (size_t idx = 0; idx < num_children; ++idx) {
675b9c1b51eSKate Stone if (ValueObjectSP child_sp = GenerateChild(synth_m_valobj, idx)) {
676b9c1b51eSKate Stone if (!any_children_printed) {
6778cf44d96SEnrico Granata PrintChildrenPreamble();
6788cf44d96SEnrico Granata any_children_printed = true;
6798cf44d96SEnrico Granata }
6804d93b8cdSEnrico Granata PrintChild(child_sp, curr_ptr_depth);
6814d93b8cdSEnrico Granata }
6824d93b8cdSEnrico Granata }
6838cf44d96SEnrico Granata
6848cf44d96SEnrico Granata if (any_children_printed)
6858cf44d96SEnrico Granata PrintChildrenPostamble(print_dotdotdot);
686b9c1b51eSKate Stone else {
687b9c1b51eSKate Stone if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) {
6888cf44d96SEnrico Granata if (ShouldPrintValueObject())
6898cf44d96SEnrico Granata m_stream->PutCString(" {}\n");
6908cf44d96SEnrico Granata else
6918cf44d96SEnrico Granata m_stream->EOL();
692b9c1b51eSKate Stone } else
6938cf44d96SEnrico Granata m_stream->EOL();
6948cf44d96SEnrico Granata }
695b9c1b51eSKate Stone } else if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) {
6964d93b8cdSEnrico Granata // Aggregate, no children...
697b9c1b51eSKate Stone if (ShouldPrintValueObject()) {
698b9c1b51eSKate Stone // if it has a synthetic value, then don't print {}, the synthetic
699b9c1b51eSKate Stone // children are probably only being used to vend a value
700b9c1b51eSKate Stone if (m_valobj->DoesProvideSyntheticValue() ||
701b9c1b51eSKate Stone !ShouldExpandEmptyAggregates())
702d07cfd3aSEnrico Granata m_stream->PutCString("\n");
703d07cfd3aSEnrico Granata else
7044d93b8cdSEnrico Granata m_stream->PutCString(" {}\n");
7054d93b8cdSEnrico Granata }
706b9c1b51eSKate Stone } else {
7074d93b8cdSEnrico Granata if (ShouldPrintValueObject())
7084d93b8cdSEnrico Granata m_stream->EOL();
7094d93b8cdSEnrico Granata }
7104d93b8cdSEnrico Granata }
7114d93b8cdSEnrico Granata
PrintChildrenOneLiner(bool hide_names)712b9c1b51eSKate Stone bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) {
713d07cfd3aSEnrico Granata if (!GetMostSpecializedValue() || m_valobj == nullptr)
714a29cb0baSEnrico Granata return false;
715a29cb0baSEnrico Granata
716a29cb0baSEnrico Granata ValueObject *synth_m_valobj = GetValueObjectForChildrenGeneration();
717a29cb0baSEnrico Granata
718a29cb0baSEnrico Granata bool print_dotdotdot = false;
719a29cb0baSEnrico Granata size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
720a29cb0baSEnrico Granata
721b9c1b51eSKate Stone if (num_children) {
722a29cb0baSEnrico Granata m_stream->PutChar('(');
723a29cb0baSEnrico Granata
724b9c1b51eSKate Stone for (uint32_t idx = 0; idx < num_children; ++idx) {
725a29cb0baSEnrico Granata lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
726ddac7611SEnrico Granata if (child_sp)
727b9c1b51eSKate Stone child_sp = child_sp->GetQualifiedRepresentationIfAvailable(
728b9c1b51eSKate Stone m_options.m_use_dynamic, m_options.m_use_synthetic);
729b9c1b51eSKate Stone if (child_sp) {
730a29cb0baSEnrico Granata if (idx)
731a29cb0baSEnrico Granata m_stream->PutCString(", ");
732b9c1b51eSKate Stone if (!hide_names) {
733a29cb0baSEnrico Granata const char *name = child_sp.get()->GetName().AsCString();
734b9c1b51eSKate Stone if (name && *name) {
735a29cb0baSEnrico Granata m_stream->PutCString(name);
736a29cb0baSEnrico Granata m_stream->PutCString(" = ");
737a29cb0baSEnrico Granata }
738a29cb0baSEnrico Granata }
739b9c1b51eSKate Stone child_sp->DumpPrintableRepresentation(
740b9c1b51eSKate Stone *m_stream, ValueObject::eValueObjectRepresentationStyleSummary,
7417aafb6a1SEnrico Granata m_options.m_format,
74265d86e4fSEnrico Granata ValueObject::PrintableRepresentationSpecialCases::eDisable);
743a29cb0baSEnrico Granata }
744a29cb0baSEnrico Granata }
745a29cb0baSEnrico Granata
746a29cb0baSEnrico Granata if (print_dotdotdot)
747a29cb0baSEnrico Granata m_stream->PutCString(", ...)");
748a29cb0baSEnrico Granata else
749a29cb0baSEnrico Granata m_stream->PutChar(')');
750a29cb0baSEnrico Granata }
751a29cb0baSEnrico Granata return true;
752a29cb0baSEnrico Granata }
753a29cb0baSEnrico Granata
PrintChildrenIfNeeded(bool value_printed,bool summary_printed)754b9c1b51eSKate Stone void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
755b9c1b51eSKate Stone bool summary_printed) {
756dc333e63SJonas Devlieghere // This flag controls whether we tried to display a description for this
757dc333e63SJonas Devlieghere // object and failed if that happens, we want to display the children if any.
758b9c1b51eSKate Stone bool is_failed_description =
759b9c1b51eSKate Stone !PrintObjectDescriptionIfNeeded(value_printed, summary_printed);
7604d93b8cdSEnrico Granata
761dc333e63SJonas Devlieghere DumpValueObjectOptions::PointerDepth curr_ptr_depth = m_ptr_depth;
762dc333e63SJonas Devlieghere const bool print_children =
763b9c1b51eSKate Stone ShouldPrintChildren(is_failed_description, curr_ptr_depth);
764dc333e63SJonas Devlieghere const bool print_oneline =
765b9c1b51eSKate Stone (curr_ptr_depth.CanAllowExpansion() || m_options.m_show_types ||
766b9c1b51eSKate Stone !m_options.m_allow_oneliner_mode || m_options.m_flat_output ||
7679ac0dac1SEnrico Granata (m_options.m_pointer_as_array) || m_options.m_show_location)
768b9c1b51eSKate Stone ? false
769b9c1b51eSKate Stone : DataVisualization::ShouldPrintAsOneLiner(*m_valobj);
770dc333e63SJonas Devlieghere if (print_children && IsInstancePointer()) {
771dc333e63SJonas Devlieghere uint64_t instance_ptr_value = m_valobj->GetValueAsUnsigned(0);
772b9c1b51eSKate Stone if (m_printed_instance_pointers->count(instance_ptr_value)) {
773dc333e63SJonas Devlieghere // We already printed this instance-is-pointer thing, so don't expand it.
7748cf44d96SEnrico Granata m_stream->PutCString(" {...}\n");
7758cf44d96SEnrico Granata return;
776dc333e63SJonas Devlieghere } else {
777dc333e63SJonas Devlieghere // Remember this guy for future reference.
778dc333e63SJonas Devlieghere m_printed_instance_pointers->emplace(instance_ptr_value);
779dc333e63SJonas Devlieghere }
7808cf44d96SEnrico Granata }
7814d93b8cdSEnrico Granata
782b9c1b51eSKate Stone if (print_children) {
783b9c1b51eSKate Stone if (print_oneline) {
784a29cb0baSEnrico Granata m_stream->PutChar(' ');
785a29cb0baSEnrico Granata PrintChildrenOneLiner(false);
786a29cb0baSEnrico Granata m_stream->EOL();
787b9c1b51eSKate Stone } else
788c1b7c09aSEnrico Granata PrintChildren(value_printed, summary_printed, curr_ptr_depth);
789*2f9fc576SDave Lee } else if (HasReachedMaximumDepth() && IsAggregate() &&
790b9c1b51eSKate Stone ShouldPrintValueObject()) {
7914d93b8cdSEnrico Granata m_stream->PutCString("{...}\n");
792*2f9fc576SDave Lee // The maximum child depth has been reached. If `m_max_depth` is the default
793*2f9fc576SDave Lee // (i.e. the user has _not_ customized it), then lldb presents a warning to
794*2f9fc576SDave Lee // the user. The warning tells the user that the limit has been reached, but
795*2f9fc576SDave Lee // more importantly tells them how to expand the limit if desired.
796*2f9fc576SDave Lee if (m_options.m_max_depth_is_default)
797*2f9fc576SDave Lee m_valobj->GetTargetSP()
798*2f9fc576SDave Lee ->GetDebugger()
799*2f9fc576SDave Lee .GetCommandInterpreter()
800*2f9fc576SDave Lee .SetReachedMaximumDepth();
801b9c1b51eSKate Stone } else
802245b3caaSEnrico Granata m_stream->EOL();
8034d93b8cdSEnrico Granata }
804*2f9fc576SDave Lee
HasReachedMaximumDepth()805*2f9fc576SDave Lee bool ValueObjectPrinter::HasReachedMaximumDepth() {
806*2f9fc576SDave Lee return m_curr_depth >= m_options.m_max_depth;
807*2f9fc576SDave Lee }
808