gdb
authorTom Tromey <tromey@redhat.com>
Mon, 30 Aug 2010 20:28:31 +0000 (20:28 +0000)
committerTom Tromey <tromey@redhat.com>
Mon, 30 Aug 2010 20:28:31 +0000 (20:28 +0000)
2010-08-30  Andre Poenitz  <andre.poenitz@nokia.com>
    Tom Tromey  <tromey@redhat.com>

PR python/11792:
* python/py-value.c (valpy_get_dynamic_type): New function.
(value_object_getset): Add "dynamic_type".
(valpy_get_type): Fail on error.
gdb/doc
PR python/11792:
* gdb.texinfo (Values From Inferior): Document dynamic_type.
gdb/testsuite
PR python/11792:
* gdb.python/py-value.exp (test_subscript_regression): Add
dynamic_type test.

gdb/ChangeLog
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/python/py-value.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.python/py-value.exp

index 7312034e52c91706c08340f5df67ac6c513bac4c..102bdb18a62d6a0c57029b48d8494fb55ced2243 100644 (file)
@@ -1,3 +1,11 @@
+2010-08-30  Andre Poenitz  <andre.poenitz@nokia.com>
+           Tom Tromey  <tromey@redhat.com>
+
+       PR python/11792:
+       * python/py-value.c (valpy_get_dynamic_type): New function.
+       (value_object_getset): Add "dynamic_type".
+       (valpy_get_type): Fail on error.
+
 2010-08-30  Yao Qi  <yao@codesourcery.com>
 
        * arm-linux-tdep.c (arm_linux_sigreturn_return_addr): New.
index 634cc9dae01537a1101c15a46ea34127d88c9dc7..ac8f6e9d98502bfbb7f5c792ef5f33ce2bc2ec49 100644 (file)
@@ -1,3 +1,8 @@
+2010-08-30  Tom Tromey  <tromey@redhat.com>
+
+       PR python/11792:
+       * gdb.texinfo (Values From Inferior): Document dynamic_type.
+
 2010-08-24  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * gdb.texinfo (ARM Features): Document
index 3418eb2fc6b6b5c49558e736f730564f66be902a..393c8b7fbf2c52ce1257e56271b2ae2b923f244d 100644 (file)
@@ -20759,6 +20759,16 @@ this value, thus it is not available for fetching from the inferior.
 The type of this @code{gdb.Value}.  The value of this attribute is a
 @code{gdb.Type} object.
 @end defivar
+
+@defivar Value dynamic_type
+The dynamic type of this @code{gdb.Value}.  This uses C@t{++} run-time
+type information to determine the dynamic type of the value.  If this
+value is of class type, it will return the class in which the value is
+embedded, if any.  If this value is of pointer or reference to a class
+type, it will compute the dynamic type of the referenced object, and
+return a pointer or reference to that type, respectively.  In all
+other cases, it will return the value's static type.
+@end defivar
 @end table
 
 The following methods are provided:
index aa180428574a3ae7d4412255442581cea7ef0d03..0aeea7cb5322ac939eb7ce727504b29306b7f616 100644 (file)
@@ -27,6 +27,7 @@
 #include "valprint.h"
 #include "infcall.h"
 #include "expression.h"
+#include "cp-abi.h"
 
 #ifdef HAVE_PYTHON
 
@@ -62,6 +63,7 @@ typedef struct value_object {
   struct value *value;
   PyObject *address;
   PyObject *type;
+  PyObject *dynamic_type;
 } value_object;
 
 /* List of all values which are currently exposed to Python. It is
@@ -101,6 +103,8 @@ valpy_dealloc (PyObject *obj)
       Py_DECREF (self->type);
     }
 
+  Py_XDECREF (self->dynamic_type);
+
   self->ob_type->tp_free (self);
 }
 
@@ -148,6 +152,7 @@ valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords)
   value_incref (value);
   value_obj->address = NULL;
   value_obj->type = NULL;
+  value_obj->dynamic_type = NULL;
   note_value (value_obj);
 
   return (PyObject *) value_obj;
@@ -218,15 +223,78 @@ valpy_get_type (PyObject *self, void *closure)
     {
       obj->type = type_to_type_object (value_type (obj->value));
       if (!obj->type)
-       {
-         obj->type = Py_None;
-         Py_INCREF (obj->type);
-       }
+       return NULL;
     }
   Py_INCREF (obj->type);
   return obj->type;
 }
 
+/* Return dynamic type of the value.  */
+
+static PyObject *
+valpy_get_dynamic_type (PyObject *self, void *closure)
+{
+  value_object *obj = (value_object *) self;
+  volatile struct gdb_exception except;
+  struct type *type = NULL;
+
+  if (obj->dynamic_type != NULL)
+    {
+      Py_INCREF (obj->dynamic_type);
+      return obj->dynamic_type;
+    }
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      struct value *val = obj->value;
+
+      type = value_type (val);
+      CHECK_TYPEDEF (type);
+
+      if (((TYPE_CODE (type) == TYPE_CODE_PTR)
+          || (TYPE_CODE (type) == TYPE_CODE_REF))
+         && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
+       {
+         struct value *target;
+         int was_pointer = TYPE_CODE (type) == TYPE_CODE_PTR;
+
+         target = value_ind (val);
+         type = value_rtti_type (target, NULL, NULL, NULL);
+
+         if (type)
+           {
+             if (was_pointer)
+               type = lookup_pointer_type (type);
+             else
+               type = lookup_reference_type (type);
+           }
+       }
+      else if (TYPE_CODE (type) == TYPE_CODE_CLASS)
+       type = value_rtti_type (val, NULL, NULL, NULL);
+      else
+       {
+         /* Re-use object's static type.  */
+         type = NULL;
+       }
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  if (type == NULL)
+    {
+      /* Ensure that the TYPE field is ready.  */
+      if (!valpy_get_type (self, NULL))
+       return NULL;
+      /* We don't need to incref here, because valpy_get_type already
+        did it for us.  */
+      obj->dynamic_type = obj->type;
+    }
+  else
+    obj->dynamic_type = type_to_type_object (type);
+
+  Py_INCREF (obj->dynamic_type);
+  return obj->dynamic_type;
+}
+
 /* Implementation of gdb.Value.lazy_string ([encoding] [, length]) ->
    string.  Return a PyObject representing a lazy_string_object type.
    A lazy string is a pointer to a string with an optional encoding and
@@ -994,6 +1062,7 @@ value_to_value_object (struct value *val)
       value_incref (val);
       val_obj->address = NULL;
       val_obj->type = NULL;
+      val_obj->dynamic_type = NULL;
       note_value (val_obj);
     }
 
@@ -1169,6 +1238,8 @@ static PyGetSetDef value_object_getset[] = {
     "Boolean telling whether the value is optimized out (i.e., not available).",
     NULL },
   { "type", valpy_get_type, NULL, "Type of the value.", NULL },
+  { "dynamic_type", valpy_get_dynamic_type, NULL,
+    "Dynamic type of the value.", NULL },
   {NULL}  /* Sentinel */
 };
 
index 00c599ac89275f85f82adadbe6b289c6143658a2..433cfa2589d102cecb811f13769b89186c619472 100644 (file)
@@ -1,3 +1,9 @@
+2010-08-30  Tom Tromey  <tromey@redhat.com>
+
+       PR python/11792:
+       * gdb.python/py-value.exp (test_subscript_regression): Add
+       dynamic_type test.
+
 2010-08-30  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * gdb.cp/cpexprs.exp (test_breakpoint): Continue to test_function
index 13bce9a05efb1819723f0681c70aff97d6f6f2d7..0ecb57c66b06bbc4feafb450981fde749c7f7938 100644 (file)
@@ -379,6 +379,13 @@ proc test_subscript_regression {lang} {
      # the C++ tests.
      gdb_test "python print bool(gdb.parse_and_eval('base').dynamic_cast(gdb.lookup_type('Derived').pointer()))" \
         True
+
+     # Likewise.
+     gdb_test "python print gdb.parse_and_eval('base').dynamic_type" \
+        "Derived \[*\]"
+     # A static type case.
+     gdb_test "python print gdb.parse_and_eval('5').dynamic_type" \
+        "int"
  }
 
  gdb_breakpoint [gdb_get_line_number "break to inspect struct and union"]