Skip to content

Commit 6462ead

Browse files
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
1 parent 94c988b commit 6462ead

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
@@ -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: 18 additions & 4 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,7 +762,12 @@ 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('(');

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

Lines changed: 6 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)));
@@ -5325,9 +5326,11 @@ TypeSystemClang::GetNumChildren(lldb::opaque_compiler_type_t type,
53255326
}
53265327
num_children += std::distance(record_decl->field_begin(),
53275328
record_decl->field_end());
5328-
}
5329+
} else
5330+
return llvm::make_error<llvm::StringError>(
5331+
"incomplete type \"" + GetDisplayTypeName(type).GetString() + "\"",
5332+
llvm::inconvertibleErrorCode());
53295333
break;
5330-
53315334
case clang::Type::ObjCObject:
53325335
case clang::Type::ObjCInterface:
53335336
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: 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)