[Patch] PR python/15464 and python/16113

Siva Chandra sivachandra@google.com
Fri Dec 27 22:38:00 GMT 2013


I was not aware of "unnamed fields" until I saw Tom's update to 15464
today. Playing with them and my previous patch for 16113, I realized
that my patch does not handle unnamed fields thoroughly. It does
however work for the example posted with the 15464 report.

[I probably would have looked up unnamed fields when working on my
earlier patch, but the documentation for gdb.Field.name only says
this: "The name of the field, or None for anonymous fields." I know
anonymous fields exist in Go, and they show up with a name behind the
scenes. Hence, I considered the documentation to be incorrect. I had
made a note to ask about this or fix this, but missed getting back to
it.]

Unnamed fields have a name equal to an empty string (""). Hence, if
there were only one unnamed field, my previous patch works as it looks
up a field by name. It fails when there are more than one unnamed
fields. The attached patch fixes this by looking up unnamed fields
using 'bitpos' instead of the field name.

2013-12-27  Siva Chandra Reddy  <sivachandra@google.com>

        PR python/15464
        PR python/16133
        * valops.c (value_struct_elt_bitpos): New function
        * python/py-value.c (valpy_getitem): Use 'bitpos' attribute to
        look for a field when 'name' is 'None' or empty.

        testsuite/
        * gdb.python/py-value-cc.cc: Enhance test case.
        * gdb.python/py-value-cc.exp: Add new tests.
-------------- next part --------------
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 87701b4..5c9c003 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@
+2013-12-27  Siva Chandra Reddy  <sivachandra@google.com>
+
+	PR python/15464
+	PR python/16133
+	* valops.c (value_struct_elt_bitpos): New function
+	* python/py-value.c (valpy_getitem): Use 'bitpos' attribute to
+	look for a field when 'name' is 'None' or empty.
+
 2013-12-23  Sterling Augustine  <saugustine@google.com>
 
 	* linespec.c (add_sal_to_sals): Use "<unknown>" when a symbol
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index df25179..60a916d 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -573,6 +573,7 @@ valpy_getitem (PyObject *self, PyObject *key)
   value_object *self_value = (value_object *) self;
   char *field = NULL;
   PyObject *base_class_type_object = NULL;
+  long bitpos = -1;
   volatile struct gdb_exception except;
   PyObject *result = NULL;
 
@@ -614,10 +615,40 @@ valpy_getitem (PyObject *self, PyObject *key)
 	  if (name_obj == NULL)
 	    return NULL;
 
-	  field = python_string_to_host_string (name_obj);
-	  Py_DECREF (name_obj);
-	  if (field == NULL)
-	    return NULL;
+	  if (name_obj != Py_None)
+	    {
+	      field = python_string_to_host_string (name_obj);
+	      Py_DECREF (name_obj);
+	      name_obj = NULL;
+	      if (field == NULL)
+		return NULL;
+	    }
+
+	  if (name_obj == Py_None || field[0] == '\0')
+	    {
+	      PyObject *bitpos_obj;
+	      int valid;
+
+	      Py_XDECREF (name_obj); /* We do not need NAME_OBJ anymore.  */
+
+	      if (!PyObject_HasAttrString (key, "bitpos"))
+		{
+		  xfree (field);
+		  PyErr_SetString (PyExc_AttributeError,
+				   _("gdb.Field object has no name and no "
+                                     "'bitpos' attribute."));
+
+		  return NULL;
+		}
+	      bitpos_obj = PyObject_GetAttrString (key, "bitpos");
+	      if (bitpos_obj == NULL)
+		return NULL;
+
+	      valid = gdb_py_int_as_long (bitpos_obj, &bitpos);
+	      Py_DECREF (bitpos_obj);
+	      if (!valid)
+		return NULL;
+	    }
 	}
     }
 
@@ -627,7 +658,9 @@ valpy_getitem (PyObject *self, PyObject *key)
       struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
       struct value *res_val = NULL;
 
-      if (field)
+      if (bitpos >= 0)
+	res_val = value_struct_elt_bitpos (&tmp, bitpos, "struct/class/union");
+      else if (field)
 	res_val = value_struct_elt (&tmp, NULL, field, 0, NULL);
       else if (base_class_type_object != NULL)
 	{
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 97ad49b..4502a3c 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2013-12-27  Siva Chandra Reddy  <sivachandra@google.com>
+
+	PR python/15464
+	PR python/16133
+	* gdb.python/py-value-cc.cc: Enhance test case.
+	* gdb.python/py-value-cc.exp: Add new tests.
+
 2013-12-19  Sergio Durigan Junior  <sergiodj@redhat.com>
 
 	PR breakpoints/16297
diff --git a/gdb/testsuite/gdb.python/py-value-cc.cc b/gdb/testsuite/gdb.python/py-value-cc.cc
index 80094ec..8b9aa5a 100644
--- a/gdb/testsuite/gdb.python/py-value-cc.cc
+++ b/gdb/testsuite/gdb.python/py-value-cc.cc
@@ -30,8 +30,15 @@ class B : public A {
   char a;
 };
 
+struct X
+{
+  union { int x; char y; };
+  union { int a; char b; };
+};
+
 typedef B Btd;
 typedef int *int_ptr;
+typedef X Xtd;
 
 int
 func (const A &a)
@@ -57,6 +64,13 @@ func (const A &a)
   U u;
   u.a = 99;
 
+  X x;
+  x.x = 101;
+  x.a = 102;
+
+  X *x_ptr = &x;
+  Xtd *xtd = &x;
+
   return 0; /* Break here.  */
 }
 
