[Lldb-commits] [lldb] [lldb] Add lookup by name to SBValue.child (PR #118814)

Dave Lee via lldb-commits lldb-commits at lists.llvm.org
Fri Dec 6 15:13:04 PST 2024


https://github.com/kastiglione updated https://github.com/llvm/llvm-project/pull/118814

>From 639fc6d87345c8d68a822032917102a4225df355 Mon Sep 17 00:00:00 2001
From: Dave Lee <davelee.com at gmail.com>
Date: Wed, 4 Dec 2024 14:37:24 -0800
Subject: [PATCH 1/4] [lldb] Add lookup by name to SBValue.child

---
 lldb/bindings/interface/SBValueExtensions.i    | 6 ++++--
 lldb/test/API/python_api/value/TestValueAPI.py | 8 +++-----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/lldb/bindings/interface/SBValueExtensions.i b/lldb/bindings/interface/SBValueExtensions.i
index bee9c27775d453..f743b8b9bc786f 100644
--- a/lldb/bindings/interface/SBValueExtensions.i
+++ b/lldb/bindings/interface/SBValueExtensions.i
@@ -7,7 +7,7 @@ STRING_EXTENSION_OUTSIDE(SBValue)
             return self.GetDynamicValue (eDynamicCanRunTarget)
 
         class children_access(object):
-            '''A helper object that will lazily hand out thread for a process when supplied an index.'''
+            '''A helper object that will lazily hand out child values when supplied an index or name.'''
 
             def __init__(self, sbvalue):
                 self.sbvalue = sbvalue
@@ -23,6 +23,8 @@ STRING_EXTENSION_OUTSIDE(SBValue)
                     if -count <= key < count:
                         key %= count
                         return self.sbvalue.GetChildAtIndex(key)
+                elif isinstance(key, str):
+                    return self.sbvalue.GetChildMemberWithName(key)
                 return None
 
         def get_child_access_object(self):
@@ -49,7 +51,7 @@ STRING_EXTENSION_OUTSIDE(SBValue)
             return self.GetNumChildren()
 
         children = property(get_value_child_list, None, doc='''A read only property that returns a list() of lldb.SBValue objects for the children of the value.''')
-        child = property(get_child_access_object, None, doc='''A read only property that returns an object that can access children of a variable by index (child_value = value.children[12]).''')
+        child = property(get_child_access_object, None, doc='''A read only property that returns an object that can access children of a variable by index or by name.''')
         name = property(GetName, None, doc='''A read only property that returns the name of this value as a string.''')
         type = property(GetType, None, doc='''A read only property that returns a lldb.SBType object that represents the type for this value.''')
         size = property(GetByteSize, None, doc='''A read only property that returns the size in bytes of this value.''')
diff --git a/lldb/test/API/python_api/value/TestValueAPI.py b/lldb/test/API/python_api/value/TestValueAPI.py
index 512100912d6fe7..eb6dbfe6362a43 100644
--- a/lldb/test/API/python_api/value/TestValueAPI.py
+++ b/lldb/test/API/python_api/value/TestValueAPI.py
@@ -140,10 +140,8 @@ def test(self):
         val_i = target.EvaluateExpression("i")
         val_s = target.EvaluateExpression("s")
         val_a = target.EvaluateExpression("a")
-        self.assertTrue(
-            val_s.GetChildMemberWithName("a").GetAddress().IsValid(), VALID_VARIABLE
-        )
-        self.assertTrue(val_s.GetChildMemberWithName("a").AddressOf(), VALID_VARIABLE)
+        self.assertTrue(val_s.child["a"].GetAddress().IsValid(), VALID_VARIABLE)
+        self.assertTrue(val_s.child["a"].AddressOf(), VALID_VARIABLE)
         self.assertTrue(val_a.Cast(val_i.GetType()).AddressOf(), VALID_VARIABLE)
 
         # Test some other cases of the Cast API.  We allow casts from one struct type
@@ -210,7 +208,7 @@ def test(self):
         weird_cast = f_var.Cast(val_s.GetType())
         self.assertSuccess(weird_cast.GetError(), "Can cast from a larger to a smaller")
         self.assertEqual(
-            weird_cast.GetChildMemberWithName("a").GetValueAsSigned(0),
+            weird_cast.child["a"].GetValueAsSigned(0),
             33,
             "Got the right value",
         )

>From c6f926b0e451f87af8c14baed3de55f4cb4240d5 Mon Sep 17 00:00:00 2001
From: Dave Lee <davelee.com at gmail.com>
Date: Thu, 5 Dec 2024 13:04:20 -0800
Subject: [PATCH 2/4] Support base class children

---
 lldb/bindings/interface/SBValueExtensions.i | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/lldb/bindings/interface/SBValueExtensions.i b/lldb/bindings/interface/SBValueExtensions.i
index f743b8b9bc786f..c813de6c65c5c6 100644
--- a/lldb/bindings/interface/SBValueExtensions.i
+++ b/lldb/bindings/interface/SBValueExtensions.i
@@ -24,7 +24,12 @@ STRING_EXTENSION_OUTSIDE(SBValue)
                         key %= count
                         return self.sbvalue.GetChildAtIndex(key)
                 elif isinstance(key, str):
-                    return self.sbvalue.GetChildMemberWithName(key)
+                    if child := self.sbvalue.GetChildMemberWithName(key)
+                        return child
+                    # Support base classes, which are children but not members.
+                    for child in self.sbvalue:
+                        if child.name == key:
+                            return child
                 return None
 
         def get_child_access_object(self):

>From 7e2c554d69473dee6f01438d783508a70120d47a Mon Sep 17 00:00:00 2001
From: Dave Lee <davelee.com at gmail.com>
Date: Thu, 5 Dec 2024 13:10:55 -0800
Subject: [PATCH 3/4] Add missing colon

---
 lldb/bindings/interface/SBValueExtensions.i | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lldb/bindings/interface/SBValueExtensions.i b/lldb/bindings/interface/SBValueExtensions.i
index c813de6c65c5c6..93ec055d4560eb 100644
--- a/lldb/bindings/interface/SBValueExtensions.i
+++ b/lldb/bindings/interface/SBValueExtensions.i
@@ -24,7 +24,7 @@ STRING_EXTENSION_OUTSIDE(SBValue)
                         key %= count
                         return self.sbvalue.GetChildAtIndex(key)
                 elif isinstance(key, str):
-                    if child := self.sbvalue.GetChildMemberWithName(key)
+                    if child := self.sbvalue.GetChildMemberWithName(key):
                         return child
                     # Support base classes, which are children but not members.
                     for child in self.sbvalue:

>From 174b562fc604c42d8fe559fc797ea2c8fc1a802e Mon Sep 17 00:00:00 2001
From: Dave Lee <davelee.com at gmail.com>
Date: Fri, 6 Dec 2024 15:12:33 -0800
Subject: [PATCH 4/4] Introduce member property which looks up members by name

---
 lldb/bindings/interface/SBValueExtensions.i   | 25 ++++++++++++-------
 .../test/API/python_api/value/TestValueAPI.py |  6 ++---
 2 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/lldb/bindings/interface/SBValueExtensions.i b/lldb/bindings/interface/SBValueExtensions.i
index 93ec055d4560eb..9b2f7c809d7231 100644
--- a/lldb/bindings/interface/SBValueExtensions.i
+++ b/lldb/bindings/interface/SBValueExtensions.i
@@ -7,7 +7,7 @@ STRING_EXTENSION_OUTSIDE(SBValue)
             return self.GetDynamicValue (eDynamicCanRunTarget)
 
         class children_access(object):
-            '''A helper object that will lazily hand out child values when supplied an index or name.'''
+            '''A helper object that will lazily hand out child values when supplied an index.'''
 
             def __init__(self, sbvalue):
                 self.sbvalue = sbvalue
@@ -23,19 +23,25 @@ STRING_EXTENSION_OUTSIDE(SBValue)
                     if -count <= key < count:
                         key %= count
                         return self.sbvalue.GetChildAtIndex(key)
-                elif isinstance(key, str):
-                    if child := self.sbvalue.GetChildMemberWithName(key):
-                        return child
-                    # Support base classes, which are children but not members.
-                    for child in self.sbvalue:
-                        if child.name == key:
-                            return child
                 return None
 
         def get_child_access_object(self):
             '''An accessor function that returns a children_access() object which allows lazy member variable access from a lldb.SBValue object.'''
             return self.children_access (self)
 
+        def get_member_access_object(self):
+            '''An accessor function that returns an interface which provides subscript based lookup of child members.'''
+            class member_access:
+                def __init__(self, valobj):
+                    self.valobj = valobj
+
+                def __getitem__(self, key):
+                    if isinstance(key, str):
+                        return self.valobj.GetChildMemberWithName(key)
+                    raise TypeError("invalid subscript key")
+
+            return member_access(self)
+
         def get_value_child_list(self):
             '''An accessor function that returns a list() that contains all children in a lldb.SBValue object.'''
             children = []
@@ -56,7 +62,8 @@ STRING_EXTENSION_OUTSIDE(SBValue)
             return self.GetNumChildren()
 
         children = property(get_value_child_list, None, doc='''A read only property that returns a list() of lldb.SBValue objects for the children of the value.''')
-        child = property(get_child_access_object, None, doc='''A read only property that returns an object that can access children of a variable by index or by name.''')
+        child = property(get_child_access_object, None, doc='''A read only property that returns an object that can access children of a variable by index (child_value = value.children[12]).''')
+        member = property(get_member_access_object, None, doc='''A read only property that returns an object that can access child members by name.''')
         name = property(GetName, None, doc='''A read only property that returns the name of this value as a string.''')
         type = property(GetType, None, doc='''A read only property that returns a lldb.SBType object that represents the type for this value.''')
         size = property(GetByteSize, None, doc='''A read only property that returns the size in bytes of this value.''')
diff --git a/lldb/test/API/python_api/value/TestValueAPI.py b/lldb/test/API/python_api/value/TestValueAPI.py
index eb6dbfe6362a43..9eaf2c994d8463 100644
--- a/lldb/test/API/python_api/value/TestValueAPI.py
+++ b/lldb/test/API/python_api/value/TestValueAPI.py
@@ -140,8 +140,8 @@ def test(self):
         val_i = target.EvaluateExpression("i")
         val_s = target.EvaluateExpression("s")
         val_a = target.EvaluateExpression("a")
-        self.assertTrue(val_s.child["a"].GetAddress().IsValid(), VALID_VARIABLE)
-        self.assertTrue(val_s.child["a"].AddressOf(), VALID_VARIABLE)
+        self.assertTrue(val_s.member["a"].GetAddress().IsValid(), VALID_VARIABLE)
+        self.assertTrue(val_s.member["a"].AddressOf(), VALID_VARIABLE)
         self.assertTrue(val_a.Cast(val_i.GetType()).AddressOf(), VALID_VARIABLE)
 
         # Test some other cases of the Cast API.  We allow casts from one struct type
@@ -208,7 +208,7 @@ def test(self):
         weird_cast = f_var.Cast(val_s.GetType())
         self.assertSuccess(weird_cast.GetError(), "Can cast from a larger to a smaller")
         self.assertEqual(
-            weird_cast.child["a"].GetValueAsSigned(0),
+            weird_cast.member["a"].GetValueAsSigned(0),
             33,
             "Got the right value",
         )



More information about the lldb-commits mailing list