https://github.com/adrian-prantl updated https://github.com/llvm/llvm-project/pull/84265
>From 9b02d004a3aec681047d47cb481a269637bdd9fc Mon Sep 17 00:00:00 2001 From: Adrian Prantl <apra...@apple.com> Date: Fri, 8 Mar 2024 14:46:13 -0800 Subject: [PATCH] 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. --- .../lldb/DataFormatters/ValueObjectPrinter.h | 2 +- lldb/source/Core/ValueObjectVariable.cpp | 3 ++- .../DataFormatters/ValueObjectPrinter.cpp | 22 +++++++++++++++---- .../TypeSystem/Clang/TypeSystemClang.cpp | 8 ++++--- lldb/source/Symbol/CompilerType.cpp | 3 ++- .../functionalities/valobj_errors/Makefile | 9 ++++++++ .../valobj_errors/TestValueObjectErrors.py | 15 +++++++++++++ .../functionalities/valobj_errors/hidden.c | 4 ++++ .../API/functionalities/valobj_errors/main.c | 9 ++++++++ 9 files changed, 65 insertions(+), 10 deletions(-) create mode 100644 lldb/test/API/functionalities/valobj_errors/Makefile create mode 100644 lldb/test/API/functionalities/valobj_errors/TestValueObjectErrors.py create mode 100644 lldb/test/API/functionalities/valobj_errors/hidden.c create mode 100644 lldb/test/API/functionalities/valobj_errors/main.c diff --git a/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h b/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h index fe46321c3186cf..32b101a2f9843c 100644 --- a/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h +++ b/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h @@ -127,7 +127,7 @@ class ValueObjectPrinter { void PrintChild(lldb::ValueObjectSP child_sp, const DumpValueObjectOptions::PointerDepth &curr_ptr_depth); - uint32_t GetMaxNumChildrenToPrint(bool &print_dotdotdot); + llvm::Expected<uint32_t> GetMaxNumChildrenToPrint(bool &print_dotdotdot); void PrintChildren(bool value_printed, bool summary_printed, diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp index fb29c22c0ab5af..67d71c90a959d5 100644 --- a/lldb/source/Core/ValueObjectVariable.cpp +++ b/lldb/source/Core/ValueObjectVariable.cpp @@ -99,7 +99,8 @@ ValueObjectVariable::CalculateNumChildren(uint32_t max) { CompilerType type(GetCompilerType()); if (!type.IsValid()) - return 0; + return llvm::make_error<llvm::StringError>("invalid type", + llvm::inconvertibleErrorCode()); ExecutionContext exe_ctx(GetExecutionContextRef()); const bool omit_empty_base_classes = true; diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp index b853199e878c95..bbdc2a99815706 100644 --- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp +++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp @@ -621,13 +621,17 @@ void ValueObjectPrinter::PrintChild( } } -uint32_t ValueObjectPrinter::GetMaxNumChildrenToPrint(bool &print_dotdotdot) { +llvm::Expected<uint32_t> +ValueObjectPrinter::GetMaxNumChildrenToPrint(bool &print_dotdotdot) { ValueObject &synth_valobj = GetValueObjectForChildrenGeneration(); if (m_options.m_pointer_as_array) return m_options.m_pointer_as_array.m_element_count; - uint32_t num_children = synth_valobj.GetNumChildrenIgnoringErrors(); + auto num_children_or_err = synth_valobj.GetNumChildren(); + if (!num_children_or_err) + return num_children_or_err; + uint32_t num_children = *num_children_or_err; print_dotdotdot = false; if (num_children) { const size_t max_num_children = GetMostSpecializedValue() @@ -704,7 +708,12 @@ void ValueObjectPrinter::PrintChildren( ValueObject &synth_valobj = GetValueObjectForChildrenGeneration(); bool print_dotdotdot = false; - size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); + auto num_children_or_err = GetMaxNumChildrenToPrint(print_dotdotdot); + if (!num_children_or_err) { + *m_stream << " <" << llvm::toString(num_children_or_err.takeError()) << '>'; + return; + } + uint32_t num_children = *num_children_or_err; if (num_children) { bool any_children_printed = false; @@ -753,7 +762,12 @@ bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) { ValueObject &synth_valobj = GetValueObjectForChildrenGeneration(); bool print_dotdotdot = false; - size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); + auto num_children_or_err = GetMaxNumChildrenToPrint(print_dotdotdot); + if (!num_children_or_err) { + *m_stream << '<' << llvm::toString(num_children_or_err.takeError()) << '>'; + return true; + } + uint32_t num_children = *num_children_or_err; if (num_children) { m_stream->PutChar('('); diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index c02b08cb478280..16974224f3e2ca 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -5268,7 +5268,8 @@ TypeSystemClang::GetNumChildren(lldb::opaque_compiler_type_t type, bool omit_empty_base_classes, const ExecutionContext *exe_ctx) { if (!type) - return 0; + return llvm::make_error<llvm::StringError>("invalid clang type", + llvm::inconvertibleErrorCode()); uint32_t num_children = 0; clang::QualType qual_type(RemoveWrappingTypes(GetQualType(type))); @@ -5326,8 +5327,9 @@ TypeSystemClang::GetNumChildren(lldb::opaque_compiler_type_t type, num_children += std::distance(record_decl->field_begin(), record_decl->field_end()); } - break; - + return llvm::make_error<llvm::StringError>( + "incomplete type \"" + GetDisplayTypeName(type).GetString() + "\"", + llvm::inconvertibleErrorCode()); case clang::Type::ObjCObject: case clang::Type::ObjCInterface: if (GetCompleteQualType(&getASTContext(), qual_type)) { diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp index 85dd2d841a5a0c..8e4c3c761f784e 100644 --- a/lldb/source/Symbol/CompilerType.cpp +++ b/lldb/source/Symbol/CompilerType.cpp @@ -777,7 +777,8 @@ CompilerType::GetNumChildren(bool omit_empty_base_classes, if (auto type_system_sp = GetTypeSystem()) return type_system_sp->GetNumChildren(m_type, omit_empty_base_classes, exe_ctx); - return 0; + return llvm::make_error<llvm::StringError>("invalid type", + llvm::inconvertibleErrorCode()); } lldb::BasicType CompilerType::GetBasicTypeEnumeration() const { diff --git a/lldb/test/API/functionalities/valobj_errors/Makefile b/lldb/test/API/functionalities/valobj_errors/Makefile new file mode 100644 index 00000000000000..d2c966a71411b2 --- /dev/null +++ b/lldb/test/API/functionalities/valobj_errors/Makefile @@ -0,0 +1,9 @@ +C_SOURCES := main.c +LD_EXTRAS = hidden.o + +a.out: hidden.o + +hidden.o: hidden.c + $(CC) -g0 -c -o $@ $< + +include Makefile.rules diff --git a/lldb/test/API/functionalities/valobj_errors/TestValueObjectErrors.py b/lldb/test/API/functionalities/valobj_errors/TestValueObjectErrors.py new file mode 100644 index 00000000000000..5346e61b2b0c45 --- /dev/null +++ b/lldb/test/API/functionalities/valobj_errors/TestValueObjectErrors.py @@ -0,0 +1,15 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ValueObjectErrorsTestCase(TestBase): + def test(self): + """Test that the error message for a missing type + is visible when printing an object""" + self.build() + lldbutil.run_to_source_breakpoint( + self, "break here", lldb.SBFileSpec('main.c')) + self.expect('v -ptr-depth 1 x', + substrs=['<incomplete type "Opaque">']) diff --git a/lldb/test/API/functionalities/valobj_errors/hidden.c b/lldb/test/API/functionalities/valobj_errors/hidden.c new file mode 100644 index 00000000000000..d3b93ce1ab9cf5 --- /dev/null +++ b/lldb/test/API/functionalities/valobj_errors/hidden.c @@ -0,0 +1,4 @@ +struct Opaque { + int i, j, k; +} *global; +struct Opaque *getOpaque() { return &global; } diff --git a/lldb/test/API/functionalities/valobj_errors/main.c b/lldb/test/API/functionalities/valobj_errors/main.c new file mode 100644 index 00000000000000..fabdca9d3a2ecd --- /dev/null +++ b/lldb/test/API/functionalities/valobj_errors/main.c @@ -0,0 +1,9 @@ +struct Opaque; +struct Opaque *getOpaque(); +void puts(const char *); + +int main() { + struct Opaque *x = getOpaque(); + puts("break here\n"); + return (int)x; +} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits