mib updated this revision to Diff 262823.
mib edited the summary of this revision.
mib added a comment.
- Added a virtual method to create an empty struct type
`TypeSystem::GetEmptyStructType` (if someone can think of a better name, I'm
open to suggestions)
- Refactored `ValueObject::Dereference`
- Reverted the NFC changes in `ValueObject::CreateChildAtIndex`
- Added test for C++ incomplete type with data-formatter (WIP)
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D79554/new/
https://reviews.llvm.org/D79554
Files:
lldb/include/lldb/Symbol/TypeSystem.h
lldb/source/Core/ValueObject.cpp
lldb/source/Plugins/Language/ObjC/NSSet.cpp
lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
lldb/source/Symbol/TypeSystem.cpp
lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py
lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m
lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/Makefile
lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/TestDataFormatterOpaquePtr.py
lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/main.cpp
lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/opaque_ptr.cc
lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/opaque_ptr.h
lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/opaque_ptr.py
Index: lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/opaque_ptr.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/opaque_ptr.py
@@ -0,0 +1,42 @@
+import lldb
+import lldb.formatters
+import lldb.formatters.synth as synth
+
+def ReadOpaquePointerAddress(var):
+ error = lldb.SBError()
+
+ ptr = var.GetChildMemberWithName('pImpl')
+
+ if not ptr or not ptr.IsValid():
+ error.SetErrorString('Invalid pointer.')
+ return error, None
+
+ return error, ptr.GetValue()
+
+def ReadOpaquePointerValue(var):
+ error = lldb.SBError()
+
+ ptr = var.GetChildAtIndex(0)
+
+ if not ptr or not ptr.IsValid():
+ error.SetErrorString('Invalid pointer.')
+ return error, None
+
+ return error, ptr.GetValue;
+
+def OpaquePtrSummaryProvider(value, _):
+ error, addr = ReadOpaquePointerAddress(value)
+ if error.Fail():
+ return "{} has no value!".format(addr)
+ return "{} contains a value!".format(addr)
+
+class OpaquePtrSyntheticChildProvider(synth.PythonObjectSyntheticChildProvider):
+ def __init__(self, value, dict):
+ synth.PythonObjectSyntheticChildProvider.__init__(self, value, dict)
+
+ def make_children(self):
+ error, value = ReadOpaquePointerValue(self.value)
+
+ if error.Fail():
+ return []
+ return [('value', value)]
Index: lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/opaque_ptr.h
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/opaque_ptr.h
@@ -0,0 +1,8 @@
+class Opaque {
+ class Impl;
+ Impl *pImpl;
+
+public:
+ Opaque(int);
+ ~Opaque();
+};
Index: lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/opaque_ptr.cc
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/opaque_ptr.cc
@@ -0,0 +1,9 @@
+#include "opaque_ptr.h"
+
+class Opaque::Impl {
+ int value; // private data
+public:
+ Impl(int value) : value(value) {}
+};
+Opaque::Opaque(int value) : pImpl{new Impl(value)} {}
+Opaque::~Opaque() = default;
Index: lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/main.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/main.cpp
@@ -0,0 +1,9 @@
+#include "opaque_ptr.h"
+
+typedef Opaque *OpaquePtr;
+
+int main() {
+ Opaque base(7);
+ OpaquePtr ptr = &base;
+ return 0; // Set breakpoint here.
+}
Index: lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/TestDataFormatterOpaquePtr.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/TestDataFormatterOpaquePtr.py
@@ -0,0 +1,51 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class OpaquePtrDataFormatterTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ # Find the line number to break at.
+ self.line = line_number('main.cpp', '// Set breakpoint here.')
+
+ # FIXME: Still need some adjustements (WIP)
+ @expectedFailureAll()
+ def test_with_run_command(self):
+ """Test that that file and class static variables display correctly."""
+ self.build()
+# self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
+
+ self.build()
+ lldbutil.run_to_line_breakpoint(self, lldb.SBFileSpec(self.source),
+ self.line)
+
+ # This is the function to remove the custom formats in order to have a
+ # clean slate for the next test case.
+ def cleanup():
+ self.runCmd('type format clear', check=False)
+ self.runCmd('type summary clear', check=False)
+
+ # Execute the cleanup function during test case tear down.
+ self.addTearDownHook(cleanup)
+
+ self.runCmd("command script import opaque_ptr.py")
+
+ self.runCmd("type summary add Opaque --python-function opaque_ptr.OpaquePtrSummaryProvider -C no")
+ self.runCmd("type summary add OpaqueRef --python-function opaque_ptr.OpaquePtrSummaryProvider")
+ self.runCmd("type synthetic add Opaque* --python-class opaque_ptr.OpaquePtrSyntheticChildProvider")
+# self.runCmd("type summary add Opaque --python-function opaque_ptr.OpaquePtrSummaryProvider -C no")
+
+ self.expect("frame variable base", substrs=['contains a value!'])
+ self.expect("frame variable ptr", substrs=['contains a value!'])
Index: lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/data-formatter/data-formatter-opaque-ptr/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
Index: lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m
===================================================================
--- lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m
+++ lldb/test/API/functionalities/data-formatter/data-formatter-objc/main.m
@@ -482,8 +482,7 @@
CFDictionaryCreate(nil, (void *)cfKeys, (void *)cfValues, 2, nil, nil));
NSDictionary *nscfDictionary = CFBridgingRelease(
CFDictionaryCreate(nil, (void *)cfKeys, (void *)cfValues, 4, nil, nil));
- CFDictionaryRef cfDictionaryRef =
- CFDictionaryCreate(nil, (void *)cfKeys, (void *)cfValues, 3, nil, nil);
+ CFDictionaryRef cfDictionaryRef = (__bridge CFDictionaryRef)nsDictionary;
NSAttributedString *attrString =
[[NSAttributedString alloc] initWithString:@"hello world from foo"
@@ -542,6 +541,7 @@
[nsmutableset addObject:str4];
NSSet *nscfSet =
CFBridgingRelease(CFSetCreate(nil, (void *)cfValues, 2, nil));
+ CFSetRef cfSetRef = (__bridge CFSetRef)nscfSet;
CFDataRef data_ref =
CFDataCreate(kCFAllocatorDefault, [immutableData bytes], 5);
Index: lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py
===================================================================
--- lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py
+++ lldb/test/API/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSContainer.py
@@ -32,7 +32,7 @@
'(NSDictionary *) nscfDictionary = ',
' 4 key/value pairs',
'(CFDictionaryRef) cfDictionaryRef = ',
- ' 3 key/value pairs',
+ ' 2 key/value pairs',
'(NSDictionary *) newMutableDictionary = ',
' 21 key/value pairs',
'(CFArrayRef) cfarray_ref = ',
@@ -57,10 +57,23 @@
self.expect(
- 'frame var nscfSet',
+ 'frame variable -d run-target *cfDictionaryRef',
+ patterns=[
+ '\(CFDictionaryRef\) \*cfDictionaryRef =',
+ 'key = 0x.* @"foo"',
+ 'value = 0x.* @"foo"',
+ 'key = 0x.* @"bar"',
+ 'value = 0x.* @"bar"',
+ ])
+
+
+ self.expect(
+ 'frame var nscfSet cfSetRef',
substrs=[
'(NSSet *) nscfSet = ',
'2 elements',
+ '(CFSetRef) cfSetRef = ',
+ '2 elements',
])
self.expect(
@@ -71,6 +84,14 @@
'\[1\] = 0x.* @".*"',
])
+ self.expect(
+ 'frame variable -d run-target *cfSetRef',
+ patterns=[
+ '\(CFSetRef\) \*cfSetRef =',
+ '\[0\] = 0x.* @".*"',
+ '\[1\] = 0x.* @".*"',
+ ])
+
self.expect(
'frame variable iset1 iset2 imset',
substrs=['4 indexes', '512 indexes', '10 indexes'])
Index: lldb/source/Symbol/TypeSystem.cpp
===================================================================
--- lldb/source/Symbol/TypeSystem.cpp
+++ lldb/source/Symbol/TypeSystem.cpp
@@ -97,6 +97,10 @@
return CompilerType();
}
+CompilerType TypeSystem::GetEmptyStructType(ConstString type_name) {
+ return CompilerType();
+}
+
CompilerType TypeSystem::AddConstModifier(lldb::opaque_compiler_type_t type) {
return CompilerType();
}
Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
===================================================================
--- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -729,6 +729,8 @@
CompilerType GetAtomicType(lldb::opaque_compiler_type_t type) override;
+ CompilerType GetEmptyStructType(ConstString type_name) override;
+
CompilerType AddConstModifier(lldb::opaque_compiler_type_t type) override;
CompilerType AddVolatileModifier(lldb::opaque_compiler_type_t type) override;
Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
===================================================================
--- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -4445,6 +4445,23 @@
return GetType(getASTContext().getAtomicType(GetQualType(type)));
}
+CompilerType TypeSystemClang::GetEmptyStructType(ConstString type_name) {
+ if (type_name.IsEmpty())
+ return CompilerType();
+
+ CompilerType empty_struct_type = CreateRecordType(
+ nullptr, OptionalClangModuleID(), lldb::eAccessPublic,
+ type_name.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC);
+
+ if (!empty_struct_type)
+ return CompilerType();
+
+ StartTagDeclarationDefinition(empty_struct_type);
+ CompleteTagDeclarationDefinition(empty_struct_type);
+
+ return empty_struct_type;
+}
+
CompilerType
TypeSystemClang::AddConstModifier(lldb::opaque_compiler_type_t type) {
if (type) {
Index: lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
===================================================================
--- lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -610,6 +610,10 @@
lldb_private::formatters::NSSetSyntheticFrontEndCreator,
"__NSCFSet synthetic children", ConstString("__NSCFSet"),
ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp,
+ lldb_private::formatters::NSSetSyntheticFrontEndCreator,
+ "CFSetRef synthetic children", ConstString("CFSetRef"),
+ ScriptedSyntheticChildren::Flags());
AddCXXSynthetic(
objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator,
Index: lldb/source/Plugins/Language/ObjC/NSSet.cpp
===================================================================
--- lldb/source/Plugins/Language/ObjC/NSSet.cpp
+++ lldb/source/Plugins/Language/ObjC/NSSet.cpp
@@ -282,6 +282,7 @@
static const ConstString g_OrderedSetI("__NSOrderedSetI");
static const ConstString g_SetM("__NSSetM");
static const ConstString g_SetCF("__NSCFSet");
+ static const ConstString g_SetCFRef("CFSetRef");
if (class_name.IsEmpty())
return false;
@@ -306,7 +307,7 @@
}
if (error.Fail())
return false;
- } else if (class_name == g_SetCF) {
+ } else if (class_name == g_SetCF || class_name == g_SetCFRef) {
ExecutionContext exe_ctx(process_sp);
CFBasicHash cfbh;
if (!cfbh.Update(valobj_addr, exe_ctx))
@@ -367,6 +368,7 @@
static const ConstString g_OrderedSetI("__NSOrderedSetI");
static const ConstString g_SetM("__NSSetM");
static const ConstString g_SetCF("__NSCFSet");
+ static const ConstString g_SetCFRef("CFSetRef");
if (class_name.IsEmpty())
return nullptr;
@@ -386,7 +388,7 @@
} else {
return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp));
}
- } else if (class_name == g_SetCF) {
+ } else if (class_name == g_SetCF || class_name == g_SetCFRef) {
return (new NSCFSetSyntheticFrontEnd(valobj_sp));
} else {
auto &map(NSSet_Additionals::GetAdditionalSynthetics());
Index: lldb/source/Core/ValueObject.cpp
===================================================================
--- lldb/source/Core/ValueObject.cpp
+++ lldb/source/Core/ValueObject.cpp
@@ -687,6 +687,11 @@
language_flags);
}
+ if (!valobj && synthetic_array_member)
+ valobj = GetSyntheticValue()
+ ->GetChildAtIndex(synthetic_index, synthetic_array_member)
+ .get();
+
return valobj;
}
@@ -2830,6 +2835,35 @@
child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid,
language_flags);
}
+
+ // In case of C opaque pointers, create an empty struct type and try to
+ // recreate a new ValueObjectChild using it.
+ if (!m_deref_valobj) {
+ if (Language::LanguageIsCFamily(GetPreferredDisplayLanguage())) {
+ if (HasSyntheticValue()) {
+ TypeSystem *type_system = compiler_type.GetTypeSystem();
+ if (type_system) {
+
+ child_compiler_type =
+ type_system->GetEmptyStructType(compiler_type.GetTypeName());
+
+ if (child_compiler_type) {
+ 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);
+ }
+ }
+ }
+ }
+ }
+
} else if (HasSyntheticValue()) {
m_deref_valobj =
GetSyntheticValue()
Index: lldb/include/lldb/Symbol/TypeSystem.h
===================================================================
--- lldb/include/lldb/Symbol/TypeSystem.h
+++ lldb/include/lldb/Symbol/TypeSystem.h
@@ -253,6 +253,8 @@
virtual CompilerType GetAtomicType(lldb::opaque_compiler_type_t type);
+ virtual CompilerType GetEmptyStructType(ConstString type_name);
+
virtual CompilerType AddConstModifier(lldb::opaque_compiler_type_t type);
virtual CompilerType AddVolatileModifier(lldb::opaque_compiler_type_t type);
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits