1515#include " lldb/Target/Target.h"
1616#include " lldb/Utility/Stream.h"
1717#include " lldb/ValueObject/ValueObject.h"
18+ #include " llvm/Support/Error.h"
1819#include " llvm/Support/MathExtras.h"
1920#include < cstdint>
2021#include < memory>
22+ #include < optional>
2123
2224using namespace lldb ;
2325using namespace lldb_private ;
@@ -70,6 +72,18 @@ void ValueObjectPrinter::Init(
7072 SetupMostSpecializedValue ();
7173}
7274
75+ static const char *maybeNewline (const std::string &s) {
76+ // If the string already ends with a \n don't add another one.
77+ if (s.empty () || s.back () != ' \n ' )
78+ return " \n " ;
79+ return " " ;
80+ }
81+
82+ bool ValueObjectPrinter::ShouldPrintObjectDescription () {
83+ return ShouldPrintValueObject () && m_options.m_use_objc && !IsNil () &&
84+ !IsUninitialized () && !m_options.m_pointer_as_array ;
85+ }
86+
7387llvm::Error ValueObjectPrinter::PrintValueObject () {
7488 // If the incoming ValueObject is in an error state, the best we're going to
7589 // get out of it is its type. But if we don't even have that, just print
@@ -78,6 +92,25 @@ llvm::Error ValueObjectPrinter::PrintValueObject() {
7892 !m_orig_valobj.GetCompilerType ().IsValid ())
7993 return m_orig_valobj.GetError ().ToError ();
8094
95+ std::optional<std::string> object_desc;
96+ if (ShouldPrintObjectDescription ()) {
97+ // The object description is invoked now, but not printed until after
98+ // value/summary. Calling GetObjectDescription at the outset of printing
99+ // allows for early discovery of errors. In the case of an error, the value
100+ // object is printed normally.
101+ llvm::Expected<std::string> object_desc_or_err =
102+ GetMostSpecializedValue ().GetObjectDescription ();
103+ if (!object_desc_or_err) {
104+ auto error_msg = toString (object_desc_or_err.takeError ());
105+ *m_stream << " error: " << error_msg << maybeNewline (error_msg);
106+
107+ // Print the value object directly.
108+ m_options.DisableObjectiveC ();
109+ } else {
110+ object_desc = *object_desc_or_err;
111+ }
112+ }
113+
81114 if (ShouldPrintValueObject ()) {
82115 PrintLocationIfNeeded ();
83116 m_stream->Indent ();
@@ -91,8 +124,10 @@ llvm::Error ValueObjectPrinter::PrintValueObject() {
91124 m_val_summary_ok =
92125 PrintValueAndSummaryIfNeeded (value_printed, summary_printed);
93126
94- if (m_val_summary_ok)
127+ if (m_val_summary_ok) {
128+ PrintObjectDescriptionIfNeeded (object_desc);
95129 return PrintChildrenIfNeeded (value_printed, summary_printed);
130+ }
96131 m_stream->EOL ();
97132
98133 return llvm::Error::success ();
@@ -145,29 +180,6 @@ void ValueObjectPrinter::SetupMostSpecializedValue() {
145180 " SetupMostSpecialized value must compute a valid ValueObject" );
146181}
147182
148- llvm::Expected<std::string> ValueObjectPrinter::GetDescriptionForDisplay () {
149- ValueObject &valobj = GetMostSpecializedValue ();
150- llvm::Expected<std::string> maybe_str = valobj.GetObjectDescription ();
151- if (maybe_str)
152- return maybe_str;
153-
154- if (maybe_str.errorIsA <lldb_private::ExpressionError>())
155- // Propagate expression errors to expose diagnostics to the user.
156- // Without this early exit, the summary/value may be shown without errors.
157- return maybe_str;
158-
159- const char *str = nullptr ;
160- if (!str)
161- str = valobj.GetSummaryAsCString ();
162- if (!str)
163- str = valobj.GetValueAsCString ();
164-
165- if (!str)
166- return maybe_str;
167- llvm::consumeError (maybe_str.takeError ());
168- return str;
169- }
170-
171183const char *ValueObjectPrinter::GetRootNameForDisplay () {
172184 const char *root_valobj_name =
173185 m_options.m_root_valobj_name .empty ()
@@ -474,38 +486,14 @@ bool ValueObjectPrinter::PrintValueAndSummaryIfNeeded(bool &value_printed,
474486 return !error_printed;
475487}
476488
477- llvm::Error
478- ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed,
479- bool summary_printed) {
480- if (ShouldPrintValueObject ()) {
481- // let's avoid the overly verbose no description error for a nil thing
482- if (m_options.m_use_objc && !IsNil () && !IsUninitialized () &&
483- (!m_options.m_pointer_as_array )) {
484- if (!m_options.m_hide_value || ShouldShowName ())
485- *m_stream << ' ' ;
486- llvm::Expected<std::string> object_desc =
487- (value_printed || summary_printed)
488- ? GetMostSpecializedValue ().GetObjectDescription ()
489- : GetDescriptionForDisplay ();
490- if (!object_desc) {
491- // If no value or summary was printed, surface the error.
492- if (!value_printed && !summary_printed)
493- return object_desc.takeError ();
494- // Otherwise gently nudge the user that they should have used
495- // `p` instead of `po`. Unfortunately we cannot be more direct
496- // about this, because we don't actually know what the user did.
497- *m_stream << " warning: no object description available\n " ;
498- llvm::consumeError (object_desc.takeError ());
499- } else {
500- *m_stream << *object_desc;
501- // If the description already ends with a \n don't add another one.
502- if (object_desc->empty () || object_desc->back () != ' \n ' )
503- *m_stream << ' \n ' ;
504- }
505- return llvm::Error::success ();
506- }
507- }
508- return llvm::Error::success ();
489+ void ValueObjectPrinter::PrintObjectDescriptionIfNeeded (
490+ std::optional<std::string> object_desc) {
491+ if (!object_desc)
492+ return ;
493+
494+ if (!m_options.m_hide_value || ShouldShowName ())
495+ *m_stream << ' ' ;
496+ *m_stream << *object_desc << maybeNewline (*object_desc);
509497}
510498
511499bool DumpValueObjectOptions::PointerDepth::CanAllowExpansion () const {
@@ -825,9 +813,6 @@ bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) {
825813
826814llvm::Error ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed,
827815 bool summary_printed) {
828- auto error = PrintObjectDescriptionIfNeeded (value_printed, summary_printed);
829- if (error)
830- return error;
831816
832817 ValueObject &valobj = GetMostSpecializedValue ();
833818
0 commit comments