From 03f17ccfe196bd03d370b5c0d9983b8d8eed12d7 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Mon, 30 Aug 2010 20:28:31 +0000 Subject: [PATCH] gdb 2010-08-30 Andre Poenitz Tom Tromey 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 | 8 +++ gdb/doc/ChangeLog | 5 ++ gdb/doc/gdb.texinfo | 10 ++++ gdb/python/py-value.c | 79 +++++++++++++++++++++++++-- gdb/testsuite/ChangeLog | 6 ++ gdb/testsuite/gdb.python/py-value.exp | 7 +++ 6 files changed, 111 insertions(+), 4 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7312034e52..102bdb18a6 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2010-08-30 Andre Poenitz + Tom Tromey + + 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 * arm-linux-tdep.c (arm_linux_sigreturn_return_addr): New. diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 634cc9dae0..ac8f6e9d98 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2010-08-30 Tom Tromey + + PR python/11792: + * gdb.texinfo (Values From Inferior): Document dynamic_type. + 2010-08-24 Daniel Jacobowitz * gdb.texinfo (ARM Features): Document diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 3418eb2fc6..393c8b7fbf 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -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: diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c index aa18042857..0aeea7cb53 100644 --- a/gdb/python/py-value.c +++ b/gdb/python/py-value.c @@ -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 */ }; diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 00c599ac89..433cfa2589 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2010-08-30 Tom Tromey + + PR python/11792: + * gdb.python/py-value.exp (test_subscript_regression): Add + dynamic_type test. + 2010-08-30 Daniel Jacobowitz * gdb.cp/cpexprs.exp (test_breakpoint): Continue to test_function diff --git a/gdb/testsuite/gdb.python/py-value.exp b/gdb/testsuite/gdb.python/py-value.exp index 13bce9a05e..0ecb57c66b 100644 --- a/gdb/testsuite/gdb.python/py-value.exp +++ b/gdb/testsuite/gdb.python/py-value.exp @@ -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"] -- 2.34.1