diff options
Diffstat (limited to 'lldb/source')
5 files changed, 82 insertions, 13 deletions
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 25a88449c52..431b3d4ff88 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -282,6 +282,18 @@ CommandObjectExpression::GetOptions () return &m_option_group; } +static lldb_private::Error +CanBeUsedForElementCountPrinting (ValueObject& valobj) +{ + CompilerType type(valobj.GetCompilerType()); + CompilerType pointee; + if (!type.IsPointerType(&pointee)) + return Error("as it does not refer to a pointer"); + if (pointee.IsVoidType()) + return Error("as it refers to a pointer to void"); + return Error(); +} + bool CommandObjectExpression::EvaluateExpression(const char *expr, Stream *output_stream, @@ -356,6 +368,17 @@ CommandObjectExpression::EvaluateExpression(const char *expr, if (format != eFormatDefault) result_valobj_sp->SetFormat (format); + if (m_varobj_options.elem_count > 0) + { + Error error(CanBeUsedForElementCountPrinting(*result_valobj_sp)); + if (error.Fail()) + { + result->AppendErrorWithFormat("expression cannot be used with --element-count %s\n", error.AsCString("")); + result->SetStatus(eReturnStatusFailed); + return false; + } + } + DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format)); options.SetVariableFormatDisplayLanguage(result_valobj_sp->GetPreferredDisplayLanguage()); diff --git a/lldb/source/DataFormatters/DumpValueObjectOptions.cpp b/lldb/source/DataFormatters/DumpValueObjectOptions.cpp index f3de1257bb8..e1f5320feee 100644 --- a/lldb/source/DataFormatters/DumpValueObjectOptions.cpp +++ b/lldb/source/DataFormatters/DumpValueObjectOptions.cpp @@ -242,4 +242,10 @@ DumpValueObjectOptions::SetRevealEmptyAggregates (bool reveal) m_reveal_empty_aggregates = reveal; return *this; } - + +DumpValueObjectOptions& +DumpValueObjectOptions::SetElementCount (uint32_t element_count) +{ + m_element_count = element_count; + return *this; +} diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp index 04c29128354..167afca7fbb 100644 --- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp +++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp @@ -416,11 +416,12 @@ ValueObjectPrinter::GetValueSummaryError (std::string& value, std::string& summary, std::string& error) { - if (m_options.m_format != eFormatDefault && m_options.m_format != m_valobj->GetFormat()) - { - m_valobj->GetValueAsCString(m_options.m_format, - value); - } + lldb::Format format = m_options.m_format; + // if I am printing synthetized elements, apply the format to those elements only + if (m_options.m_element_count > 0) + m_valobj->GetValueAsCString(lldb::eFormatDefault, value); + else if (format != eFormatDefault && format != m_valobj->GetFormat()) + m_valobj->GetValueAsCString(format, value); else { const char* val_cstr = m_valobj->GetValueAsCString(); @@ -514,7 +515,7 @@ ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed, if (ShouldPrintValueObject()) { // let's avoid the overly verbose no description error for a nil thing - if (m_options.m_use_objc && !IsNil() && !IsUninitialized()) + if (m_options.m_use_objc && !IsNil() && !IsUninitialized() && (m_options.m_element_count == 0)) { if (!m_options.m_hide_value || !m_options.m_hide_name) m_stream->Printf(" "); @@ -587,6 +588,11 @@ ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description, if (is_uninit) return false; + // if the user has specified an element count, always print children + // as it is explicit user demand being honored + if (m_options.m_element_count > 0) + return true; + TypeSummaryImpl* entry = GetSummaryFormatter(); if (m_options.m_use_objc) @@ -667,18 +673,22 @@ void ValueObjectPrinter::PrintChild (ValueObjectSP child_sp, const DumpValueObjectOptions::PointerDepth& curr_ptr_depth) { + const uint32_t consumed_depth = (m_options.m_element_count == 0) ? 1 : 0; + const bool does_consume_ptr_depth = ((IsPtr() && m_options.m_element_count == 0) || IsRef()); + DumpValueObjectOptions child_options(m_options); 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); + .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - consumed_depth : 0) + .SetElementCount(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, + does_consume_ptr_depth ? --curr_ptr_depth : curr_ptr_depth, + m_curr_depth + consumed_depth, m_printed_instance_pointers); child_printer.PrintValueObject(); } @@ -689,6 +699,9 @@ ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot) { ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); + if (m_options.m_element_count > 0) + return m_options.m_element_count; + size_t num_children = synth_m_valobj->GetNumChildren(); print_dotdotdot = false; if (num_children) @@ -743,6 +756,21 @@ ValueObjectPrinter::ShouldPrintEmptyBrackets (bool value_printed, return true; } +ValueObjectSP +ValueObjectPrinter::GenerateChild (ValueObject* synth_valobj, size_t idx) +{ + if (m_options.m_element_count > 0) + { + // if generating pointer-as-array children, use GetSyntheticArrayMember + return synth_valobj->GetSyntheticArrayMember(idx, true); + } + else + { + // otherwise, do the usual thing + return synth_valobj->GetChildAtIndex(idx, true); + } +} + void ValueObjectPrinter::PrintChildren (bool value_printed, bool summary_printed, @@ -758,8 +786,7 @@ ValueObjectPrinter::PrintChildren (bool value_printed, for (size_t idx=0; idx<num_children; ++idx) { - ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); - if (child_sp) + if (ValueObjectSP child_sp = GenerateChild(synth_m_valobj, idx)) { if (!any_children_printed) { @@ -866,6 +893,7 @@ ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed, m_options.m_show_types || !m_options.m_allow_oneliner_mode || m_options.m_flat_output || + (m_options.m_element_count > 0) || m_options.m_show_location) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj); bool is_instance_ptr = IsInstancePointer(); uint64_t instance_ptr_value = LLDB_INVALID_ADDRESS; diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index b28c44a5272..bf6cded4e92 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -348,6 +348,8 @@ CommandInterpreter::Initialize () po->SetHelp("Evaluate an expression in the current program context, using user defined variables and variables currently in scope, and display the result of evaluation in a language-specific manner."); po->SetHelpLong(""); } + AddAlias("parray", cmd_obj_sp, "--element-count %1 --")->SetHelpLong(""); + AddAlias("poarray", cmd_obj_sp, "--object-description --element-count %1 --")->SetHelpLong(""); } cmd_obj_sp = GetCommandSPExact ("process kill", false); diff --git a/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp index bbd966859c3..c30a978d957 100644 --- a/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp +++ b/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp @@ -44,7 +44,8 @@ g_option_table[] = { LLDB_OPT_SET_1, false, "no-summary-depth", 'Y', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the depth at which omitting summary information stops (default is 1)."}, { LLDB_OPT_SET_1, false, "raw-output", 'R', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use formatting options."}, { LLDB_OPT_SET_1, false, "show-all-children", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Ignore the upper bound on the number of children to show."}, - { LLDB_OPT_SET_1, false, "validate", 'V', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Show results of type validators."}, + { LLDB_OPT_SET_1, false, "validate", 'V', OptionParser::eRequiredArgument, nullptr, nullptr,0, eArgTypeBoolean, "Show results of type validators."}, + { LLDB_OPT_SET_1, false, "element-count", 'Z', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Treat the result of the expression as if its type is an array of this many values."}, { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } }; @@ -92,6 +93,12 @@ OptionGroupValueObjectDisplay::SetOptionValue (CommandInterpreter &interpreter, if (!success) error.SetErrorStringWithFormat("invalid max depth '%s'", option_arg); break; + + case 'Z': + elem_count = StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid element count '%s'", option_arg); + break; case 'P': ptr_depth = StringConvert::ToUInt32 (option_arg, 0, 0, &success); @@ -141,6 +148,7 @@ OptionGroupValueObjectDisplay::OptionParsingStarting (CommandInterpreter &interp use_objc = false; max_depth = UINT32_MAX; ptr_depth = 0; + elem_count = 0; use_synth = true; be_raw = false; ignore_cap = false; @@ -187,6 +195,8 @@ OptionGroupValueObjectDisplay::GetAsDumpOptions (LanguageRuntimeDescriptionDispl options.SetRawDisplay(); options.SetRunValidator(run_validator); + + options.SetElementCount(elem_count); return options; } |