Skip to content

Commit 3965ca0

Browse files
committed
An SBValue whose underlying ValueObject has no valid value, but does
hold an error should: (a) return false for IsValid, since that's the current behavior and is a convenient way to check "should I get the value for this". (b) preserve the error when an SBValue is made from it, and print the error in the ValueObjectPrinter. Make that happen. Differential Revision: https://reviews.llvm.org/D144664 (cherry picked from commit e8a2fd5) (cherry picked from commit f1d3034)
1 parent 84ec9db commit 3965ca0

File tree

3 files changed

+33
-1
lines changed

3 files changed

+33
-1
lines changed

lldb/source/API/SBValue.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ class ValueImpl {
114114
lldb::ValueObjectSP value_sp = m_valobj_sp;
115115

116116
Target *target = value_sp->GetTargetSP().get();
117+
// If this ValueObject holds an error, then it is valuable for that.
118+
if (value_sp->GetError().Fail())
119+
return value_sp;
120+
117121
if (!target)
118122
return ValueObjectSP();
119123

@@ -1047,7 +1051,12 @@ lldb::SBFrame SBValue::GetFrame() {
10471051
}
10481052

10491053
lldb::ValueObjectSP SBValue::GetSP(ValueLocker &locker) const {
1050-
if (!m_opaque_sp || !m_opaque_sp->IsValid()) {
1054+
// IsValid means that the SBValue has a value in it. But that's not the
1055+
// only time that ValueObjects are useful. We also want to return the value
1056+
// if there's an error state in it.
1057+
if (!m_opaque_sp || (!m_opaque_sp->IsValid()
1058+
&& (m_opaque_sp->GetRootSP()
1059+
&& !m_opaque_sp->GetRootSP()->GetError().Fail()))) {
10511060
locker.GetError().SetErrorString("No value");
10521061
return ValueObjectSP();
10531062
}

lldb/source/Core/ValueObject.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,15 @@ bool ValueObject::DumpPrintableRepresentation(
12501250
Stream &s, ValueObjectRepresentationStyle val_obj_display,
12511251
Format custom_format, PrintableRepresentationSpecialCases special,
12521252
bool do_dump_error) {
1253+
1254+
// If the ValueObject has an error, we might end up dumping the type, which
1255+
// is useful, but if we don't even have a type, then don't examine the object
1256+
// further as that's not meaningful, only the error is.
1257+
if (m_error.Fail() && !GetCompilerType().IsValid()) {
1258+
if (do_dump_error)
1259+
s.Printf("<%s>", m_error.AsCString());
1260+
return false;
1261+
}
12531262

12541263
Flags flags(GetTypeInfo());
12551264

@@ -1451,6 +1460,8 @@ bool ValueObject::DumpPrintableRepresentation(
14511460
if (!str.empty())
14521461
s << str;
14531462
else {
1463+
// We checked for errors at the start, but do it again here in case
1464+
// realizing the value for dumping produced an error.
14541465
if (m_error.Fail()) {
14551466
if (do_dump_error)
14561467
s.Printf("<%s>", m_error.AsCString());

lldb/source/DataFormatters/ValueObjectPrinter.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,18 @@ void ValueObjectPrinter::Init(
7171
}
7272

7373
bool ValueObjectPrinter::PrintValueObject() {
74+
if (!m_orig_valobj)
75+
return false;
76+
77+
// If the incoming ValueObject is in an error state, the best we're going to
78+
// get out of it is its type. But if we don't even have that, just print
79+
// the error and exit early.
80+
if (m_orig_valobj->GetError().Fail()
81+
&& !m_orig_valobj->GetCompilerType().IsValid()) {
82+
m_stream->Printf("Error: '%s'", m_orig_valobj->GetError().AsCString());
83+
return true;
84+
}
85+
7486
if (!GetMostSpecializedValue() || m_valobj == nullptr)
7587
return false;
7688

0 commit comments

Comments
 (0)