From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16678 invoked by alias); 20 Aug 2010 22:41:53 -0000 Received: (qmail 16671 invoked by uid 22791); 20 Aug 2010 22:41:51 -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; Fri, 20 Aug 2010 22:41:43 +0000 Received: from int-mx08.intmail.prod.int.phx2.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o7KMffIo004817 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 20 Aug 2010 18:41:41 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx08.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o7KMffoY000687; Fri, 20 Aug 2010 18:41:41 -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 o7KMfeg3003965; Fri, 20 Aug 2010 18:41:40 -0400 Received: by opsy.redhat.com (Postfix, from userid 500) id 33D7837897B; Fri, 20 Aug 2010 16:41:40 -0600 (MDT) From: Tom Tromey To: gdb-patches@sourceware.org Subject: RFA: fix PR python/11145 Date: Fri, 20 Aug 2010 22:41:00 -0000 Message-ID: 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/msg00380.txt.bz2 PR python/11145 asks for the addition of C++-style cast operators to gdb.Value. I think this is a basically reasonable request, but really only reinterpret_cast and dynamic_cast are needed -- static_cast and const_cast are, I think, already well-handled by Value.cast. This needs a doc review. Built and regtested on x86-64 (compile farm). Tom 2010-08-20 Tom Tromey PR python/11145: * python/py-value.c: Include expression.h. (valpy_do_cast): New function. (valpy_cast): Use it. (valpy_dynamic_cast): New function. (valpy_reinterpret_cast): Likewise. (value_object_methods): Add dynamic_cast, reinterpret_cast. 2010-08-20 Tom Tromey PR python/11145: * gdb.texinfo (Values From Inferior): Document dynamic_cast and reinterpret_cast methods. 2010-08-20 Tom Tromey PR python/11145: * gdb.python/py-value.c (Base, Derived): New types. (base): New global. * gdb.python/py-value.exp (test_subscript_regression): Add dynamic_cast test. gdb/ChangeLog | 10 ++++++ gdb/doc/ChangeLog | 6 ++++ gdb/doc/gdb.texinfo | 10 ++++++ gdb/python/py-value.c | 51 +++++++++++++++++++++++++++++++-- gdb/testsuite/ChangeLog | 8 +++++ gdb/testsuite/gdb.python/py-value.c | 10 ++++++ gdb/testsuite/gdb.python/py-value.exp | 5 +++ 7 files changed, 97 insertions(+), 3 deletions(-) diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 628e147..bde0eb4 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -20770,6 +20770,16 @@ The result @code{bar} will be a @code{gdb.Value} object holding the value pointed to by @code{foo}. @end defmethod +@defmethod Value dynamic_cast type +Like @code{Value.cast}, but works as if the C++ @code{dynamic_cast} +operator were used. Consult a C++ reference for details. +@end defmethod + +@defmethod Value reinterpret_cast type +Like @code{Value.cast}, but works as if the C++ @code{reinterpret_cast} +operator were used. Consult a C++ reference for details. +@end defmethod + @defmethod Value string @r{[}encoding@r{]} @r{[}errors@r{]} @r{[}length@r{]} If this @code{gdb.Value} represents a string, then this method converts the contents to a Python string. Otherwise, this method will diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c index 75ee0de..aa18042 100644 --- a/gdb/python/py-value.c +++ b/gdb/python/py-value.c @@ -26,6 +26,7 @@ #include "dfp.h" #include "valprint.h" #include "infcall.h" +#include "expression.h" #ifdef HAVE_PYTHON @@ -295,9 +296,10 @@ valpy_string (PyObject *self, PyObject *args, PyObject *kw) return unicode; } -/* Cast a value to a given type. */ +/* A helper function that implements the various cast operators. */ + static PyObject * -valpy_cast (PyObject *self, PyObject *args) +valpy_do_cast (PyObject *self, PyObject *args, enum exp_opcode op) { PyObject *type_obj; struct type *type; @@ -317,13 +319,47 @@ valpy_cast (PyObject *self, PyObject *args) TRY_CATCH (except, RETURN_MASK_ALL) { - res_val = value_cast (type, ((value_object *) self)->value); + struct value *val = ((value_object *) self)->value; + + if (op == UNOP_DYNAMIC_CAST) + res_val = value_dynamic_cast (type, val); + else if (op == UNOP_REINTERPRET_CAST) + res_val = value_reinterpret_cast (type, val); + else + { + gdb_assert (op == UNOP_CAST); + res_val = value_cast (type, val); + } } GDB_PY_HANDLE_EXCEPTION (except); return value_to_value_object (res_val); } +/* Implementation of the "cast" method. */ + +static PyObject * +valpy_cast (PyObject *self, PyObject *args) +{ + return valpy_do_cast (self, args, UNOP_CAST); +} + +/* Implementation of the "dynamic_cast" method. */ + +static PyObject * +valpy_dynamic_cast (PyObject *self, PyObject *args) +{ + return valpy_do_cast (self, args, UNOP_DYNAMIC_CAST); +} + +/* Implementation of the "reinterpret_cast" method. */ + +static PyObject * +valpy_reinterpret_cast (PyObject *self, PyObject *args) +{ + return valpy_do_cast (self, args, UNOP_REINTERPRET_CAST); +} + static Py_ssize_t valpy_length (PyObject *self) { @@ -1138,6 +1174,15 @@ static PyGetSetDef value_object_getset[] = { static PyMethodDef value_object_methods[] = { { "cast", valpy_cast, METH_VARARGS, "Cast the value to the supplied type." }, + { "dynamic_cast", valpy_dynamic_cast, METH_VARARGS, + "dynamic_cast (gdb.Type) -> gdb.Value\n\ +Cast the value to the supplied type, as if by the C++ dynamic_cast operator." + }, + { "reinterpret_cast", valpy_reinterpret_cast, METH_VARARGS, + "reinterpret_cast (gdb.Type) -> gdb.Value\n\ +Cast the value to the supplied type, as if by the C++\n\ +reinterpret_cast operator." + }, { "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." }, { "lazy_string", (PyCFunction) valpy_lazy_string, METH_VARARGS | METH_KEYWORDS, "lazy_string ([encoding] [, length]) -> lazy_string\n\ diff --git a/gdb/testsuite/gdb.python/py-value.c b/gdb/testsuite/gdb.python/py-value.c index 7481bd5..5ac7d76 100644 --- a/gdb/testsuite/gdb.python/py-value.c +++ b/gdb/testsuite/gdb.python/py-value.c @@ -40,6 +40,16 @@ typedef struct s *PTR; enum e evalue = TWO; #ifdef __cplusplus + +struct Base { + virtual int x() { return 5; } +}; + +struct Derived : public Base { +}; + +Base *base = new Derived (); + void ptr_ref(int*& rptr_int) { return; /* break to inspect pointer by reference. */ diff --git a/gdb/testsuite/gdb.python/py-value.exp b/gdb/testsuite/gdb.python/py-value.exp index eaed9c7..13bce9a 100644 --- a/gdb/testsuite/gdb.python/py-value.exp +++ b/gdb/testsuite/gdb.python/py-value.exp @@ -374,6 +374,11 @@ proc test_subscript_regression {lang} { gdb_py_test_silent_cmd "python rptr = gdb.history(0)" \ "Obtains value from GDB" 1 gdb_test "python print rptr\[0\]" "2" "Check pointer passed as reference" + + # Just the most basic test of dynamic_cast -- it is checked in + # the C++ tests. + gdb_test "python print bool(gdb.parse_and_eval('base').dynamic_cast(gdb.lookup_type('Derived').pointer()))" \ + True } gdb_breakpoint [gdb_get_line_number "break to inspect struct and union"]