[Lldb-commits] [lldb] 3aacd74 - [lldb][TypeSystemClang] Allow arrays to be dereferenced in C/C++. (#135843)
via lldb-commits
lldb-commits at lists.llvm.org
Mon May 12 04:47:02 PDT 2025
Author: Ilia Kuklin
Date: 2025-05-12T16:46:58+05:00
New Revision: 3aacd74594b1f8ab04904d277b6a106c98904b29
URL: https://github.com/llvm/llvm-project/commit/3aacd74594b1f8ab04904d277b6a106c98904b29
DIFF: https://github.com/llvm/llvm-project/commit/3aacd74594b1f8ab04904d277b6a106c98904b29.diff
LOG: [lldb][TypeSystemClang] Allow arrays to be dereferenced in C/C++. (#135843)
Add a function `GetDereferencedType` to `CompilerType` and allow
`TypeSystemClang` to dereference arrays.
Added:
Modified:
lldb/include/lldb/Symbol/CompilerType.h
lldb/include/lldb/Symbol/TypeSystem.h
lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
lldb/source/Symbol/CompilerType.cpp
lldb/source/ValueObject/ValueObject.cpp
lldb/test/API/commands/frame/var-dil/basics/PointerArithmetic/TestFrameVarDILPointerArithmetic.py
lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py
Removed:
################################################################################
diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h
index fdbc2057ac10f..b8badfda92cf3 100644
--- a/lldb/include/lldb/Symbol/CompilerType.h
+++ b/lldb/include/lldb/Symbol/CompilerType.h
@@ -433,6 +433,11 @@ class CompilerType {
CompilerDecl GetStaticFieldWithName(llvm::StringRef name) const;
+ llvm::Expected<CompilerType>
+ GetDereferencedType(ExecutionContext *exe_ctx, std::string &deref_name,
+ uint32_t &deref_byte_size, int32_t &deref_byte_offset,
+ ValueObject *valobj, uint64_t &language_flags) 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 df87fea32b72a..1f1a3ac4bc56b 100644
--- a/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/lldb/include/lldb/Symbol/TypeSystem.h
@@ -364,6 +364,12 @@ class TypeSystem : public PluginInterface,
return CompilerDecl();
}
+ virtual llvm::Expected<CompilerType>
+ GetDereferencedType(lldb::opaque_compiler_type_t type,
+ ExecutionContext *exe_ctx, std::string &deref_name,
+ uint32_t &deref_byte_size, int32_t &deref_byte_offset,
+ ValueObject *valobj, uint64_t &language_flags) = 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 3b286885cc37f..d24f3726b1d25 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -6184,6 +6184,24 @@ 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 &deref_name, uint32_t &deref_byte_size,
+ int32_t &deref_byte_offset, ValueObject *valobj, uint64_t &language_flags) {
+ bool type_valid = IsPointerOrReferenceType(type, nullptr) ||
+ IsArrayType(type, nullptr, nullptr, nullptr);
+ if (!type_valid)
+ return llvm::createStringError("not a pointer, reference or array type");
+ uint32_t child_bitfield_bit_size = 0;
+ uint32_t child_bitfield_bit_offset = 0;
+ bool child_is_base_class;
+ bool child_is_deref_of_parent;
+ return GetChildCompilerTypeAtIndex(
+ type, exe_ctx, 0, false, true, false, deref_name, deref_byte_size,
+ deref_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 93933846d114d..f918cb017f51b 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -889,6 +889,12 @@ 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 &deref_name,
+ uint32_t &deref_byte_size, int32_t &deref_byte_offset,
+ ValueObject *valobj, uint64_t &language_flags) 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 90c4dbf0c6206..dd81fc2361f88 100644
--- a/lldb/source/Symbol/CompilerType.cpp
+++ b/lldb/source/Symbol/CompilerType.cpp
@@ -893,6 +893,18 @@ CompilerDecl CompilerType::GetStaticFieldWithName(llvm::StringRef name) const {
return CompilerDecl();
}
+llvm::Expected<CompilerType> CompilerType::GetDereferencedType(
+ ExecutionContext *exe_ctx, std::string &deref_name,
+ uint32_t &deref_byte_size, int32_t &deref_byte_offset, ValueObject *valobj,
+ uint64_t &language_flags) const {
+ if (IsValid())
+ if (auto type_system_sp = GetTypeSystem())
+ return type_system_sp->GetDereferencedType(
+ m_type, exe_ctx, deref_name, deref_byte_size, deref_byte_offset,
+ valobj, language_flags);
+ 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 e1c66763ff0b8..6f0fe9a5b83f9 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -2794,74 +2794,60 @@ 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 deref_name_str;
+ uint32_t deref_byte_size = 0;
+ int32_t deref_byte_offset = 0;
+ CompilerType compiler_type = GetCompilerType();
+ uint64_t language_flags = 0;
- 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)
- LLDB_LOG_ERROR(GetLog(LLDBLog::Types),
- child_compiler_type_or_err.takeError(),
- "could not find child: {0}");
- else
- child_compiler_type = *child_compiler_type_or_err;
-
- if (child_compiler_type && child_byte_size) {
- ConstString child_name;
- if (!child_name_str.empty())
- child_name.SetCString(child_name_str.c_str());
-
- 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);
+ CompilerType deref_compiler_type;
+ auto deref_compiler_type_or_err = compiler_type.GetDereferencedType(
+ &exe_ctx, deref_name_str, deref_byte_size, deref_byte_offset, this,
+ language_flags);
+
+ std::string deref_error;
+ if (deref_compiler_type_or_err) {
+ deref_compiler_type = *deref_compiler_type_or_err;
+ if (deref_compiler_type && deref_byte_size) {
+ ConstString deref_name;
+ if (!deref_name_str.empty())
+ deref_name.SetCString(deref_name_str.c_str());
+
+ m_deref_valobj =
+ new ValueObjectChild(*this, deref_compiler_type, deref_name,
+ deref_byte_size, deref_byte_offset, 0, 0, false,
+ true, eAddressTypeInvalid, language_flags);
}
- // In case of incomplete child compiler type, use the pointee type and try
+ // In case of incomplete deref compiler type, use the pointee type and try
// to recreate a new ValueObjectChild using it.
if (!m_deref_valobj) {
// FIXME(#59012): C++ stdlib formatters break with incomplete types (e.g.
// `std::vector<int> &`). Remove ObjC restriction once that's resolved.
if (Language::LanguageIsObjC(GetPreferredDisplayLanguage()) &&
HasSyntheticValue()) {
- child_compiler_type = compiler_type.GetPointeeType();
+ deref_compiler_type = compiler_type.GetPointeeType();
- if (child_compiler_type) {
- ConstString child_name;
- if (!child_name_str.empty())
- child_name.SetCString(child_name_str.c_str());
+ if (deref_compiler_type) {
+ ConstString deref_name;
+ if (!deref_name_str.empty())
+ deref_name.SetCString(deref_name_str.c_str());
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);
+ *this, deref_compiler_type, deref_name, deref_byte_size,
+ deref_byte_offset, 0, 0, false, true, eAddressTypeInvalid,
+ language_flags);
}
}
}
-
- } else if (IsSynthetic()) {
- m_deref_valobj = GetChildMemberWithName("$$dereference$$").get();
+ } else {
+ deref_error = llvm::toString(deref_compiler_type_or_err.takeError());
+ LLDB_LOG(GetLog(LLDBLog::Types), "could not find child: {0}", deref_error);
+ if (IsSynthetic()) {
+ m_deref_valobj = GetChildMemberWithName("$$dereference$$").get();
+ }
}
if (m_deref_valobj) {
@@ -2871,13 +2857,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/commands/frame/var-dil/basics/PointerArithmetic/TestFrameVarDILPointerArithmetic.py b/lldb/test/API/commands/frame/var-dil/basics/PointerArithmetic/TestFrameVarDILPointerArithmetic.py
index d36c5fce6d43d..6753f988c4187 100644
--- a/lldb/test/API/commands/frame/var-dil/basics/PointerArithmetic/TestFrameVarDILPointerArithmetic.py
+++ b/lldb/test/API/commands/frame/var-dil/basics/PointerArithmetic/TestFrameVarDILPointerArithmetic.py
@@ -33,11 +33,7 @@ def test_dereference(self):
self.expect_var_path("*offset_pref", True, type="int *")
self.expect_var_path("**pp_int0", value="0")
self.expect_var_path("&**pp_int0", type="int *")
- self.expect(
- "frame var '*array'",
- error=True,
- substrs=["not a pointer or reference type"],
- )
+ self.expect_var_path("*array", value="0")
self.expect(
"frame var '&*p_null'",
error=True,
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..99d79a9f125b1 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 pointer, reference or array type"],
)
@add_test_categories(["libc++"])
More information about the lldb-commits
mailing list