diff --git a/gdb/testsuite/gdb.python/py-value-cc.exp b/gdb/testsuite/gdb.python/py-value-cc.exp
index eacaf2e..08dc462 100644
--- a/gdb/testsuite/gdb.python/py-value-cc.exp
+++ b/gdb/testsuite/gdb.python/py-value-cc.exp
@@ -53,6 +53,12 @@ gdb_test_no_output "python b_ref = gdb.parse_and_eval('b_ref')" "init b_ref"
 gdb_test_no_output "python b_td = gdb.parse_and_eval('b_td')" "init b_td"
 gdb_test_no_output "python u = gdb.parse_and_eval('u')" "init u"
 gdb_test_no_output "python u_fields = u.type.fields()" "init u_fields"
+gdb_test_no_output "python x = gdb.parse_and_eval('x')" "init x"
+gdb_test_no_output "python x_fields = x.type.fields()" "init x_fields"
+gdb_test_no_output "python x_ptr = gdb.parse_and_eval('x_ptr')" "init x_ptr"
+gdb_test_no_output "python xtd = gdb.parse_and_eval('xtd')" "init xtd"
+
+gdb_test "python print(b\[b_fields\[1\]\])" "97 'a'" "b.a via field"
 
 gdb_test "python print(b\[b_fields\[1\]\])" "97 'a'" "b.a via field"
 gdb_test "python print(b\[b_fields\[0\]\].type)" "A" \
@@ -79,3 +85,11 @@ gdb_test "python print(b_td\[b_fields\[0\]\]\['a'\])" "100" \
 
 gdb_test "python print(u\[u_fields\[0\]\])" "99.*" "u's first field via field"
 gdb_test "python print(u\[u_fields\[1\]\])" "99.*" "u's second field via field"
+
+gdb_test "python print len(x_fields)" "2" "number for fields in u"
+gdb_test "python print x\[x_fields\[0\]\]\['x'\]" "101" "x.x via field"
+gdb_test "python print x\[x_fields\[1\]\]\['a'\]" "102" "x.a via field"
+gdb_test "python print x_ptr\[x_fields\[0\]\]\['x'\]" "101" "x_ptr->x via field"
+gdb_test "python print x_ptr\[x_fields\[1\]\]\['a'\]" "102" "x_ptr->a via field"
+gdb_test "python print xtd\[x_fields\[0\]\]\['x'\]" "101" "xtd->x via field"
+gdb_test "python print xtd\[x_fields\[1\]\]\['a'\]" "102" "xtd->a via field"
diff --git a/gdb/valops.c b/gdb/valops.c
index d43c758..f147854 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -2248,6 +2248,49 @@ value_struct_elt (struct value **argp, struct value **args,
   return v;
 }
 
+/* Given *ARGP, a value of type structure or union, or a pointer/reference
+   to a structure or union, extract and return its component (field) at the
+   specified BITPOS.
+   Returns NULL if BITPOS is invalid.  */
+
+struct value *
+value_struct_elt_bitpos (struct value **argp, int bitpos, const char *err)
+{
+  struct type *t;
+  struct value *v;
+  int i;
+  int nbases;
+
+  *argp = coerce_array (*argp);
+
+  t = check_typedef (value_type (*argp));
+
+  while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
+    {
+      *argp = value_ind (*argp);
+      if (TYPE_CODE (check_typedef (value_type (*argp))) != TYPE_CODE_FUNC)
+	*argp = coerce_array (*argp);
+      t = check_typedef (value_type (*argp));
+    }
+
+  if (TYPE_CODE (t) != TYPE_CODE_STRUCT
+      && TYPE_CODE (t) != TYPE_CODE_UNION)
+    error (_("Attempt to extract a component of a value that is not a %s."),
+	   err);
+
+  for (i = TYPE_N_BASECLASSES (t); i < TYPE_NFIELDS (t); i++)
+    {
+      if (!field_is_static (&TYPE_FIELD (t, i))
+	  && bitpos == TYPE_FIELD_BITPOS (t, i))
+	return value_primitive_field (*argp, 0, i, t);
+    }
+
+  error (_("Attempt to extract a component with an invalid bitpos."));
+
+  /* Never hit.  */
+  return NULL;
+}
+
 /* Search through the methods of an object (and its bases) to find a
    specified method.  Return the pointer to the fn_field list of
    overloaded instances.
diff --git a/gdb/value.h b/gdb/value.h
index 6b158df..a279803 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -670,6 +670,10 @@ extern struct value *value_struct_elt (struct value **argp,
 				       const char *name, int *static_memfuncp,
 				       const char *err);
 
+extern struct value *value_struct_elt_bitpos (struct value **argp,
+					      int bitpos,
+					      const char *err);
+
 extern struct value *value_aggregate_elt (struct type *curtype,
 					  char *name,
 					  struct type *expect_type,


More information about the Gdb-patches mailing list