Skip to content

Commit f900644

Browse files
committed
Refactor GetObjectDescription() to return llvm::Expected (NFC)
This is de facto an NFC change for Objective-C but will benefit the Swift language plugin.
1 parent d1bc75c commit f900644

File tree

12 files changed

+143
-103
lines changed

12 files changed

+143
-103
lines changed

lldb/include/lldb/Core/ValueObject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ class ValueObject {
537537
std::string &destination,
538538
const TypeSummaryOptions &options);
539539

540-
const char *GetObjectDescription();
540+
llvm::Expected<std::string> GetObjectDescription();
541541

542542
bool HasSpecialPrintableRepresentation(
543543
ValueObjectRepresentationStyle val_obj_display,

lldb/include/lldb/DataFormatters/ValueObjectPrinter.h

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

7676
void SetupMostSpecializedValue();
7777

78-
const char *GetDescriptionForDisplay();
78+
llvm::Expected<std::string> GetDescriptionForDisplay();
7979

8080
const char *GetRootNameForDisplay();
8181

@@ -108,7 +108,8 @@ class ValueObjectPrinter {
108108

109109
bool PrintValueAndSummaryIfNeeded(bool &value_printed, bool &summary_printed);
110110

111-
bool PrintObjectDescriptionIfNeeded(bool value_printed, bool summary_printed);
111+
llvm::Error PrintObjectDescriptionIfNeeded(bool value_printed,
112+
bool summary_printed);
112113

113114
bool
114115
ShouldPrintChildren(DumpValueObjectOptions::PointerDepth &curr_ptr_depth);
@@ -132,7 +133,7 @@ class ValueObjectPrinter {
132133
PrintChildren(bool value_printed, bool summary_printed,
133134
const DumpValueObjectOptions::PointerDepth &curr_ptr_depth);
134135

135-
void PrintChildrenIfNeeded(bool value_printed, bool summary_printed);
136+
llvm::Error PrintChildrenIfNeeded(bool value_printed, bool summary_printed);
136137

137138
bool PrintChildrenOneLiner(bool hide_names);
138139

lldb/include/lldb/Target/LanguageRuntime.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,12 @@ class LanguageRuntime : public Runtime, public PluginInterface {
7373
return nullptr;
7474
}
7575

76-
virtual bool GetObjectDescription(Stream &str, ValueObject &object) = 0;
77-
78-
virtual bool GetObjectDescription(Stream &str, Value &value,
79-
ExecutionContextScope *exe_scope) = 0;
76+
virtual llvm::Error GetObjectDescription(Stream &str,
77+
ValueObject &object) = 0;
8078

79+
virtual llvm::Error
80+
GetObjectDescription(Stream &str, Value &value,
81+
ExecutionContextScope *exe_scope) = 0;
8182

8283
struct VTableInfo {
8384
Address addr; /// Address of the vtable's virtual function table

lldb/source/API/SBValue.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,10 @@ const char *SBValue::GetObjectDescription() {
379379
if (!value_sp)
380380
return nullptr;
381381

382-
return ConstString(value_sp->GetObjectDescription()).GetCString();
382+
llvm::Expected<std::string> str = value_sp->GetObjectDescription();
383+
if (!str)
384+
return ConstString("error: " + toString(str.takeError())).AsCString();
385+
return ConstString(*str).AsCString();
383386
}
384387

385388
SBType SBValue::GetType() {

lldb/source/Core/ValueObject.cpp

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -989,41 +989,46 @@ ValueObject::ReadPointedString(lldb::WritableDataBufferSP &buffer_sp,
989989
return {total_bytes_read, was_capped};
990990
}
991991

992-
const char *ValueObject::GetObjectDescription() {
992+
llvm::Expected<std::string> ValueObject::GetObjectDescription() {
993993
if (!UpdateValueIfNeeded(true))
994-
return nullptr;
994+
return llvm::createStringError("could not update value");
995995

996996
// Return cached value.
997997
if (!m_object_desc_str.empty())
998-
return m_object_desc_str.c_str();
998+
return m_object_desc_str;
999999

10001000
ExecutionContext exe_ctx(GetExecutionContextRef());
10011001
Process *process = exe_ctx.GetProcessPtr();
10021002
if (!process)
1003-
return nullptr;
1003+
return llvm::createStringError("no process");
10041004

10051005
// Returns the object description produced by one language runtime.
1006-
auto get_object_description = [&](LanguageType language) -> const char * {
1006+
auto get_object_description =
1007+
[&](LanguageType language) -> llvm::Expected<std::string> {
10071008
if (LanguageRuntime *runtime = process->GetLanguageRuntime(language)) {
10081009
StreamString s;
1009-
if (runtime->GetObjectDescription(s, *this)) {
1010-
m_object_desc_str.append(std::string(s.GetString()));
1011-
return m_object_desc_str.c_str();
1012-
}
1010+
if (llvm::Error error = runtime->GetObjectDescription(s, *this))
1011+
return error;
1012+
m_object_desc_str = s.GetString();
1013+
return m_object_desc_str;
10131014
}
1014-
return nullptr;
1015+
return llvm::createStringError("no native language runtime");
10151016
};
10161017

10171018
// Try the native language runtime first.
10181019
LanguageType native_language = GetObjectRuntimeLanguage();
1019-
if (const char *desc = get_object_description(native_language))
1020+
llvm::Expected<std::string> desc = get_object_description(native_language);
1021+
if (desc)
10201022
return desc;
10211023

10221024
// Try the Objective-C language runtime. This fallback is necessary
10231025
// for Objective-C++ and mixed Objective-C / C++ programs.
1024-
if (Language::LanguageIsCFamily(native_language))
1026+
if (Language::LanguageIsCFamily(native_language)) {
1027+
// We're going to try again, so let's drop the first error.
1028+
llvm::consumeError(desc.takeError());
10251029
return get_object_description(eLanguageTypeObjC);
1026-
return nullptr;
1030+
}
1031+
return desc;
10271032
}
10281033

10291034
bool ValueObject::GetValueAsCString(const lldb_private::TypeFormatImpl &format,
@@ -1472,9 +1477,16 @@ bool ValueObject::DumpPrintableRepresentation(
14721477
str = GetSummaryAsCString();
14731478
break;
14741479

1475-
case eValueObjectRepresentationStyleLanguageSpecific:
1476-
str = GetObjectDescription();
1477-
break;
1480+
case eValueObjectRepresentationStyleLanguageSpecific: {
1481+
llvm::Expected<std::string> desc = GetObjectDescription();
1482+
if (!desc) {
1483+
strm << "error: " << toString(desc.takeError());
1484+
str = strm.GetString();
1485+
} else {
1486+
strm << *desc;
1487+
str = strm.GetString();
1488+
}
1489+
} break;
14781490

14791491
case eValueObjectRepresentationStyleLocation:
14801492
str = GetLocationAsCString();

lldb/source/DataFormatters/ValueObjectPrinter.cpp

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,8 @@ llvm::Error ValueObjectPrinter::PrintValueObject() {
9191
PrintValueAndSummaryIfNeeded(value_printed, summary_printed);
9292

9393
if (m_val_summary_ok)
94-
PrintChildrenIfNeeded(value_printed, summary_printed);
95-
else
96-
m_stream->EOL();
94+
return PrintChildrenIfNeeded(value_printed, summary_printed);
95+
m_stream->EOL();
9796

9897
return llvm::Error::success();
9998
}
@@ -145,13 +144,21 @@ void ValueObjectPrinter::SetupMostSpecializedValue() {
145144
"SetupMostSpecialized value must compute a valid ValueObject");
146145
}
147146

148-
const char *ValueObjectPrinter::GetDescriptionForDisplay() {
147+
llvm::Expected<std::string> ValueObjectPrinter::GetDescriptionForDisplay() {
149148
ValueObject &valobj = GetMostSpecializedValue();
150-
const char *str = valobj.GetObjectDescription();
149+
llvm::Expected<std::string> maybe_str = valobj.GetObjectDescription();
150+
if (maybe_str)
151+
return maybe_str;
152+
153+
const char *str = nullptr;
151154
if (!str)
152155
str = valobj.GetSummaryAsCString();
153156
if (!str)
154157
str = valobj.GetValueAsCString();
158+
159+
if (!str)
160+
return maybe_str;
161+
llvm::consumeError(maybe_str.takeError());
155162
return str;
156163
}
157164

@@ -461,34 +468,38 @@ bool ValueObjectPrinter::PrintValueAndSummaryIfNeeded(bool &value_printed,
461468
return !error_printed;
462469
}
463470

464-
bool ValueObjectPrinter::PrintObjectDescriptionIfNeeded(bool value_printed,
465-
bool summary_printed) {
471+
llvm::Error
472+
ValueObjectPrinter::PrintObjectDescriptionIfNeeded(bool value_printed,
473+
bool summary_printed) {
466474
if (ShouldPrintValueObject()) {
467475
// let's avoid the overly verbose no description error for a nil thing
468476
if (m_options.m_use_objc && !IsNil() && !IsUninitialized() &&
469477
(!m_options.m_pointer_as_array)) {
470478
if (!m_options.m_hide_value || ShouldShowName())
471-
m_stream->Printf(" ");
472-
const char *object_desc = nullptr;
473-
if (value_printed || summary_printed)
474-
object_desc = GetMostSpecializedValue().GetObjectDescription();
475-
else
476-
object_desc = GetDescriptionForDisplay();
477-
if (object_desc && *object_desc) {
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;
478495
// If the description already ends with a \n don't add another one.
479-
size_t object_end = strlen(object_desc) - 1;
480-
if (object_desc[object_end] == '\n')
481-
m_stream->Printf("%s", object_desc);
482-
else
483-
m_stream->Printf("%s\n", object_desc);
484-
return true;
485-
} else if (!value_printed && !summary_printed)
486-
return true;
487-
else
488-
return false;
496+
if (object_desc->empty() || object_desc->back() != '\n')
497+
*m_stream << '\n';
498+
}
499+
return llvm::Error::success();
489500
}
490501
}
491-
return true;
502+
return llvm::Error::success();
492503
}
493504

494505
bool DumpValueObjectOptions::PointerDepth::CanAllowExpansion() const {
@@ -812,9 +823,12 @@ bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) {
812823
return true;
813824
}
814825

815-
void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
816-
bool summary_printed) {
817-
PrintObjectDescriptionIfNeeded(value_printed, summary_printed);
826+
llvm::Error ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
827+
bool summary_printed) {
828+
auto error = PrintObjectDescriptionIfNeeded(value_printed, summary_printed);
829+
if (error)
830+
return error;
831+
818832
ValueObject &valobj = GetMostSpecializedValue();
819833

820834
DumpValueObjectOptions::PointerDepth curr_ptr_depth = m_ptr_depth;
@@ -830,7 +844,7 @@ void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
830844
if (m_printed_instance_pointers->count(instance_ptr_value)) {
831845
// We already printed this instance-is-pointer thing, so don't expand it.
832846
m_stream->PutCString(" {...}\n");
833-
return;
847+
return llvm::Error::success();
834848
} else {
835849
// Remember this guy for future reference.
836850
m_printed_instance_pointers->emplace(instance_ptr_value);
@@ -858,6 +872,7 @@ void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
858872
.SetReachedMaximumDepth();
859873
} else
860874
m_stream->EOL();
875+
return llvm::Error::success();
861876
}
862877

863878
bool ValueObjectPrinter::HasReachedMaximumDepth() {

lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,17 @@ bool CPPLanguageRuntime::IsAllowedRuntimeValue(ConstString name) {
4747
return name == g_this || name == g_promise || name == g_coro_frame;
4848
}
4949

50-
bool CPPLanguageRuntime::GetObjectDescription(Stream &str,
51-
ValueObject &object) {
50+
llvm::Error CPPLanguageRuntime::GetObjectDescription(Stream &str,
51+
ValueObject &object) {
5252
// C++ has no generic way to do this.
53-
return false;
53+
return llvm::createStringError("C++ does not support object descriptions");
5454
}
5555

56-
bool CPPLanguageRuntime::GetObjectDescription(
57-
Stream &str, Value &value, ExecutionContextScope *exe_scope) {
56+
llvm::Error
57+
CPPLanguageRuntime::GetObjectDescription(Stream &str, Value &value,
58+
ExecutionContextScope *exe_scope) {
5859
// C++ has no generic way to do this.
59-
return false;
60+
return llvm::createStringError("C++ does not support object descriptions");
6061
}
6162

6263
bool contains_lambda_identifier(llvm::StringRef &str_ref) {

lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ class CPPLanguageRuntime : public LanguageRuntime {
5959
process.GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus));
6060
}
6161

62-
bool GetObjectDescription(Stream &str, ValueObject &object) override;
62+
llvm::Error GetObjectDescription(Stream &str, ValueObject &object) override;
6363

64-
bool GetObjectDescription(Stream &str, Value &value,
65-
ExecutionContextScope *exe_scope) override;
64+
llvm::Error GetObjectDescription(Stream &str, Value &value,
65+
ExecutionContextScope *exe_scope) override;
6666

6767
/// Obtain a ThreadPlan to get us into C++ constructs such as std::function.
6868
///

0 commit comments

Comments
 (0)