Skip to content

Commit 31e4366

Browse files
committed
Report back errors in GetNumChildren() (llvm#84265)
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. This is the final patch in the series that includes llvm#83501 and llvm#84219 (cherry picked from commit 6462ead)
1 parent 6252994 commit 31e4366

File tree

11 files changed

+67
-12
lines changed

11 files changed

+67
-12
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
@@ -108,7 +108,8 @@ ValueObjectVariable::CalculateNumChildren(uint32_t max) {
108108
CompilerType type(GetCompilerType());
109109

110110
if (!type.IsValid())
111-
return 0;
111+
return llvm::make_error<llvm::StringError>("invalid type",
112+
llvm::inconvertibleErrorCode());
112113

113114
ExecutionContext exe_ctx(GetExecutionContextRef());
114115
const bool omit_empty_base_classes = true;

lldb/source/DataFormatters/ValueObjectPrinter.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -643,13 +643,17 @@ void ValueObjectPrinter::PrintChild(
643643
}
644644
}
645645

646-
uint32_t ValueObjectPrinter::GetMaxNumChildrenToPrint(bool &print_dotdotdot) {
646+
llvm::Expected<uint32_t>
647+
ValueObjectPrinter::GetMaxNumChildrenToPrint(bool &print_dotdotdot) {
647648
ValueObject &synth_valobj = GetValueObjectForChildrenGeneration();
648649

649650
if (m_options.m_pointer_as_array)
650651
return m_options.m_pointer_as_array.m_element_count;
651652

652-
uint32_t num_children = synth_valobj.GetNumChildrenIgnoringErrors();
653+
auto num_children_or_err = synth_valobj.GetNumChildren();
654+
if (!num_children_or_err)
655+
return num_children_or_err;
656+
uint32_t num_children = *num_children_or_err;
653657
print_dotdotdot = false;
654658
if (num_children) {
655659
const size_t max_num_children = GetMostSpecializedValue()
@@ -726,7 +730,12 @@ void ValueObjectPrinter::PrintChildren(
726730
ValueObject &synth_valobj = GetValueObjectForChildrenGeneration();
727731

728732
bool print_dotdotdot = false;
729-
size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
733+
auto num_children_or_err = GetMaxNumChildrenToPrint(print_dotdotdot);
734+
if (!num_children_or_err) {
735+
*m_stream << " <" << llvm::toString(num_children_or_err.takeError()) << '>';
736+
return;
737+
}
738+
uint32_t num_children = *num_children_or_err;
730739
if (num_children) {
731740
bool any_children_printed = false;
732741

@@ -775,7 +784,12 @@ bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) {
775784
ValueObject &synth_valobj = GetValueObjectForChildrenGeneration();
776785

777786
bool print_dotdotdot = false;
778-
size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
787+
auto num_children_or_err = GetMaxNumChildrenToPrint(print_dotdotdot);
788+
if (!num_children_or_err) {
789+
*m_stream << '<' << llvm::toString(num_children_or_err.takeError()) << '>';
790+
return true;
791+
}
792+
uint32_t num_children = *num_children_or_err;
779793

780794
if (num_children) {
781795
m_stream->PutChar('(');

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5396,7 +5396,8 @@ TypeSystemClang::GetNumChildren(lldb::opaque_compiler_type_t type,
53965396
bool omit_empty_base_classes,
53975397
const ExecutionContext *exe_ctx) {
53985398
if (!type)
5399-
return 0;
5399+
return llvm::make_error<llvm::StringError>("invalid clang type",
5400+
llvm::inconvertibleErrorCode());
54005401

54015402
uint32_t num_children = 0;
54025403
clang::QualType qual_type(RemoveWrappingTypes(GetQualType(type)));
@@ -5456,9 +5457,11 @@ TypeSystemClang::GetNumChildren(lldb::opaque_compiler_type_t type,
54565457
field_end = record_decl->field_end();
54575458
field != field_end; ++field)
54585459
++num_children;
5459-
}
5460+
} else
5461+
return llvm::make_error<llvm::StringError>(
5462+
"incomplete type \"" + GetDisplayTypeName(type).GetString() + "\"",
5463+
llvm::inconvertibleErrorCode());
54605464
break;
5461-
54625465
case clang::Type::ObjCObject:
54635466
case clang::Type::ObjCInterface:
54645467
if (GetCompleteQualType(&getASTContext(), qual_type)) {

lldb/source/Symbol/CompilerType.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,8 @@ CompilerType::GetNumChildren(bool omit_empty_base_classes,
616616
if (auto type_system_sp = GetTypeSystem())
617617
return type_system_sp->GetNumChildren(m_type, omit_empty_base_classes,
618618
exe_ctx);
619-
return 0;
619+
return llvm::make_error<llvm::StringError>("invalid type",
620+
llvm::inconvertibleErrorCode());
620621
}
621622

622623
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: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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(self, "break here",
13+
lldb.SBFileSpec('main.c'))
14+
self.expect('v -ptr-depth 1 x', substrs=['<incomplete type "Opaque">'])
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
struct Opaque {
2+
int i, j, k;
3+
} *global;
4+
struct Opaque *getOpaque() { return &global; }
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+
}

lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_declaration-with-children.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
target var a
1313
# CHECK-LABEL: target var a
1414
# FIXME: This should also produce some kind of an error.
15-
# CHECK: (A) a = {}
15+
# CHECK: (A) a = <incomplete type "A">
1616
expr a
1717
# CHECK-LABEL: expr a
1818
# CHECK: incomplete type 'A' where a complete type is required

lldb/test/Shell/SymbolFile/DWARF/x86/debug-types-missing-signature.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ RUN: not %lldb %t -b -o "expression (EC) 1" 2>&1 | FileCheck --check-prefix=PRIN
2121
PRINTEC: use of undeclared identifier 'EC'
2222

2323
RUN: %lldb %t -b -o "target variable a e ec" | FileCheck --check-prefix=VARS %s
24-
VARS: (const (unnamed struct)) a = {}
24+
VARS: (const (unnamed struct)) a = <incomplete type "const (unnamed struct)">
2525
VARS: (const (unnamed enum)) e = 0x1
2626
VARS: (const (unnamed enum)) ec = 0x1

0 commit comments

Comments
 (0)