[Lldb-commits] [lldb] Report back errors in GetNumChildren() (PR #84265)
Adrian Prantl via lldb-commits
lldb-commits at lists.llvm.org
Fri Mar 8 10:40:25 PST 2024
https://github.com/adrian-prantl updated https://github.com/llvm/llvm-project/pull/84265
>From 76d65446227d18f4f3c4675b1aa12678037dff8c Mon Sep 17 00:00:00 2001
From: Adrian Prantl <aprantl at apple.com>
Date: Wed, 6 Mar 2024 16:21:14 -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;
+}
More information about the lldb-commits
mailing list