[Lldb-commits] [lldb] [lldb][TypeSystemClang] Allow arrays to be dereferenced in C/C++. (PR #135843)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Apr 24 09:51:09 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Ilia Kuklin (kuilpd)
<details>
<summary>Changes</summary>
Add a function `IsValidDereferenceType` to TypeSystem.
TypeSystemClang now allows arrays to be dereferenced.
---
Full diff: https://github.com/llvm/llvm-project/pull/135843.diff
7 Files Affected:
- (modified) lldb/include/lldb/Symbol/CompilerType.h (+8)
- (modified) lldb/include/lldb/Symbol/TypeSystem.h (+7)
- (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+17)
- (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h (+7)
- (modified) lldb/source/Symbol/CompilerType.cpp (+15)
- (modified) lldb/source/ValueObject/ValueObject.cpp (+31-33)
- (modified) lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py (+1-1)
``````````diff
diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h
index 671b5314c24a2..f02a415afd12c 100644
--- a/lldb/include/lldb/Symbol/CompilerType.h
+++ b/lldb/include/lldb/Symbol/CompilerType.h
@@ -433,6 +433,14 @@ class CompilerType {
CompilerDecl GetStaticFieldWithName(llvm::StringRef name) const;
+ llvm::Expected<CompilerType>
+ GetDereferencedType(ExecutionContext *exe_ctx, std::string &child_name,
+ uint32_t &child_byte_size, int32_t &child_byte_offset,
+ uint32_t &child_bitfield_bit_size,
+ uint32_t &child_bitfield_bit_offset,
+ bool &child_is_base_class, ValueObject *valobj,
+ uint64_t &language_flags, bool &type_valid) const;
+
llvm::Expected<CompilerType> GetChildCompilerTypeAtIndex(
ExecutionContext *exe_ctx, size_t idx, bool transparent_pointers,
bool omit_empty_base_classes, bool ignore_array_bounds,
diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h
index 9e9edc09a0846..7c58805342993 100644
--- a/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/lldb/include/lldb/Symbol/TypeSystem.h
@@ -364,6 +364,13 @@ class TypeSystem : public PluginInterface,
return CompilerDecl();
}
+ virtual llvm::Expected<CompilerType> GetDereferencedType(
+ lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
+ std::string &child_name, uint32_t &child_byte_size,
+ int32_t &child_byte_offset, uint32_t &child_bitfield_bit_size,
+ uint32_t &child_bitfield_bit_offset, bool &child_is_base_class,
+ ValueObject *valobj, uint64_t &language_flags, bool &type_valid) = 0;
+
virtual llvm::Expected<CompilerType> GetChildCompilerTypeAtIndex(
lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
bool transparent_pointers, bool omit_empty_base_classes,
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 59292f4b24af3..5c1b98509892e 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -6201,6 +6201,23 @@ uint32_t TypeSystemClang::GetNumPointeeChildren(clang::QualType type) {
return 0;
}
+llvm::Expected<CompilerType> TypeSystemClang::GetDereferencedType(
+ lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
+ std::string &child_name, uint32_t &child_byte_size,
+ int32_t &child_byte_offset, uint32_t &child_bitfield_bit_size,
+ uint32_t &child_bitfield_bit_offset, bool &child_is_base_class,
+ ValueObject *valobj, uint64_t &language_flags, bool &type_valid) {
+ type_valid = IsPointerOrReferenceType(type, nullptr) ||
+ IsArrayType(type, nullptr, nullptr, nullptr);
+ if (!type_valid)
+ return llvm::createStringError("not a pointer, reference or array type");
+ bool child_is_deref_of_parent;
+ return GetChildCompilerTypeAtIndex(
+ type, exe_ctx, 0, false, true, false, child_name, child_byte_size,
+ child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
+ child_is_base_class, child_is_deref_of_parent, valobj, language_flags);
+}
+
llvm::Expected<CompilerType> TypeSystemClang::GetChildCompilerTypeAtIndex(
lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
bool transparent_pointers, bool omit_empty_base_classes,
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index 442f88a5b79ae..ab74027cc75c4 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -889,6 +889,13 @@ class TypeSystemClang : public TypeSystem {
static uint32_t GetNumPointeeChildren(clang::QualType type);
+ llvm::Expected<CompilerType> GetDereferencedType(
+ lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
+ std::string &child_name, uint32_t &child_byte_size,
+ int32_t &child_byte_offset, uint32_t &child_bitfield_bit_size,
+ uint32_t &child_bitfield_bit_offset, bool &child_is_base_class,
+ ValueObject *valobj, uint64_t &language_flags, bool &type_valid) override;
+
llvm::Expected<CompilerType> GetChildCompilerTypeAtIndex(
lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
bool transparent_pointers, bool omit_empty_base_classes,
diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp
index 8e89d006d08d3..998822708fe21 100644
--- a/lldb/source/Symbol/CompilerType.cpp
+++ b/lldb/source/Symbol/CompilerType.cpp
@@ -893,6 +893,21 @@ CompilerDecl CompilerType::GetStaticFieldWithName(llvm::StringRef name) const {
return CompilerDecl();
}
+llvm::Expected<CompilerType> CompilerType::GetDereferencedType(
+ ExecutionContext *exe_ctx, std::string &child_name,
+ uint32_t &child_byte_size, int32_t &child_byte_offset,
+ uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
+ bool &child_is_base_class, ValueObject *valobj, uint64_t &language_flags,
+ bool &type_valid) const {
+ if (IsValid())
+ if (auto type_system_sp = GetTypeSystem())
+ return type_system_sp->GetDereferencedType(
+ m_type, exe_ctx, child_name, child_byte_size, child_byte_offset,
+ child_bitfield_bit_size, child_bitfield_bit_offset,
+ child_is_base_class, valobj, language_flags, type_valid);
+ return CompilerType();
+}
+
llvm::Expected<CompilerType> CompilerType::GetChildCompilerTypeAtIndex(
ExecutionContext *exe_ctx, size_t idx, bool transparent_pointers,
bool omit_empty_base_classes, bool ignore_array_bounds,
diff --git a/lldb/source/ValueObject/ValueObject.cpp b/lldb/source/ValueObject/ValueObject.cpp
index 8741cb7343166..b023dbf118d78 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -2850,37 +2850,37 @@ ValueObjectSP ValueObject::Dereference(Status &error) {
if (m_deref_valobj)
return m_deref_valobj->GetSP();
- const bool is_pointer_or_reference_type = IsPointerOrReferenceType();
- if (is_pointer_or_reference_type) {
- bool omit_empty_base_classes = true;
- bool ignore_array_bounds = false;
-
- std::string child_name_str;
- uint32_t child_byte_size = 0;
- int32_t child_byte_offset = 0;
- uint32_t child_bitfield_bit_size = 0;
- uint32_t child_bitfield_bit_offset = 0;
- bool child_is_base_class = false;
- bool child_is_deref_of_parent = false;
- const bool transparent_pointers = false;
- CompilerType compiler_type = GetCompilerType();
- uint64_t language_flags = 0;
+ std::string child_name_str;
+ uint32_t child_byte_size = 0;
+ int32_t child_byte_offset = 0;
+ uint32_t child_bitfield_bit_size = 0;
+ uint32_t child_bitfield_bit_offset = 0;
+ bool child_is_base_class = false;
+ CompilerType compiler_type = GetCompilerType();
+ uint64_t language_flags = 0;
+ bool is_valid_dereference_type = false;
- ExecutionContext exe_ctx(GetExecutionContextRef());
+ ExecutionContext exe_ctx(GetExecutionContextRef());
- CompilerType child_compiler_type;
- auto child_compiler_type_or_err = compiler_type.GetChildCompilerTypeAtIndex(
- &exe_ctx, 0, transparent_pointers, omit_empty_base_classes,
- ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset,
- child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
- child_is_deref_of_parent, this, language_flags);
- if (!child_compiler_type_or_err)
+ CompilerType child_compiler_type;
+ auto child_compiler_type_or_err = compiler_type.GetDereferencedType(
+ &exe_ctx, child_name_str, child_byte_size, child_byte_offset,
+ child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
+ this, language_flags, is_valid_dereference_type);
+
+ std::string deref_error;
+ if (!child_compiler_type_or_err) {
+ auto err = child_compiler_type_or_err.takeError();
+ if (err.isA<llvm::StringError>()) {
+ deref_error = llvm::toString(std::move(err));
LLDB_LOG_ERROR(GetLog(LLDBLog::Types),
- child_compiler_type_or_err.takeError(),
+ llvm::createStringError(deref_error),
"could not find child: {0}");
- else
- child_compiler_type = *child_compiler_type_or_err;
+ }
+ } else
+ child_compiler_type = *child_compiler_type_or_err;
+ if (is_valid_dereference_type) {
if (child_compiler_type && child_byte_size) {
ConstString child_name;
if (!child_name_str.empty())
@@ -2889,8 +2889,7 @@ ValueObjectSP ValueObject::Dereference(Status &error) {
m_deref_valobj = new ValueObjectChild(
*this, child_compiler_type, child_name, child_byte_size,
child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
- child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid,
- language_flags);
+ child_is_base_class, true, eAddressTypeInvalid, language_flags);
}
// In case of incomplete child compiler type, use the pointee type and try
@@ -2910,12 +2909,11 @@ ValueObjectSP ValueObject::Dereference(Status &error) {
m_deref_valobj = new ValueObjectChild(
*this, child_compiler_type, child_name, child_byte_size,
child_byte_offset, child_bitfield_bit_size,
- child_bitfield_bit_offset, child_is_base_class,
- child_is_deref_of_parent, eAddressTypeInvalid, language_flags);
+ child_bitfield_bit_offset, child_is_base_class, true,
+ eAddressTypeInvalid, language_flags);
}
}
}
-
} else if (HasSyntheticValue()) {
m_deref_valobj =
GetSyntheticValue()->GetChildMemberWithName("$$dereference$$").get();
@@ -2930,13 +2928,13 @@ ValueObjectSP ValueObject::Dereference(Status &error) {
StreamString strm;
GetExpressionPath(strm);
- if (is_pointer_or_reference_type)
+ if (deref_error.empty())
error = Status::FromErrorStringWithFormat(
"dereference failed: (%s) %s",
GetTypeName().AsCString("<invalid type>"), strm.GetData());
else
error = Status::FromErrorStringWithFormat(
- "not a pointer or reference type: (%s) %s",
+ "dereference failed: %s: (%s) %s", deref_error.c_str(),
GetTypeName().AsCString("<invalid type>"), strm.GetData());
return ValueObjectSP();
}
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py
index 7dc656a7ae225..8f36edea7d727 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py
@@ -88,7 +88,7 @@ def cleanup():
self.expect(
"frame variable *number_not_engaged",
error=True,
- substrs=["not a pointer or reference type"],
+ substrs=["dereference failed: not a"],
)
@add_test_categories(["libc++"])
``````````
</details>
https://github.com/llvm/llvm-project/pull/135843
More information about the lldb-commits
mailing list