summaryrefslogtreecommitdiffstats
path: root/lldb/source/DataFormatters/ValueObjectPrinter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/DataFormatters/ValueObjectPrinter.cpp')
-rw-r--r--lldb/source/DataFormatters/ValueObjectPrinter.cpp143
1 files changed, 119 insertions, 24 deletions
diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
index ec7862eb8a1..4bc33fdaa91 100644
--- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp
+++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
@@ -29,12 +29,12 @@ ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
if (valobj)
{
DumpValueObjectOptions options(*valobj);
- Init (valobj,s,options,m_options.m_max_ptr_depth,0);
+ Init (valobj,s,options,m_options.m_max_ptr_depth,0, nullptr);
}
else
{
DumpValueObjectOptions options;
- Init (valobj,s,options,m_options.m_max_ptr_depth,0);
+ Init (valobj,s,options,m_options.m_max_ptr_depth,0, nullptr);
}
}
@@ -42,16 +42,17 @@ ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
Stream* s,
const DumpValueObjectOptions& options)
{
- Init(valobj,s,options,m_options.m_max_ptr_depth,0);
+ Init(valobj,s,options,m_options.m_max_ptr_depth,0, nullptr);
}
ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
Stream* s,
const DumpValueObjectOptions& options,
const DumpValueObjectOptions::PointerDepth& ptr_depth,
- uint32_t curr_depth)
+ uint32_t curr_depth,
+ InstancePointersSetSP printed_instance_pointers)
{
- Init(valobj,s,options,ptr_depth,curr_depth);
+ Init(valobj,s,options,ptr_depth,curr_depth, printed_instance_pointers);
}
void
@@ -59,7 +60,8 @@ ValueObjectPrinter::Init (ValueObject* valobj,
Stream* s,
const DumpValueObjectOptions& options,
const DumpValueObjectOptions::PointerDepth& ptr_depth,
- uint32_t curr_depth)
+ uint32_t curr_depth,
+ InstancePointersSetSP printed_instance_pointers)
{
m_orig_valobj = valobj;
m_valobj = nullptr;
@@ -74,10 +76,13 @@ ValueObjectPrinter::Init (ValueObject* valobj,
m_is_ptr = eLazyBoolCalculate;
m_is_ref = eLazyBoolCalculate;
m_is_aggregate = eLazyBoolCalculate;
+ m_is_instance_ptr = eLazyBoolCalculate;
m_summary_formatter = {nullptr,false};
m_value.assign("");
m_summary.assign("");
m_error.assign("");
+ m_val_summary_ok = false;
+ m_printed_instance_pointers = printed_instance_pointers ? printed_instance_pointers : InstancePointersSetSP(new InstancePointersSet());
}
bool
@@ -95,13 +100,13 @@ ValueObjectPrinter::PrintValueObject ()
PrintDecl();
}
-
+
bool value_printed = false;
bool summary_printed = false;
- bool val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed);
-
- if (val_summary_ok)
+ m_val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed);
+
+ if (m_val_summary_ok)
PrintChildrenIfNeeded (value_printed, summary_printed);
else
m_stream->EOL();
@@ -189,8 +194,8 @@ const char*
ValueObjectPrinter::GetRootNameForDisplay (const char* if_fail)
{
const char *root_valobj_name = m_options.m_root_valobj_name.empty() ?
- m_valobj->GetName().AsCString() :
- m_options.m_root_valobj_name.c_str();
+ m_valobj->GetName().AsCString() :
+ m_options.m_root_valobj_name.c_str();
return root_valobj_name ? root_valobj_name : if_fail;
}
@@ -235,6 +240,17 @@ ValueObjectPrinter::IsAggregate ()
}
bool
+ValueObjectPrinter::IsInstancePointer ()
+{
+ // you need to do this check on the value's clang type
+ if (m_is_instance_ptr == eLazyBoolCalculate)
+ m_is_instance_ptr = (m_valobj->GetValue().GetCompilerType().GetTypeInfo() & eTypeInstanceIsPointer) != 0 ? eLazyBoolYes : eLazyBoolNo;
+ if ((eLazyBoolYes == m_is_instance_ptr) && m_valobj->IsBaseClass())
+ m_is_instance_ptr = eLazyBoolNo;
+ return m_is_instance_ptr == eLazyBoolYes;
+}
+
+bool
ValueObjectPrinter::PrintLocationIfNeeded ()
{
if (m_options.m_show_location)
@@ -361,7 +377,7 @@ ValueObjectPrinter::CheckScopeIfNeeded ()
}
TypeSummaryImpl*
-ValueObjectPrinter::GetSummaryFormatter ()
+ValueObjectPrinter::GetSummaryFormatter (bool null_if_omitted)
{
if (m_summary_formatter.second == false)
{
@@ -372,6 +388,8 @@ ValueObjectPrinter::GetSummaryFormatter ()
m_summary_formatter.first = entry;
m_summary_formatter.second = true;
}
+ if (m_options.m_omit_summary_depth > 0 && null_if_omitted)
+ return nullptr;
return m_summary_formatter.first;
}
@@ -379,7 +397,7 @@ static bool
IsPointerValue (const CompilerType &type)
{
Flags type_flags(type.GetTypeInfo());
- if (type_flags.AnySet(eTypeIsPointer))
+ if (type_flags.AnySet(eTypeInstanceIsPointer | eTypeIsPointer))
return type_flags.AllClear(eTypeIsBuiltIn);
return false;
}
@@ -438,6 +456,16 @@ ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed,
}
if (m_error.size())
{
+ // we need to support scenarios in which it is actually fine for a value to have no type
+ // but - on the other hand - if we get an error *AND* have no type, we try to get out
+ // gracefully, since most often that combination means "could not resolve a type"
+ // and the default failure mode is quite ugly
+ if (!m_compiler_type.IsValid())
+ {
+ m_stream->Printf(" <could not resolve type>");
+ return false;
+ }
+
error_printed = true;
m_stream->Printf (" <%s>\n", m_error.c_str());
}
@@ -543,9 +571,12 @@ ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description,
{
const bool is_ref = IsRef ();
const bool is_ptr = IsPtr ();
-
+
TypeSummaryImpl* entry = GetSummaryFormatter();
-
+
+ if (m_options.m_use_objc)
+ return false;
+
if (is_failed_description || m_curr_depth < m_options.m_max_depth)
{
// We will show children for all concrete types. We won't show
@@ -588,10 +619,10 @@ bool
ValueObjectPrinter::ShouldExpandEmptyAggregates ()
{
TypeSummaryImpl* entry = GetSummaryFormatter();
-
+
if (!entry)
return true;
-
+
return entry->DoesPrintEmptyAggregates();
}
@@ -625,13 +656,15 @@ ValueObjectPrinter::PrintChild (ValueObjectSP child_sp,
child_options.SetFormat(m_options.m_format).SetSummary().SetRootValueObjectName();
child_options.SetScopeChecked(true).SetHideName(m_options.m_hide_name).SetHideValue(m_options.m_hide_value)
.SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0);
+
if (child_sp.get())
{
ValueObjectPrinter child_printer(child_sp.get(),
m_stream,
child_options,
(IsPtr() || IsRef()) ? --curr_ptr_depth : curr_ptr_depth,
- m_curr_depth + 1);
+ m_curr_depth + 1,
+ m_printed_instance_pointers);
child_printer.PrintValueObject();
}
}
@@ -671,6 +704,30 @@ ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot)
}
}
+bool
+ValueObjectPrinter::ShouldPrintEmptyBrackets (bool value_printed,
+ bool summary_printed)
+{
+ ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
+
+ if (!IsAggregate())
+ return false;
+
+ if (m_options.m_reveal_empty_aggregates == false)
+ {
+ if (value_printed || summary_printed)
+ return false;
+ }
+
+ if (synth_m_valobj->MightHaveChildren())
+ return true;
+
+ if (m_val_summary_ok)
+ return false;
+
+ return true;
+}
+
void
ValueObjectPrinter::PrintChildren (bool value_printed,
bool summary_printed,
@@ -682,17 +739,38 @@ ValueObjectPrinter::PrintChildren (bool value_printed,
size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
if (num_children)
{
- PrintChildrenPreamble ();
+ bool any_children_printed = false;
for (size_t idx=0; idx<num_children; ++idx)
{
ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
- PrintChild (child_sp, curr_ptr_depth);
+ if (child_sp)
+ {
+ if (!any_children_printed)
+ {
+ PrintChildrenPreamble ();
+ any_children_printed = true;
+ }
+ PrintChild (child_sp, curr_ptr_depth);
+ }
}
- PrintChildrenPostamble (print_dotdotdot);
+ if (any_children_printed)
+ PrintChildrenPostamble (print_dotdotdot);
+ else
+ {
+ if (ShouldPrintEmptyBrackets(value_printed, summary_printed))
+ {
+ if (ShouldPrintValueObject())
+ m_stream->PutCString(" {}\n");
+ else
+ m_stream->EOL();
+ }
+ else
+ m_stream->EOL();
+ }
}
- else if (IsAggregate())
+ else if (ShouldPrintEmptyBrackets(value_printed, summary_printed))
{
// Aggregate, no children...
if (ShouldPrintValueObject())
@@ -774,6 +852,23 @@ ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed,
!m_options.m_allow_oneliner_mode ||
m_options.m_flat_output ||
m_options.m_show_location) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj);
+ bool is_instance_ptr = IsInstancePointer();
+ uint64_t instance_ptr_value = LLDB_INVALID_ADDRESS;
+
+ if (print_children && is_instance_ptr)
+ {
+ instance_ptr_value = m_valobj->GetValueAsUnsigned(0);
+ if (m_printed_instance_pointers->count(instance_ptr_value))
+ {
+ // we already printed this instance-is-pointer thing, so don't expand it
+ m_stream->PutCString(" {...}\n");
+
+ // we're done here - get out fast
+ return;
+ }
+ else
+ m_printed_instance_pointers->emplace(instance_ptr_value); // remember this guy for future reference
+ }
if (print_children)
{
@@ -788,7 +883,7 @@ ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed,
}
else if (m_curr_depth >= m_options.m_max_depth && IsAggregate() && ShouldPrintValueObject())
{
- m_stream->PutCString("{...}\n");
+ m_stream->PutCString("{...}\n");
}
else
m_stream->EOL();
OpenPOWER on IntegriCloud