This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
RFA: fix PR python/11145
- From: Tom Tromey <tromey at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Fri, 20 Aug 2010 16:41:40 -0600
- Subject: RFA: fix PR python/11145
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 <tromey@redhat.com>
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 <tromey@redhat.com>
PR python/11145:
* gdb.texinfo (Values From Inferior): Document dynamic_cast and
reinterpret_cast methods.
2010-08-20 Tom Tromey <tromey@redhat.com>
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"]