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
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to