diff options
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/API/SBValue.cpp | 4 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectExpression.cpp | 29 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectExpression.h | 1 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectFrame.cpp | 15 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectMemory.cpp | 7 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectTarget.cpp | 8 | ||||
-rw-r--r-- | lldb/source/Core/Debugger.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Core/ValueObject.cpp | 317 | ||||
-rw-r--r-- | lldb/source/DataFormatters/ValueObjectPrinter.cpp | 533 | ||||
-rw-r--r-- | lldb/source/Interpreter/CommandObject.cpp | 1 | ||||
-rw-r--r-- | lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp | 9 |
11 files changed, 592 insertions, 334 deletions
diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index f13b6722d99..c860876fd12 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -1394,9 +1394,7 @@ SBValue::GetDescription (SBStream &description) ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) - { - ValueObject::DumpValueObject (strm, value_sp.get()); - } + value_sp->Dump(strm); else strm.PutCString ("No value"); diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 7186b9a7cb4..8b04da600f4 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Value.h" #include "lldb/Core/InputReader.h" #include "lldb/Core/ValueObjectVariable.h" +#include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Expression/ClangExpressionVariable.h" #include "lldb/Expression/ClangUserExpression.h" #include "lldb/Expression/ClangFunction.h" @@ -49,6 +50,13 @@ CommandObjectExpression::CommandOptions::~CommandOptions () { } +static OptionEnumValueElement g_description_verbosity_type[] = +{ + { eLanguageRuntimeDescriptionDisplayVerbosityCompact, "compact", "Only show the description string"}, + { eLanguageRuntimeDescriptionDisplayVerbosityFull, "full", "Show the full output, including persistent variable's name and type"}, + { 0, NULL, NULL } +}; + OptionDefinition CommandObjectExpression::CommandOptions::g_option_table[] = { @@ -56,6 +64,7 @@ CommandObjectExpression::CommandOptions::g_option_table[] = { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"}, { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."}, { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."}, + { LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."}, }; @@ -127,6 +136,18 @@ CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &int error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg); break; } + + case 'v': + if (!option_arg) + { + m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull; + break; + } + m_verbosity = (LanguageRuntimeDescriptionDisplayVerbosity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error); + if (!error.Success()) + error.SetErrorStringWithFormat ("unrecognized value for description-verbosity '%s'", option_arg); + break; + default: error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); break; @@ -153,6 +174,7 @@ CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpret show_summary = true; try_all_threads = true; timeout = 0; + m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact; } const OptionDefinition* @@ -357,11 +379,10 @@ CommandObjectExpression::EvaluateExpression if (format != eFormatDefault) result_valobj_sp->SetFormat (format); - ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(true,format)); + DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format)); - ValueObject::DumpValueObject (*(output_stream), - result_valobj_sp.get(), // Variable object to dump - options); + result_valobj_sp->Dump(*output_stream,options); + if (result) result->SetStatus (eReturnStatusSuccessFinishResult); } diff --git a/lldb/source/Commands/CommandObjectExpression.h b/lldb/source/Commands/CommandObjectExpression.h index 3964f2d423e..a62a21287c2 100644 --- a/lldb/source/Commands/CommandObjectExpression.h +++ b/lldb/source/Commands/CommandObjectExpression.h @@ -57,6 +57,7 @@ public: bool show_summary; uint32_t timeout; bool try_all_threads; + LanguageRuntimeDescriptionDisplayVerbosity m_verbosity; }; CommandObjectExpression (CommandInterpreter &interpreter); diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp index 202d62e6009..2e852d0bb76 100644 --- a/lldb/source/Commands/CommandObjectFrame.cpp +++ b/lldb/source/Commands/CommandObjectFrame.cpp @@ -25,6 +25,7 @@ #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/DataFormatters/DataVisualization.h" +#include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Host/Host.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -400,7 +401,7 @@ protected: else if (!m_option_variable.summary_string.IsCurrentValueEmpty()) summary_format_sp.reset(new StringSummaryFormat(TypeSummaryImpl::Flags(),m_option_variable.summary_string.GetCurrentValue())); - ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(false,eFormatDefault,summary_format_sp)); + DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,eFormatDefault,summary_format_sp)); if (variable_list) { @@ -447,9 +448,7 @@ protected: if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) s.PutCString (": "); } - ValueObject::DumpValueObject (result.GetOutputStream(), - valobj_sp.get(), - options); + valobj_sp->Dump(result.GetOutputStream(),options); } } } @@ -493,9 +492,7 @@ protected: Stream &output_stream = result.GetOutputStream(); options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr : NULL); - ValueObject::DumpValueObject (output_stream, - valobj_sp.get(), - options); + valobj_sp->Dump(output_stream,options); } else { @@ -571,9 +568,7 @@ protected: options.SetFormat(format); options.SetRootValueObjectName(name_cstr); - ValueObject::DumpValueObject (result.GetOutputStream(), - valobj_sp.get(), - options); + valobj_sp->Dump(result.GetOutputStream(),options); } } } diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp index 7a0e204993e..d7e59fb3486 100644 --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -23,6 +23,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectMemory.h" +#include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -836,11 +837,9 @@ protected: if (format != eFormatDefault) valobj_sp->SetFormat (format); - ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(false,format)); + DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format)); - ValueObject::DumpValueObject (*output_stream, - valobj_sp.get(), - options); + valobj_sp->Dump(*output_stream,options); } else { diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 7f121ecc1c3..ef431e25c3d 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -26,6 +26,7 @@ #include "lldb/Core/State.h" #include "lldb/Core/Timer.h" #include "lldb/Core/ValueObjectVariable.h" +#include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Host/Symbols.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -719,7 +720,7 @@ public: void DumpValueObject (Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp, const char *root_name) { - ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions()); + DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions()); switch (var_sp->GetScope()) { @@ -761,10 +762,7 @@ public: options.SetRootValueObjectName(root_name); - ValueObject::DumpValueObject (s, - valobj_sp.get(), - options); - + valobj_sp->Dump(s,options); } diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 8a29934ff62..caeed72e2a7 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -1981,7 +1981,7 @@ FormatPromptRecurse ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); if (return_valobj_sp) { - ValueObject::DumpValueObject (s, return_valobj_sp.get()); + return_valobj_sp->Dump(s); var_success = true; } } diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 19d17af7d99..f07b5e375d1 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -34,6 +34,7 @@ #include "lldb/Core/ValueObjectSyntheticFilter.h" #include "lldb/DataFormatters/DataVisualization.h" +#include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Host/Endian.h" @@ -3422,329 +3423,39 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, } } -static void -DumpValueObject_Impl (Stream &s, - ValueObject *valobj, - const ValueObject::DumpValueObjectOptions& options, - uint32_t ptr_depth, - uint32_t curr_depth) -{ - if (valobj) - { - bool update_success = valobj->UpdateValueIfNeeded (true); - - const char *root_valobj_name = - options.m_root_valobj_name.empty() ? - valobj->GetName().AsCString() : - options.m_root_valobj_name.c_str(); - - if (update_success && options.m_use_dynamic != eNoDynamicValues) - { - ValueObject *dynamic_value = valobj->GetDynamicValue(options.m_use_dynamic).get(); - if (dynamic_value) - valobj = dynamic_value; - } - - ClangASTType clang_type = valobj->GetClangType(); - const Flags type_flags (clang_type.GetTypeInfo ()); - const char *err_cstr = NULL; - const bool has_children = type_flags.Test (ClangASTType::eTypeHasChildren); - const bool has_value = type_flags.Test (ClangASTType::eTypeHasValue); - - const bool print_valobj = options.m_flat_output == false || has_value; - - if (print_valobj) - { - if (options.m_show_location) - { - s.Printf("%s: ", valobj->GetLocationAsCString()); - } - - s.Indent(); - - bool show_type = true; - // if we are at the root-level and been asked to hide the root's type, then hide it - if (curr_depth == 0 && options.m_hide_root_type) - show_type = false; - else - // otherwise decide according to the usual rules (asked to show types - always at the root level) - show_type = options.m_show_types || (curr_depth == 0 && !options.m_flat_output); - - if (show_type) - { - // Some ValueObjects don't have types (like registers sets). Only print - // the type if there is one to print - ConstString qualified_type_name(valobj->GetQualifiedTypeName()); - if (qualified_type_name) - s.Printf("(%s) ", qualified_type_name.GetCString()); - } - - if (options.m_flat_output) - { - // If we are showing types, also qualify the C++ base classes - const bool qualify_cxx_base_classes = options.m_show_types; - if (!options.m_hide_name) - { - valobj->GetExpressionPath(s, qualify_cxx_base_classes); - s.PutCString(" ="); - } - } - else if (!options.m_hide_name) - { - const char *name_cstr = root_valobj_name ? root_valobj_name : valobj->GetName().AsCString(""); - s.Printf ("%s =", name_cstr); - } - - if (!options.m_scope_already_checked && !valobj->IsInScope()) - { - err_cstr = "out of scope"; - } - } - - std::string summary_str; - std::string value_str; - const char *val_cstr = NULL; - const char *sum_cstr = NULL; - TypeSummaryImpl* entry = options.m_summary_sp ? options.m_summary_sp.get() : valobj->GetSummaryFormat().get(); - - if (options.m_omit_summary_depth > 0) - entry = NULL; - - bool is_nil = valobj->IsObjCNil(); - - if (err_cstr == NULL) - { - if (options.m_format != eFormatDefault && options.m_format != valobj->GetFormat()) - { - valobj->GetValueAsCString(options.m_format, - value_str); - } - else - { - val_cstr = valobj->GetValueAsCString(); - if (val_cstr) - value_str = val_cstr; - } - err_cstr = valobj->GetError().AsCString(); - } - - if (err_cstr) - { - s.Printf (" <%s>\n", err_cstr); - } - else - { - const bool is_ref = type_flags.Test (ClangASTType::eTypeIsReference); - if (print_valobj) - { - if (is_nil) - sum_cstr = "nil"; - else if (options.m_omit_summary_depth == 0) - { - if (options.m_summary_sp) - { - valobj->GetSummaryAsCString(entry, summary_str); - sum_cstr = summary_str.c_str(); - } - else - sum_cstr = valobj->GetSummaryAsCString(); - } - - // Make sure we have a value and make sure the summary didn't - // specify that the value should not be printed - and do not print - // the value if this thing is nil - // (but show the value if the user passes a format explicitly) - if (!is_nil && !value_str.empty() && (entry == NULL || (entry->DoesPrintValue() || options.m_format != eFormatDefault) || sum_cstr == NULL) && !options.m_hide_value) - s.Printf(" %s", value_str.c_str()); - - if (sum_cstr) - s.Printf(" %s", sum_cstr); - - // let's avoid the overly verbose no description error for a nil thing - if (options.m_use_objc && !is_nil) - { - if (!options.m_hide_value || !options.m_hide_name) - s.Printf(" "); - const char *object_desc = valobj->GetObjectDescription(); - if (object_desc) - s.Printf("%s\n", object_desc); - else - s.Printf ("[no Objective-C description available]\n"); - return; - } - } - - if (curr_depth < options.m_max_depth) - { - // We will show children for all concrete types. We won't show - // pointer contents unless a pointer depth has been specified. - // We won't reference contents unless the reference is the - // root object (depth of zero). - bool print_children = true; - - // Use a new temporary pointer depth in case we override the - // current pointer depth below... - uint32_t curr_ptr_depth = ptr_depth; - - const bool is_ptr = type_flags.Test (ClangASTType::eTypeIsPointer); - if (is_ptr || is_ref) - { - // We have a pointer or reference whose value is an address. - // Make sure that address is not NULL - AddressType ptr_address_type; - if (valobj->GetPointerValue (&ptr_address_type) == 0) - print_children = false; - - else if (is_ref && curr_depth == 0) - { - // If this is the root object (depth is zero) that we are showing - // and it is a reference, and no pointer depth has been supplied - // print out what it references. Don't do this at deeper depths - // otherwise we can end up with infinite recursion... - curr_ptr_depth = 1; - } - - if (curr_ptr_depth == 0) - print_children = false; - } - - if (print_children && (!entry || entry->DoesPrintChildren() || !sum_cstr)) - { - ValueObjectSP synth_valobj_sp = valobj->GetSyntheticValue (options.m_use_synthetic); - ValueObject* synth_valobj = (synth_valobj_sp ? synth_valobj_sp.get() : valobj); - - size_t num_children = synth_valobj->GetNumChildren(); - bool print_dotdotdot = false; - if (num_children) - { - if (options.m_flat_output) - { - if (print_valobj) - s.EOL(); - } - else - { - if (print_valobj) - s.PutCString(is_ref ? ": {\n" : " {\n"); - s.IndentMore(); - } - - const size_t max_num_children = valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); - - if (num_children > max_num_children && !options.m_ignore_cap) - { - num_children = max_num_children; - print_dotdotdot = true; - } - - ValueObject::DumpValueObjectOptions child_options(options); - child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName(); - child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(options.m_hide_value) - .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0); - for (size_t idx=0; idx<num_children; ++idx) - { - ValueObjectSP child_sp(synth_valobj->GetChildAtIndex(idx, true)); - if (child_sp.get()) - { - DumpValueObject_Impl (s, - child_sp.get(), - child_options, - (is_ptr || is_ref) ? curr_ptr_depth - 1 : curr_ptr_depth, - curr_depth + 1); - } - } - - if (!options.m_flat_output) - { - if (print_dotdotdot) - { - ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); - Target *target = exe_ctx.GetTargetPtr(); - if (target) - target->GetDebugger().GetCommandInterpreter().ChildrenTruncated(); - s.Indent("...\n"); - } - s.IndentLess(); - s.Indent("}\n"); - } - } - else if (has_children) - { - // Aggregate, no children... - if (print_valobj) - s.PutCString(" {}\n"); - } - else - { - if (print_valobj) - s.EOL(); - } - - } - else - { - s.EOL(); - } - } - else - { - if (has_children && print_valobj) - { - s.PutCString("{...}\n"); - } - } - } - } -} - void -ValueObject::LogValueObject (Log *log, - ValueObject *valobj) +ValueObject::LogValueObject (Log *log) { - if (log && valobj) - return LogValueObject (log, valobj, DumpValueObjectOptions::DefaultOptions()); + if (log) + return LogValueObject (log, DumpValueObjectOptions::DefaultOptions()); } void -ValueObject::LogValueObject (Log *log, - ValueObject *valobj, - const DumpValueObjectOptions& options) +ValueObject::LogValueObject (Log *log, const DumpValueObjectOptions& options) { - if (log && valobj) + if (log) { StreamString s; - ValueObject::DumpValueObject (s, valobj, options); + Dump (s, options); if (s.GetSize()) log->PutCString(s.GetData()); } } void -ValueObject::DumpValueObject (Stream &s, - ValueObject *valobj) +ValueObject::Dump (Stream &s) { - if (!valobj) - return; - - DumpValueObject_Impl(s, - valobj, - DumpValueObjectOptions::DefaultOptions(), - 0, - 0); + ValueObjectPrinter printer(this,&s,DumpValueObjectOptions::DefaultOptions()); + printer.PrintValueObject(); } void -ValueObject::DumpValueObject (Stream &s, - ValueObject *valobj, - const DumpValueObjectOptions& options) +ValueObject::Dump (Stream &s, + const DumpValueObjectOptions& options) { - DumpValueObject_Impl(s, - valobj, - options, - options.m_max_ptr_depth, // max pointer depth allowed, we will go down from here - 0 // current object depth is 0 since we are just starting - ); + ValueObjectPrinter printer(this,&s,options); + printer.PrintValueObject(); } ValueObjectSP diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp new file mode 100644 index 00000000000..417b5822aab --- /dev/null +++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp @@ -0,0 +1,533 @@ +//===-- ValueObjectPrinter.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/DataFormatters/ValueObjectPrinter.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Debugger.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; + +ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, + Stream* s, + const DumpValueObjectOptions& options) : + m_orig_valobj(valobj), + m_valobj(nullptr), + m_stream(s), + options(options), + m_ptr_depth(options.m_max_ptr_depth), + m_curr_depth(0), + m_should_print(eLazyBoolCalculate), + m_is_nil(eLazyBoolCalculate), + m_is_ptr(eLazyBoolCalculate), + m_is_ref(eLazyBoolCalculate), + m_is_aggregate(eLazyBoolCalculate), + m_summary_formatter({nullptr,false}), + m_value(), + m_summary(), + m_error() +{ + assert (m_orig_valobj && "cannot print a NULL ValueObject"); + assert (m_stream && "cannot print to a NULL Stream"); +} + +ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, + Stream* s, + const DumpValueObjectOptions& options, + uint32_t ptr_depth, + uint32_t curr_depth) : + ValueObjectPrinter(valobj,s,options) +{ + m_ptr_depth = ptr_depth; + m_curr_depth = curr_depth; +} + +bool +ValueObjectPrinter::PrintValueObject () +{ + if (!GetDynamicValueIfNeeded () || m_valobj == nullptr) + return false; + + if (ShouldPrintValueObject()) + { + PrintLocationIfNeeded(); + m_stream->Indent(); + + bool show_type = PrintTypeIfNeeded(); + + PrintNameIfNeeded(show_type); + } + + bool value_printed = false; + bool summary_printed = false; + + bool val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed); + + if (val_summary_ok) + PrintChildrenIfNeeded (value_printed, summary_printed); + + m_stream->EOL(); + + return true; +} + +bool +ValueObjectPrinter::GetDynamicValueIfNeeded () +{ + bool update_success = m_orig_valobj->UpdateValueIfNeeded (true); + if (!update_success) + return false; + if (options.m_use_dynamic != eNoDynamicValues) + { + ValueObject *dynamic_value = m_orig_valobj->GetDynamicValue(options.m_use_dynamic).get(); + if (dynamic_value) + m_valobj = dynamic_value; + else + m_valobj = m_orig_valobj; + } + else + m_valobj = m_orig_valobj; + m_clang_type = m_valobj->GetClangType(); + m_type_flags = m_clang_type.GetTypeInfo (); + return true; +} + +const char* +ValueObjectPrinter::GetDescriptionForDisplay () +{ + const char* str = m_valobj->GetObjectDescription(); + if (!str) + str = m_valobj->GetSummaryAsCString(); + if (!str) + str = m_valobj->GetValueAsCString(); + return str; +} + +const char* +ValueObjectPrinter::GetRootNameForDisplay (const char* if_fail) +{ + const char *root_valobj_name = options.m_root_valobj_name.empty() ? + m_valobj->GetName().AsCString() : + options.m_root_valobj_name.c_str(); + return root_valobj_name ? root_valobj_name : if_fail; +} + +bool +ValueObjectPrinter::ShouldPrintValueObject () +{ + if (m_should_print == eLazyBoolCalculate) + m_should_print = (options.m_flat_output == false || m_type_flags.Test (ClangASTType::eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo; + return m_should_print == eLazyBoolYes; +} + +bool +ValueObjectPrinter::IsNil () +{ + if (m_is_nil == eLazyBoolCalculate) + m_is_nil = m_valobj->IsObjCNil() ? eLazyBoolYes : eLazyBoolNo; + return m_is_nil == eLazyBoolYes; +} + +bool +ValueObjectPrinter::IsPtr () +{ + if (m_is_ptr == eLazyBoolCalculate) + m_is_ptr = m_type_flags.Test (ClangASTType::eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo; + return m_is_ptr == eLazyBoolYes; +} + +bool +ValueObjectPrinter::IsRef () +{ + if (m_is_ref == eLazyBoolCalculate) + m_is_ref = m_type_flags.Test (ClangASTType::eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo; + return m_is_ref == eLazyBoolYes; +} + +bool +ValueObjectPrinter::IsAggregate () +{ + if (m_is_aggregate == eLazyBoolCalculate) + m_is_aggregate = m_type_flags.Test (ClangASTType::eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo; + return m_is_aggregate == eLazyBoolYes; +} + +bool +ValueObjectPrinter::PrintLocationIfNeeded () +{ + if (options.m_show_location) + { + m_stream->Printf("%s: ", m_valobj->GetLocationAsCString()); + return true; + } + return false; +} + +bool +ValueObjectPrinter::PrintTypeIfNeeded () +{ + bool show_type = true; + // if we are at the root-level and been asked to hide the root's type, then hide it + if (m_curr_depth == 0 && options.m_hide_root_type) + show_type = false; + else + // otherwise decide according to the usual rules (asked to show types - always at the root level) + show_type = options.m_show_types || (m_curr_depth == 0 && !options.m_flat_output); + + if (show_type) + { + // Some ValueObjects don't have types (like registers sets). Only print + // the type if there is one to print + ConstString qualified_type_name(m_valobj->GetQualifiedTypeName()); + if (qualified_type_name) + m_stream->Printf("(%s) ", qualified_type_name.GetCString()); + else + show_type = false; + } + return show_type; +} + +bool +ValueObjectPrinter::PrintNameIfNeeded (bool show_type) +{ + if (options.m_flat_output) + { + // If we are showing types, also qualify the C++ base classes + const bool qualify_cxx_base_classes = show_type; + if (!options.m_hide_name) + { + m_valobj->GetExpressionPath(*m_stream, qualify_cxx_base_classes); + m_stream->PutCString(" ="); + return true; + } + } + else if (!options.m_hide_name) + { + const char *name_cstr = GetRootNameForDisplay(""); + m_stream->Printf ("%s =", name_cstr); + return true; + } + return false; +} + +bool +ValueObjectPrinter::CheckScopeIfNeeded () +{ + if (options.m_scope_already_checked) + return true; + return m_valobj->IsInScope(); +} + +TypeSummaryImpl* +ValueObjectPrinter::GetSummaryFormatter () +{ + if (m_summary_formatter.second == false) + { + TypeSummaryImpl* entry = options.m_summary_sp ? options.m_summary_sp.get() : m_valobj->GetSummaryFormat().get(); + + if (options.m_omit_summary_depth > 0) + entry = NULL; + m_summary_formatter.first = entry; + m_summary_formatter.second = true; + } + return m_summary_formatter.first; +} + +void +ValueObjectPrinter::GetValueSummaryError (std::string& value, + std::string& summary, + std::string& error) +{ + if (options.m_format != eFormatDefault && options.m_format != m_valobj->GetFormat()) + { + m_valobj->GetValueAsCString(options.m_format, + value); + } + else + { + const char* val_cstr = m_valobj->GetValueAsCString(); + if (val_cstr) + value.assign(val_cstr); + } + const char* err_cstr = m_valobj->GetError().AsCString(); + if (err_cstr) + error.assign(err_cstr); + + if (ShouldPrintValueObject()) + { + if (IsNil()) + summary.assign("nil"); + else if (options.m_omit_summary_depth == 0) + { + TypeSummaryImpl* entry = GetSummaryFormatter(); + if (entry) + m_valobj->GetSummaryAsCString(entry, summary); + else + { + const char* sum_cstr = m_valobj->GetSummaryAsCString(); + if (sum_cstr) + summary.assign(sum_cstr); + } + } + } +} + +bool +ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed, + bool& summary_printed) +{ + bool error_printed = false; + if (ShouldPrintValueObject()) + { + if (!CheckScopeIfNeeded()) + m_error.assign("out of scope"); + if (m_error.empty()) + { + GetValueSummaryError(m_value, m_summary, m_error); + } + if (m_error.size()) + { + error_printed = true; + m_stream->Printf (" <%s>\n", m_error.c_str()); + } + else + { + // Make sure we have a value and make sure the summary didn't + // specify that the value should not be printed - and do not print + // the value if this thing is nil + // (but show the value if the user passes a format explicitly) + TypeSummaryImpl* entry = GetSummaryFormatter(); + if (!IsNil() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue() || options.m_format != eFormatDefault) || m_summary.empty()) && !options.m_hide_value) + { + m_stream->Printf(" %s", m_value.c_str()); + value_printed = true; + } + + if (m_summary.size()) + { + m_stream->Printf(" %s", m_summary.c_str()); + summary_printed = true; + } + } + } + return !error_printed; +} + +bool +ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed, + bool summary_printed) +{ + if (ShouldPrintValueObject()) + { + // let's avoid the overly verbose no description error for a nil thing + if (options.m_use_objc && !IsNil()) + { + if (!options.m_hide_value || !options.m_hide_name) + m_stream->Printf(" "); + const char *object_desc = nullptr; + if (value_printed || summary_printed) + object_desc = m_valobj->GetObjectDescription(); + else + object_desc = GetDescriptionForDisplay(); + if (object_desc && *object_desc) + { + m_stream->Printf("%s\n", object_desc); + return true; + } + else if (value_printed == false && summary_printed == false) + return true; + else + return false; + } + } + return true; +} + +bool +ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description, + uint32_t& curr_ptr_depth) +{ + const bool is_ref = IsRef (); + const bool is_ptr = IsPtr (); + + if (is_failed_description || m_curr_depth < options.m_max_depth) + { + // We will show children for all concrete types. We won't show + // pointer contents unless a pointer depth has been specified. + // We won't reference contents unless the reference is the + // root object (depth of zero). + + // Use a new temporary pointer depth in case we override the + // current pointer depth below... + uint32_t curr_ptr_depth = m_ptr_depth; + + if (is_ptr || is_ref) + { + // We have a pointer or reference whose value is an address. + // Make sure that address is not NULL + AddressType ptr_address_type; + if (m_valobj->GetPointerValue (&ptr_address_type) == 0) + return false; + + else if (is_ref && m_curr_depth == 0) + { + // If this is the root object (depth is zero) that we are showing + // and it is a reference, and no pointer depth has been supplied + // print out what it references. Don't do this at deeper depths + // otherwise we can end up with infinite recursion... + curr_ptr_depth = 1; + } + + if (curr_ptr_depth == 0) + return false; + } + + TypeSummaryImpl* entry = GetSummaryFormatter(); + + return (!entry || entry->DoesPrintChildren() || m_summary.empty()); + } + return false; +} + +ValueObject* +ValueObjectPrinter::GetValueObjectForChildrenGeneration () +{ + ValueObjectSP synth_valobj_sp = m_valobj->GetSyntheticValue (options.m_use_synthetic); + return (synth_valobj_sp ? synth_valobj_sp.get() : m_valobj); +} + +void +ValueObjectPrinter::PrintChildrenPreamble () +{ + if (options.m_flat_output) + { + if (ShouldPrintValueObject()) + m_stream->EOL(); + } + else + { + if (ShouldPrintValueObject()) + m_stream->PutCString(IsRef () ? ": {\n" : " {\n"); + m_stream->IndentMore(); + } +} + +void +ValueObjectPrinter::PrintChild (ValueObjectSP child_sp, + uint32_t curr_ptr_depth) +{ + DumpValueObjectOptions child_options(options); + child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName(); + child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(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 - 1 : curr_ptr_depth, + m_curr_depth + 1); + child_printer.PrintValueObject(); + } + +} + +uint32_t +ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot) +{ + ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); + + size_t num_children = synth_m_valobj->GetNumChildren(); + print_dotdotdot = false; + if (num_children) + { + const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); + + if (num_children > max_num_children && !options.m_ignore_cap) + { + print_dotdotdot = true; + return max_num_children; + } + } + return num_children; +} + +void +ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot) +{ + if (!options.m_flat_output) + { + if (print_dotdotdot) + { + m_valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().ChildrenTruncated(); + m_stream->Indent("...\n"); + } + m_stream->IndentLess(); + m_stream->Indent("}\n"); + } +} + +void +ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth) +{ + ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); + + bool print_dotdotdot = false; + size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); + if (num_children) + { + PrintChildrenPreamble (); + + for (size_t idx=0; idx<num_children; ++idx) + { + ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); + PrintChild (child_sp, curr_ptr_depth); + } + + PrintChildrenPostamble (print_dotdotdot); + } + else if (IsAggregate()) + { + // Aggregate, no children... + if (ShouldPrintValueObject()) + m_stream->PutCString(" {}\n"); + } + else + { + if (ShouldPrintValueObject()) + m_stream->EOL(); + } +} + +void +ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed, + bool summary_printed) +{ + // this flag controls whether we tried to display a description for this object and failed + // if that happens, we want to display the children, if any + bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed); + + uint32_t curr_ptr_depth = m_ptr_depth; + bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth); + + if (print_children) + { + PrintChildren (curr_ptr_depth); + } + else if (m_curr_depth >= options.m_max_depth && IsAggregate() && ShouldPrintValueObject()) + { + m_stream->PutCString("{...}\n"); + } +} diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp index 6ab4af167b6..c71ca28b033 100644 --- a/lldb/source/Interpreter/CommandObject.cpp +++ b/lldb/source/Interpreter/CommandObject.cpp @@ -1098,6 +1098,7 @@ CommandObject::g_arguments_data[] = { eArgTypeCount, "count", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." }, { eArgTypeDirectoryName, "directory", CommandCompletions::eDiskDirectoryCompletion, { NULL, false }, "A directory name." }, { eArgTypeDisassemblyFlavor, "disassembly-flavor", CommandCompletions::eNoCompletion, { NULL, false }, "A disassembly flavor recognized by your disassembly plugin. Currently the only valid options are \"att\" and \"intel\" for Intel targets" }, + { eArgTypeDescriptionVerbosity, "description-verbosity", CommandCompletions::eNoCompletion, { NULL, false }, "How verbose the output of 'po' should be." }, { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, { eArgTypeExpressionPath, "expr-path", CommandCompletions::eNoCompletion, { ExprPathHelpTextCallback, true }, NULL }, diff --git a/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp index 0129d3ed3f8..c79f49dc1d9 100644 --- a/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp +++ b/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp @@ -15,6 +15,7 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Target/Target.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Utility/Utils.h" @@ -147,12 +148,12 @@ OptionGroupValueObjectDisplay::OptionParsingStarting (CommandInterpreter &interp } } -ValueObject::DumpValueObjectOptions -OptionGroupValueObjectDisplay::GetAsDumpOptions (bool objc_is_compact, +DumpValueObjectOptions +OptionGroupValueObjectDisplay::GetAsDumpOptions (LanguageRuntimeDescriptionDisplayVerbosity lang_descr_verbosity, lldb::Format format, lldb::TypeSummaryImplSP summary_sp) { - ValueObject::DumpValueObjectOptions options; + DumpValueObjectOptions options; options.SetMaximumPointerDepth(ptr_depth); if (use_objc) options.SetShowSummary(false); @@ -169,7 +170,7 @@ OptionGroupValueObjectDisplay::GetAsDumpOptions (bool objc_is_compact, .SetFormat(format) .SetSummary(summary_sp); - if (objc_is_compact) + if (lang_descr_verbosity == eLanguageRuntimeDescriptionDisplayVerbosityCompact) options.SetHideRootType(use_objc) .SetHideName(use_objc) .SetHideValue(use_objc); |