Author: Jim Ingham Date: 2023-02-28T16:41:20-08:00 New Revision: e8a2fd5e7be23e4087e7ff58efa354dfae1a17c4
URL: https://github.com/llvm/llvm-project/commit/e8a2fd5e7be23e4087e7ff58efa354dfae1a17c4 DIFF: https://github.com/llvm/llvm-project/commit/e8a2fd5e7be23e4087e7ff58efa354dfae1a17c4.diff LOG: 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 Added: Modified: lldb/source/API/SBValue.cpp lldb/source/Core/ValueObject.cpp lldb/source/DataFormatters/ValueObjectPrinter.cpp Removed: ################################################################################ diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index f9e03172a4d0f..ecd16ccf83a8f 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -114,6 +114,10 @@ class ValueImpl { lldb::ValueObjectSP value_sp = m_valobj_sp; Target *target = value_sp->GetTargetSP().get(); + // If this ValueObject holds an error, then it is valuable for that. + if (value_sp->GetError().Fail()) + return value_sp; + if (!target) return ValueObjectSP(); @@ -1047,7 +1051,12 @@ lldb::SBFrame SBValue::GetFrame() { } lldb::ValueObjectSP SBValue::GetSP(ValueLocker &locker) const { - if (!m_opaque_sp || !m_opaque_sp->IsValid()) { + // IsValid means that the SBValue has a value in it. But that's not the + // only time that ValueObjects are useful. We also want to return the value + // if there's an error state in it. + if (!m_opaque_sp || (!m_opaque_sp->IsValid() + && (m_opaque_sp->GetRootSP() + && !m_opaque_sp->GetRootSP()->GetError().Fail()))) { locker.GetError().SetErrorString("No value"); return ValueObjectSP(); } diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 38645b087435d..6e79a04d024e5 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -1173,6 +1173,15 @@ bool ValueObject::DumpPrintableRepresentation( Stream &s, ValueObjectRepresentationStyle val_obj_display, Format custom_format, PrintableRepresentationSpecialCases special, bool do_dump_error) { + + // If the ValueObject has an error, we might end up dumping the type, which + // is useful, but if we don't even have a type, then don't examine the object + // further as that's not meaningful, only the error is. + if (m_error.Fail() && !GetCompilerType().IsValid()) { + if (do_dump_error) + s.Printf("<%s>", m_error.AsCString()); + return false; + } Flags flags(GetTypeInfo()); @@ -1374,6 +1383,8 @@ bool ValueObject::DumpPrintableRepresentation( if (!str.empty()) s << str; else { + // We checked for errors at the start, but do it again here in case + // realizing the value for dumping produced an error. if (m_error.Fail()) { if (do_dump_error) s.Printf("<%s>", m_error.AsCString()); diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp index c4221a5ac7cc0..17e9877bd5242 100644 --- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp +++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp @@ -71,6 +71,18 @@ void ValueObjectPrinter::Init( } bool ValueObjectPrinter::PrintValueObject() { + if (!m_orig_valobj) + return false; + + // If the incoming ValueObject is in an error state, the best we're going to + // get out of it is its type. But if we don't even have that, just print + // the error and exit early. + if (m_orig_valobj->GetError().Fail() + && !m_orig_valobj->GetCompilerType().IsValid()) { + m_stream->Printf("Error: '%s'", m_orig_valobj->GetError().AsCString()); + return true; + } + if (!GetMostSpecializedValue() || m_valobj == nullptr) return false; _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits