Skip to content

Commit ea303d0

Browse files
committed
Report back errors in GetNumChildren()
This is a proof-of-concept patch that illustrates how to use the Expected return values to surface rich error messages all the way up to the ValueObjectPrinter.
1 parent 97a80ff commit ea303d0

File tree

9 files changed

+66
-11
lines changed

9 files changed

+66
-11
lines changed

lldb/include/lldb/DataFormatters/ValueObjectPrinter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ class ValueObjectPrinter {
127127
void PrintChild(lldb::ValueObjectSP child_sp,
128128
const DumpValueObjectOptions::PointerDepth &curr_ptr_depth);
129129

130-
uint32_t GetMaxNumChildrenToPrint(bool &print_dotdotdot);
130+
llvm::Expected<uint32_t> GetMaxNumChildrenToPrint(bool &print_dotdotdot);
131131

132132
void
133133
PrintChildren(bool value_printed, bool summary_printed,

lldb/source/Core/ValueObjectVariable.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ ValueObjectVariable::CalculateNumChildren(uint32_t max) {
9999
CompilerType type(GetCompilerType());
100100

101101
if (!type.IsValid())
102-
return 0;
102+
return llvm::make_error<llvm::StringError>("invalid type",
103+
llvm::inconvertibleErrorCode());
103104

104105
ExecutionContext exe_ctx(GetExecutionContextRef());
105106
const bool omit_empty_base_classes = true;

lldb/source/DataFormatters/ValueObjectPrinter.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -621,13 +621,17 @@ void ValueObjectPrinter::PrintChild(
621621
}
622622
}
623623

624-
uint32_t ValueObjectPrinter::GetMaxNumChildrenToPrint(bool &print_dotdotdot) {
624+
llvm::Expected<uint32_t>
625+
ValueObjectPrinter::GetMaxNumChildrenToPrint(bool &print_dotdotdot) {
625626
ValueObject &synth_valobj = GetValueObjectForChildrenGeneration();
626627

627628
if (m_options.m_pointer_as_array)
628629
return m_options.m_pointer_as_array.m_element_count;
629630

630-
uint32_t num_children = synth_valobj.GetNumChildrenIgnoringErrors();
631+
auto num_children_or_err = synth_valobj.GetNumChildren();
632+
if (!num_children_or_err)
633+
return num_children_or_err;
634+
uint32_t num_children = *num_children_or_err;
631635
print_dotdotdot = false;
632636
if (num_children) {
633637
const size_t max_num_children = GetMostSpecializedValue()
@@ -704,7 +708,12 @@ void ValueObjectPrinter::PrintChildren(
704708
ValueObject &synth_valobj = GetValueObjectForChildrenGeneration();
705709

706710
bool print_dotdotdot = false;
707-
size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
711+
auto num_children_or_err = GetMaxNumChildrenToPrint(print_dotdotdot);
712+
if (!num_children_or_err) {
713+
*m_stream << " <" << llvm::toString(num_children_or_err.takeError()) << '>';
714+
return;
715+
}
716+
uint32_t num_children = *num_children_or_err;
708717
if (num_children) {
709718
bool any_children_printed = false;
710719

@@ -753,13 +762,19 @@ bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) {
753762
ValueObject &synth_valobj = GetValueObjectForChildrenGeneration();
754763

755764
bool print_dotdotdot = false;
756-
size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
765+
auto num_children_or_err = GetMaxNumChildrenToPrint(print_dotdotdot);
766+
if (!num_children_or_err) {
767+
*m_stream << '<' << llvm::toString(num_children_or_err.takeError()) << '>';
768+
return true;
769+
}
770+
uint32_t num_children = *num_children_or_err;
757771

758772
if (num_children) {
759773
m_stream->PutChar('(');
760774

761775
bool did_print_children = false;
762-
for (uint32_t idx = 0; idx < num_children; ++idx) {
776+
for (uint32_t idx = 0; idx < num_children; ++
777+
idx) {
763778
lldb::ValueObjectSP child_sp(synth_valobj.GetChildAtIndex(idx));
764779
if (child_sp)
765780
child_sp = child_sp->GetQualifiedRepresentationIfAvailable(

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5268,7 +5268,8 @@ TypeSystemClang::GetNumChildren(lldb::opaque_compiler_type_t type,
52685268
bool omit_empty_base_classes,
52695269
const ExecutionContext *exe_ctx) {
52705270
if (!type)
5271-
return 0;
5271+
return llvm::make_error<llvm::StringError>("invalid clang type",
5272+
llvm::inconvertibleErrorCode());
52725273

52735274
uint32_t num_children = 0;
52745275
clang::QualType qual_type(RemoveWrappingTypes(GetQualType(type)));
@@ -5326,8 +5327,9 @@ TypeSystemClang::GetNumChildren(lldb::opaque_compiler_type_t type,
53265327
num_children += std::distance(record_decl->field_begin(),
53275328
record_decl->field_end());
53285329
}
5329-
break;
5330-
5330+
return llvm::make_error<llvm::StringError>(
5331+
"incomplete type \"" + GetDisplayTypeName(type).GetString() + "\"",
5332+
llvm::inconvertibleErrorCode());
53315333
case clang::Type::ObjCObject:
53325334
case clang::Type::ObjCInterface:
53335335
if (GetCompleteQualType(&getASTContext(), qual_type)) {

lldb/source/Symbol/CompilerType.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,8 @@ CompilerType::GetNumChildren(bool omit_empty_base_classes,
777777
if (auto type_system_sp = GetTypeSystem())
778778
return type_system_sp->GetNumChildren(m_type, omit_empty_base_classes,
779779
exe_ctx);
780-
return 0;
780+
return llvm::make_error<llvm::StringError>("invalid type",
781+
llvm::inconvertibleErrorCode());
781782
}
782783

783784
lldb::BasicType CompilerType::GetBasicTypeEnumeration() const {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
C_SOURCES := main.c
2+
LD_EXTRAS = hidden.o
3+
4+
a.out: hidden.o
5+
6+
hidden.o: hidden.c
7+
$(CC) -g0 -c -o $@ $<
8+
9+
include Makefile.rules
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import lldb
2+
from lldbsuite.test.decorators import *
3+
from lldbsuite.test.lldbtest import *
4+
from lldbsuite.test import lldbutil
5+
6+
7+
class ValueObjectErrorsTestCase(TestBase):
8+
def test(self):
9+
"""Test that the error message for a missing type
10+
is visible when printing an object"""
11+
self.build()
12+
lldbutil.run_to_source_breakpoint(
13+
self, "break here", lldb.SBFileSpec('main.c'))
14+
self.expect('v -ptr-depth 1 x',
15+
substrs=['<incomplete type "Opaque">'])
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
struct Opaque { int i, j, k; } *global;
2+
struct Opaque *getOpaque() { return &global; }
3+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
struct Opaque;
2+
struct Opaque *getOpaque();
3+
void puts(const char*);
4+
5+
int main() {
6+
struct Opaque *x = getOpaque();
7+
puts("break here\n");
8+
return (int)x;
9+
}

0 commit comments

Comments
 (0)