Skip to content

Commit ce204ae

Browse files
committed
Rework handling of po failure
1 parent 93c8135 commit ce204ae

File tree

4 files changed

+58
-63
lines changed

4 files changed

+58
-63
lines changed

lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ class DumpValueObjectOptions {
7676

7777
DumpValueObjectOptions &SetShowLocation(bool show = false);
7878

79+
DumpValueObjectOptions &DisableObjectiveC();
80+
7981
DumpValueObjectOptions &SetUseObjectiveC(bool use = false);
8082

8183
DumpValueObjectOptions &SetShowSummary(bool show = true);

lldb/include/lldb/DataFormatters/ValueObjectPrinter.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,6 @@ class ValueObjectPrinter {
7575

7676
void SetupMostSpecializedValue();
7777

78-
llvm::Expected<std::string> GetDescriptionForDisplay();
79-
8078
const char *GetRootNameForDisplay();
8179

8280
bool ShouldPrintValueObject();
@@ -108,8 +106,7 @@ class ValueObjectPrinter {
108106

109107
bool PrintValueAndSummaryIfNeeded(bool &value_printed, bool &summary_printed);
110108

111-
llvm::Error PrintObjectDescriptionIfNeeded(bool value_printed,
112-
bool summary_printed);
109+
void PrintObjectDescriptionIfNeeded(std::optional<std::string> object_desc);
113110

114111
bool
115112
ShouldPrintChildren(DumpValueObjectOptions::PointerDepth &curr_ptr_depth);
@@ -141,6 +138,7 @@ class ValueObjectPrinter {
141138

142139
private:
143140
bool ShouldShowName() const;
141+
bool ShouldPrintObjectDescription();
144142

145143
ValueObject &m_orig_valobj;
146144
/// Cache the current "most specialized" value. Don't use this

lldb/source/DataFormatters/DumpValueObjectOptions.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,16 @@ DumpValueObjectOptions &DumpValueObjectOptions::SetShowLocation(bool show) {
6565
return *this;
6666
}
6767

68+
DumpValueObjectOptions &DumpValueObjectOptions::DisableObjectiveC() {
69+
// Reset these options to their default values.
70+
SetUseObjectiveC(false);
71+
SetHideRootType(false);
72+
SetHideRootName(false);
73+
SetHideValue(false);
74+
SetShowSummary(true);
75+
return *this;
76+
}
77+
6878
DumpValueObjectOptions &DumpValueObjectOptions::SetUseObjectiveC(bool use) {
6979
m_use_objc = use;
7080
return *this;

lldb/source/DataFormatters/ValueObjectPrinter.cpp

Lines changed: 44 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
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

2224
using namespace lldb;
2325
using 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+
7387
llvm::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-
171183
const 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

511499
bool DumpValueObjectOptions::PointerDepth::CanAllowExpansion() const {
@@ -825,9 +813,6 @@ bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) {
825813

826814
llvm::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

Comments
 (0)