Skip to content

Commit 2fc9188

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. (cherry picked from commit f900644)
1 parent 9a172d1 commit 2fc9188

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
@@ -522,7 +522,7 @@ class ValueObject {
522522
std::string &destination,
523523
const TypeSummaryOptions &options);
524524

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

527527
bool HasSpecialPrintableRepresentation(
528528
ValueObjectRepresentationStyle val_obj_display,

lldb/include/lldb/DataFormatters/ValueObjectPrinter.h

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

7777
void SetupMostSpecializedValue();
7878

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

8181
const char *GetRootNameForDisplay();
8282

@@ -109,7 +109,8 @@ class ValueObjectPrinter {
109109

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

112-
bool PrintObjectDescriptionIfNeeded(bool value_printed, bool summary_printed);
112+
llvm::Error PrintObjectDescriptionIfNeeded(bool value_printed,
113+
bool summary_printed);
113114

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

136-
void PrintChildrenIfNeeded(bool value_printed, bool summary_printed);
137+
llvm::Error PrintChildrenIfNeeded(bool value_printed, bool summary_printed);
137138

138139
bool PrintChildrenOneLiner(bool hide_names);
139140

lldb/include/lldb/Target/LanguageRuntime.h

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

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

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

8384
struct VTableInfo {
8485
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
@@ -1067,41 +1067,46 @@ ValueObject::ReadPointedString(lldb::WritableDataBufferSP &buffer_sp,
10671067
return {total_bytes_read, was_capped};
10681068
}
10691069

1070-
const char *ValueObject::GetObjectDescription() {
1070+
llvm::Expected<std::string> ValueObject::GetObjectDescription() {
10711071
if (!UpdateValueIfNeeded(true))
1072-
return nullptr;
1072+
return llvm::createStringError("could not update value");
10731073

10741074
// Return cached value.
10751075
if (!m_object_desc_str.empty())
1076-
return m_object_desc_str.c_str();
1076+
return m_object_desc_str;
10771077

10781078
ExecutionContext exe_ctx(GetExecutionContextRef());
10791079
Process *process = exe_ctx.GetProcessPtr();
10801080
if (!process)
1081-
return nullptr;
1081+
return llvm::createStringError("no process");
10821082

10831083
// Returns the object description produced by one language runtime.
1084-
auto get_object_description = [&](LanguageType language) -> const char * {
1084+
auto get_object_description =
1085+
[&](LanguageType language) -> llvm::Expected<std::string> {
10851086
if (LanguageRuntime *runtime = process->GetLanguageRuntime(language)) {
10861087
StreamString s;
1087-
if (runtime->GetObjectDescription(s, *this)) {
1088-
m_object_desc_str.append(std::string(s.GetString()));
1089-
return m_object_desc_str.c_str();
1090-
}
1088+
if (llvm::Error error = runtime->GetObjectDescription(s, *this))
1089+
return error;
1090+
m_object_desc_str = s.GetString();
1091+
return m_object_desc_str;
10911092
}
1092-
return nullptr;
1093+
return llvm::createStringError("no native language runtime");
10931094
};
10941095

10951096
// Try the native language runtime first.
10961097
LanguageType native_language = GetObjectRuntimeLanguage();
1097-
if (const char *desc = get_object_description(native_language))
1098+
llvm::Expected<std::string> desc = get_object_description(native_language);
1099+
if (desc)
10981100
return desc;
10991101

11001102
// Try the Objective-C language runtime. This fallback is necessary
11011103
// for Objective-C++ and mixed Objective-C / C++ programs.
1102-
if (Language::LanguageIsCFamily(native_language))
1104+
if (Language::LanguageIsCFamily(native_language)) {
1105+
// We're going to try again, so let's drop the first error.
1106+
llvm::consumeError(desc.takeError());
11031107
return get_object_description(eLanguageTypeObjC);
1104-
return nullptr;
1108+
}
1109+
return desc;
11051110
}
11061111

11071112
bool ValueObject::GetValueAsCString(const lldb_private::TypeFormatImpl &format,
@@ -1402,9 +1407,16 @@ bool ValueObject::DumpPrintableRepresentation(
14021407
str = GetSummaryAsCString();
14031408
break;
14041409

1405-
case eValueObjectRepresentationStyleLanguageSpecific:
1406-
str = GetObjectDescription();
1407-
break;
1410+
case eValueObjectRepresentationStyleLanguageSpecific: {
1411+
llvm::Expected<std::string> desc = GetObjectDescription();
1412+
if (!desc) {
1413+
strm << "error: " << toString(desc.takeError());
1414+
str = strm.GetString();
1415+
} else {
1416+
strm << *desc;
1417+
str = strm.GetString();
1418+
}
1419+
} break;
14081420

14091421
case eValueObjectRepresentationStyleLocation:
14101422
str = GetLocationAsCString();

lldb/source/DataFormatters/ValueObjectPrinter.cpp

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

9191
if (m_val_summary_ok)
92-
PrintChildrenIfNeeded(value_printed, summary_printed);
93-
else
94-
m_stream->EOL();
92+
return PrintChildrenIfNeeded(value_printed, summary_printed);
93+
m_stream->EOL();
9594

9695
return llvm::Error::success();
9796
}
@@ -143,13 +142,21 @@ void ValueObjectPrinter::SetupMostSpecializedValue() {
143142
"SetupMostSpecialized value must compute a valid ValueObject");
144143
}
145144

146-
const char *ValueObjectPrinter::GetDescriptionForDisplay() {
145+
llvm::Expected<std::string> ValueObjectPrinter::GetDescriptionForDisplay() {
147146
ValueObject &valobj = GetMostSpecializedValue();
148-
const char *str = valobj.GetObjectDescription();
147+
llvm::Expected<std::string> maybe_str = valobj.GetObjectDescription();
148+
if (maybe_str)
149+
return maybe_str;
150+
151+
const char *str = nullptr;
149152
if (!str)
150153
str = valobj.GetSummaryAsCString();
151154
if (!str)
152155
str = valobj.GetValueAsCString();
156+
157+
if (!str)
158+
return maybe_str;
159+
llvm::consumeError(maybe_str.takeError());
153160
return str;
154161
}
155162

@@ -459,34 +466,38 @@ bool ValueObjectPrinter::PrintValueAndSummaryIfNeeded(bool &value_printed,
459466
return !error_printed;
460467
}
461468

462-
bool ValueObjectPrinter::PrintObjectDescriptionIfNeeded(bool value_printed,
463-
bool summary_printed) {
469+
llvm::Error
470+
ValueObjectPrinter::PrintObjectDescriptionIfNeeded(bool value_printed,
471+
bool summary_printed) {
464472
if (ShouldPrintValueObject()) {
465473
// let's avoid the overly verbose no description error for a nil thing
466474
if (m_options.m_use_objc && !IsNil() && !IsUninitialized() &&
467475
(!m_options.m_pointer_as_array)) {
468476
if (!m_options.m_hide_value || ShouldShowName())
469-
m_stream->Printf(" ");
470-
const char *object_desc = nullptr;
471-
if (value_printed || summary_printed)
472-
object_desc = GetMostSpecializedValue().GetObjectDescription();
473-
else
474-
object_desc = GetDescriptionForDisplay();
475-
if (object_desc && *object_desc) {
477+
*m_stream << ' ';
478+
llvm::Expected<std::string> object_desc =
479+
(value_printed || summary_printed)
480+
? GetMostSpecializedValue().GetObjectDescription()
481+
: GetDescriptionForDisplay();
482+
if (!object_desc) {
483+
// If no value or summary was printed, surface the error.
484+
if (!value_printed && !summary_printed)
485+
return object_desc.takeError();
486+
// Otherwise gently nudge the user that they should have used
487+
// `p` instead of `po`. Unfortunately we cannot be more direct
488+
// about this, because we don't actually know what the user did.
489+
*m_stream << "warning: no object description available\n";
490+
llvm::consumeError(object_desc.takeError());
491+
} else {
492+
*m_stream << *object_desc;
476493
// If the description already ends with a \n don't add another one.
477-
size_t object_end = strlen(object_desc) - 1;
478-
if (object_desc[object_end] == '\n')
479-
m_stream->Printf("%s", object_desc);
480-
else
481-
m_stream->Printf("%s\n", object_desc);
482-
return true;
483-
} else if (!value_printed && !summary_printed)
484-
return true;
485-
else
486-
return false;
494+
if (object_desc->empty() || object_desc->back() != '\n')
495+
*m_stream << '\n';
496+
}
497+
return llvm::Error::success();
487498
}
488499
}
489-
return true;
500+
return llvm::Error::success();
490501
}
491502

492503
bool DumpValueObjectOptions::PointerDepth::CanAllowExpansion(
@@ -833,9 +844,12 @@ bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) {
833844
return true;
834845
}
835846

836-
void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
837-
bool summary_printed) {
838-
PrintObjectDescriptionIfNeeded(value_printed, summary_printed);
847+
llvm::Error ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
848+
bool summary_printed) {
849+
auto error = PrintObjectDescriptionIfNeeded(value_printed, summary_printed);
850+
if (error)
851+
return error;
852+
839853
ValueObject &valobj = GetMostSpecializedValue();
840854

841855
DumpValueObjectOptions::PointerDepth curr_ptr_depth = m_ptr_depth;
@@ -851,7 +865,7 @@ void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
851865
if (m_printed_instance_pointers->count(instance_ptr_value)) {
852866
// We already printed this instance-is-pointer thing, so don't expand it.
853867
m_stream->PutCString(" {...}\n");
854-
return;
868+
return llvm::Error::success();
855869
} else {
856870
// Remember this guy for future reference.
857871
m_printed_instance_pointers->emplace(instance_ptr_value);
@@ -879,6 +893,7 @@ void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
879893
.SetReachedMaximumDepth();
880894
} else
881895
m_stream->EOL();
896+
return llvm::Error::success();
882897
}
883898

884899
bool ValueObjectPrinter::HasReachedMaximumDepth() {

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,17 @@ bool CPPLanguageRuntime::IsAllowedRuntimeValue(ConstString name) {
4444
return name == g_this;
4545
}
4646

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

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

5960
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)