From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6565 invoked by alias); 23 Aug 2010 20:13:30 -0000 Received: (qmail 6519 invoked by uid 22791); 23 Aug 2010 20:13:22 -0000 X-SWARE-Spam-Status: No, hits=-6.1 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 23 Aug 2010 20:13:16 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o7NKDEhx025862 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 23 Aug 2010 16:13:15 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o7NKDEbQ016394; Mon, 23 Aug 2010 16:13:14 -0400 Received: from opsy.redhat.com (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id o7NKDCJk001987; Mon, 23 Aug 2010 16:13:13 -0400 Received: by opsy.redhat.com (Postfix, from userid 500) id D6EF63780C2; Mon, 23 Aug 2010 14:13:11 -0600 (MDT) From: Tom Tromey To: gdb-patches@sourceware.org Subject: RFA: fix PR python/11792 Date: Mon, 23 Aug 2010 20:13:00 -0000 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-08/txt/msg00398.txt.bz2 This fixes PR python/11792, which is a feature request asking for a new Value.dynamic_type method. The PR includes a patch (Andre has an assignment via his company), but I've tweaked it here and there and also added docs and a test case. This needs a doc review. Built and regtested on x86-64 (compile farm). Tom 2010-08-23 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-23 Tom Tromey PR python/11792: * gdb.texinfo (Values From Inferior): Document dynamic_type. 2010-08-23 Tom Tromey PR python/11792: * gdb.python/py-value.exp (test_subscript_regression): Add dynamic_type test. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index d7ff5aa..7e9c0c1 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -20737,6 +20737,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 aa18042..0aeea7c 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/gdb.python/py-value.exp b/gdb/testsuite/gdb.python/py-value.exp index 13bce9a..0ecb57c 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"]