1414#include " lldb/Target/Target.h"
1515#include " lldb/Utility/Stream.h"
1616#include " lldb/ValueObject/ValueObject.h"
17+ #include " llvm/Support/Error.h"
1718#include " llvm/Support/MathExtras.h"
1819#include < cstdint>
20+ #include < optional>
1921
2022using namespace lldb ;
2123using namespace lldb_private ;
@@ -69,6 +71,18 @@ void ValueObjectPrinter::Init(
6971 SetupMostSpecializedValue ();
7072}
7173
74+ static const char *maybeNewline (const std::string &s) {
75+ // If the string already ends with a \n don't add another one.
76+ if (s.empty () || s.back () != ' \n ' )
77+ return " \n " ;
78+ return " " ;
79+ }
80+
81+ bool ValueObjectPrinter::ShouldPrintObjectDescription () {
82+ return ShouldPrintValueObject () && m_options.m_use_object_desc && !IsNil () &&
83+ !IsUninitialized () && !m_options.m_pointer_as_array ;
84+ }
85+
7286llvm::Error ValueObjectPrinter::PrintValueObject () {
7387 // If the incoming ValueObject is in an error state, the best we're going to
7488 // get out of it is its type. But if we don't even have that, just print
@@ -77,6 +91,25 @@ llvm::Error ValueObjectPrinter::PrintValueObject() {
7791 !m_orig_valobj.GetCompilerType ().IsValid ())
7892 return m_orig_valobj.GetError ().ToError ();
7993
94+ std::optional<std::string> object_desc;
95+ if (ShouldPrintObjectDescription ()) {
96+ // The object description is invoked now, but not printed until after
97+ // value/summary. Calling GetObjectDescription at the outset of printing
98+ // allows for early discovery of errors. In the case of an error, the value
99+ // object is printed normally.
100+ llvm::Expected<std::string> object_desc_or_err =
101+ GetMostSpecializedValue ().GetObjectDescription ();
102+ if (!object_desc_or_err) {
103+ auto error_msg = toString (object_desc_or_err.takeError ());
104+ *m_stream << " error: " << error_msg << maybeNewline (error_msg);
105+
106+ // Print the value object directly.
107+ m_options.DisableObjectDescription ();
108+ } else {
109+ object_desc = *object_desc_or_err;
110+ }
111+ }
112+
80113 if (ShouldPrintValueObject ()) {
81114 PrintLocationIfNeeded ();
82115 m_stream->Indent ();
@@ -90,8 +123,10 @@ llvm::Error ValueObjectPrinter::PrintValueObject() {
90123 m_val_summary_ok =
91124 PrintValueAndSummaryIfNeeded (value_printed, summary_printed);
92125
93- if (m_val_summary_ok)
126+ if (m_val_summary_ok) {
127+ PrintObjectDescriptionIfNeeded (object_desc);
94128 return PrintChildrenIfNeeded (value_printed, summary_printed);
129+ }
95130 m_stream->EOL ();
96131
97132 return llvm::Error::success ();
@@ -144,24 +179,6 @@ void ValueObjectPrinter::SetupMostSpecializedValue() {
144179 " SetupMostSpecialized value must compute a valid ValueObject" );
145180}
146181
147- llvm::Expected<std::string> ValueObjectPrinter::GetDescriptionForDisplay () {
148- ValueObject &valobj = GetMostSpecializedValue ();
149- llvm::Expected<std::string> maybe_str = valobj.GetObjectDescription ();
150- if (maybe_str)
151- return maybe_str;
152-
153- const char *str = nullptr ;
154- if (!str)
155- str = valobj.GetSummaryAsCString ();
156- if (!str)
157- str = valobj.GetValueAsCString ();
158-
159- if (!str)
160- return maybe_str;
161- llvm::consumeError (maybe_str.takeError ());
162- return str;
163- }
164-
165182const char *ValueObjectPrinter::GetRootNameForDisplay () {
166183 const char *root_valobj_name =
167184 m_options.m_root_valobj_name .empty ()
@@ -468,38 +485,14 @@ bool ValueObjectPrinter::PrintValueAndSummaryIfNeeded(bool &value_printed,
468485 return !error_printed;
469486}
470487
471- llvm::Error
472- ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed,
473- bool summary_printed) {
474- if (ShouldPrintValueObject ()) {
475- // let's avoid the overly verbose no description error for a nil thing
476- if (m_options.m_use_objc && !IsNil () && !IsUninitialized () &&
477- (!m_options.m_pointer_as_array )) {
478- if (!m_options.m_hide_value || ShouldShowName ())
479- *m_stream << ' ' ;
480- llvm::Expected<std::string> object_desc =
481- (value_printed || summary_printed)
482- ? GetMostSpecializedValue ().GetObjectDescription ()
483- : GetDescriptionForDisplay ();
484- if (!object_desc) {
485- // If no value or summary was printed, surface the error.
486- if (!value_printed && !summary_printed)
487- return object_desc.takeError ();
488- // Otherwise gently nudge the user that they should have used
489- // `p` instead of `po`. Unfortunately we cannot be more direct
490- // about this, because we don't actually know what the user did.
491- *m_stream << " warning: no object description available\n " ;
492- llvm::consumeError (object_desc.takeError ());
493- } else {
494- *m_stream << *object_desc;
495- // If the description already ends with a \n don't add another one.
496- if (object_desc->empty () || object_desc->back () != ' \n ' )
497- *m_stream << ' \n ' ;
498- }
499- return llvm::Error::success ();
500- }
501- }
502- return llvm::Error::success ();
488+ void ValueObjectPrinter::PrintObjectDescriptionIfNeeded (
489+ std::optional<std::string> object_desc) {
490+ if (!object_desc)
491+ return ;
492+
493+ if (!m_options.m_hide_value || ShouldShowName ())
494+ *m_stream << ' ' ;
495+ *m_stream << *object_desc << maybeNewline (*object_desc);
503496}
504497
505498bool DumpValueObjectOptions::PointerDepth::CanAllowExpansion (
@@ -552,7 +545,7 @@ bool ValueObjectPrinter::ShouldPrintChildren(
552545 if (m_options.m_pointer_as_array )
553546 return true ;
554547
555- if (m_options.m_use_objc )
548+ if (m_options.m_use_object_desc )
556549 return false ;
557550
558551 bool print_children = true ;
@@ -849,9 +842,6 @@ bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) {
849842
850843llvm::Error ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed,
851844 bool summary_printed) {
852- auto error = PrintObjectDescriptionIfNeeded (value_printed, summary_printed);
853- if (error)
854- return error;
855845
856846 ValueObject &valobj = GetMostSpecializedValue ();
857847
0 commit comments