diff options
author | Doug Evans <dje@google.com> | 2015-04-29 13:24:21 -0700 |
---|---|---|
committer | Doug Evans <dje@google.com> | 2015-04-29 13:24:21 -0700 |
commit | 2ce1cdbf84ce883b992bc8ffec3d29b4da229b72 (patch) | |
tree | 4143b5da94595cdef5199d0ca8afd6ec14bc30e6 /gdb/python | |
parent | 99b2a2dd3cd91ee45aba56a90b52be943001e8f4 (diff) | |
download | gdb-2ce1cdbf84ce883b992bc8ffec3d29b4da229b72.zip gdb-2ce1cdbf84ce883b992bc8ffec3d29b4da229b72.tar.gz gdb-2ce1cdbf84ce883b992bc8ffec3d29b4da229b72.tar.bz2 |
PR python/18285
gdb/ChangeLog:
PR python/18285
* NEWS: Document new gdb.XMethodWorker.get_result_type method.
* eval.c (evaluate_subexp_standard) <OP_FUNCALL>: Handle
EVAL_AVOID_SIDE_EFFECTS for xmethods.
* extension-priv.h (struct extension_language_ops)
<get_xmethod_result_type>: New member.
* extension.c (get_xmethod_result_type): New function.
* extension.h (get_xmethod_result_type): Declare.
* python/py-xmethods.c (get_result_type_method_name): New static
global.
(py_get_result_type_method_name): Ditto.
(gdbpy_get_xmethod_result_type): New function.
(gdbpy_initialize_xmethods): Initialize py_get_result_type_method_name.
* python/python-internal.h (gdbpy_get_xmethod_result_type): Declare.
* python/python.c (python_extension_ops): Add
gdbpy_get_xmethod_result_type.
* python/lib/gdb/xmethod.py (XMethodWorker): Add get_result_type.
* valarith.c (value_x_binop): Handle EVAL_AVOID_SIDE_EFFECTS for
xmethods.
(value_x_unop): Ditto.
* value.c (result_type_of_xmethod): New function.
* value.h (result_type_of_xmethod): Declare.
gdb/testsuite/ChangeLog:
* gdb.python/py-xmethods.exp: Add ptype tests.
* gdb.python/py-xmethods.py (E_method_char_worker): Add
get_result_type method.
gdb/doc/ChangeLog:
* python.texi (Xmethod API) <gdb.XMethodWorker.get_result_type>:
Document.
(Writing an Xmethod): Add get_result_type to example.
Diffstat (limited to 'gdb/python')
-rw-r--r-- | gdb/python/lib/gdb/xmethod.py | 20 | ||||
-rw-r--r-- | gdb/python/py-xmethods.c | 107 | ||||
-rw-r--r-- | gdb/python/python-internal.h | 5 | ||||
-rw-r--r-- | gdb/python/python.c | 1 |
4 files changed, 131 insertions, 2 deletions
diff --git a/gdb/python/lib/gdb/xmethod.py b/gdb/python/lib/gdb/xmethod.py index 672b2d8..6acc23c 100644 --- a/gdb/python/lib/gdb/xmethod.py +++ b/gdb/python/lib/gdb/xmethod.py @@ -101,9 +101,11 @@ class XMethodWorker(object): invokes the method when GDB wants it to. Internally, GDB first invokes the 'get_arg_types' method to perform overload resolution. If GDB selects to invoke this Python xmethod, then it invokes it via the overridden - '__call__' method. + '__call__' method. The 'get_result_type' method is used to implement + 'ptype' on the xmethod. - Derived classes should override the 'get_arg_types' and '__call__' methods. + Derived classes should override the 'get_arg_types', 'get_result_type' + and '__call__' methods. """ def get_arg_types(self): @@ -117,6 +119,20 @@ class XMethodWorker(object): """ raise NotImplementedError("XMethodWorker get_arg_types") + def get_result_type(self, *args): + """Return the type of the result of the xmethod. + + Args: + args: Arguments to the method. Each element of the tuple is a + gdb.Value object. The first element is the 'this' pointer + value. These are the same arguments passed to '__call__'. + + Returns: + A gdb.Type object representing the type of the result of the + xmethod. + """ + raise NotImplementedError("XMethodWorker get_result_type") + def __call__(self, *args): """Invoke the xmethod. diff --git a/gdb/python/py-xmethods.c b/gdb/python/py-xmethods.c index 0a7fc38..91e2691 100644 --- a/gdb/python/py-xmethods.c +++ b/gdb/python/py-xmethods.c @@ -30,11 +30,13 @@ static const char enabled_field_name[] = "enabled"; static const char match_method_name[] = "match"; static const char get_arg_types_method_name[] = "get_arg_types"; +static const char get_result_type_method_name[] = "get_result_type"; static const char invoke_method_name[] = "invoke"; static const char matchers_attr_str[] = "xmethods"; static PyObject *py_match_method_name = NULL; static PyObject *py_get_arg_types_method_name = NULL; +static PyObject *py_get_result_type_method_name = NULL; static PyObject *py_invoke_method_name = NULL; struct gdbpy_worker_data @@ -502,6 +504,106 @@ gdbpy_get_xmethod_arg_types (const struct extension_language_defn *extlang, return EXT_LANG_RC_OK; } +/* Implementation of get_xmethod_result_type for Python. */ + +enum ext_lang_rc +gdbpy_get_xmethod_result_type (const struct extension_language_defn *extlang, + struct xmethod_worker *worker, + struct value *obj, + struct value **args, int nargs, + struct type **result_type_ptr) +{ + struct gdbpy_worker_data *worker_data = worker->data; + PyObject *py_worker = worker_data->worker; + PyObject *py_value_obj, *py_arg_tuple, *py_result_type; + PyObject *get_result_type_method; + struct type *obj_type, *this_type; + struct cleanup *cleanups; + int i; + + cleanups = ensure_python_env (get_current_arch (), current_language); + + /* First see if there is a get_result_type method. + If not this could be an old xmethod (pre 7.9.1). */ + get_result_type_method + = PyObject_GetAttrString (py_worker, get_result_type_method_name); + if (get_result_type_method == NULL) + { + PyErr_Clear (); + do_cleanups (cleanups); + *result_type_ptr = NULL; + return EXT_LANG_RC_OK; + } + make_cleanup_py_decref (get_result_type_method); + + obj_type = check_typedef (value_type (obj)); + this_type = check_typedef (type_object_to_type (worker_data->this_type)); + if (TYPE_CODE (obj_type) == TYPE_CODE_PTR) + { + struct type *this_ptr = lookup_pointer_type (this_type); + + if (!types_equal (obj_type, this_ptr)) + obj = value_cast (this_ptr, obj); + } + else if (TYPE_CODE (obj_type) == TYPE_CODE_REF) + { + struct type *this_ref = lookup_reference_type (this_type); + + if (!types_equal (obj_type, this_ref)) + obj = value_cast (this_ref, obj); + } + else + { + if (!types_equal (obj_type, this_type)) + obj = value_cast (this_type, obj); + } + py_value_obj = value_to_value_object (obj); + if (py_value_obj == NULL) + goto Fail; + make_cleanup_py_decref (py_value_obj); + + py_arg_tuple = PyTuple_New (nargs + 1); + if (py_arg_tuple == NULL) + goto Fail; + make_cleanup_py_decref (py_arg_tuple); + + /* PyTuple_SET_ITEM steals the reference of the element. Hence INCREF the + reference to the 'this' object as we have a cleanup to DECREF it. */ + Py_INCREF (py_value_obj); + PyTuple_SET_ITEM (py_arg_tuple, 0, py_value_obj); + + for (i = 0; i < nargs; i++) + { + PyObject *py_value_arg = value_to_value_object (args[i]); + + if (py_value_arg == NULL) + goto Fail; + PyTuple_SET_ITEM (py_arg_tuple, i + 1, py_value_arg); + } + + py_result_type = PyObject_CallObject (get_result_type_method, py_arg_tuple); + if (py_result_type == NULL) + goto Fail; + make_cleanup_py_decref (py_result_type); + + *result_type_ptr = type_object_to_type (py_result_type); + if (*result_type_ptr == NULL) + { + PyErr_SetString (PyExc_TypeError, + _("Type returned by the get_result_type method of an" + " xmethod worker object is not a gdb.Type object.")); + goto Fail; + } + + do_cleanups (cleanups); + return EXT_LANG_RC_OK; + + Fail: + gdbpy_print_stack (); + do_cleanups (cleanups); + return EXT_LANG_RC_ERROR; +} + /* Implementation of invoke_xmethod for Python. */ struct value * @@ -638,5 +740,10 @@ gdbpy_initialize_xmethods (void) if (py_get_arg_types_method_name == NULL) return -1; + py_get_result_type_method_name + = PyString_FromString (get_result_type_method_name); + if (py_get_result_type_method_name == NULL) + return -1; + return 1; } diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 55af10e..f881559 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -348,6 +348,11 @@ extern enum ext_lang_rc gdbpy_get_xmethod_arg_types struct xmethod_worker *worker, int *nargs, struct type ***arg_types); +extern enum ext_lang_rc gdbpy_get_xmethod_result_type + (const struct extension_language_defn *extlang, + struct xmethod_worker *worker, + struct value *object, struct value **args, int nargs, + struct type **result_type); extern struct value *gdbpy_invoke_xmethod (const struct extension_language_defn *extlang, struct xmethod_worker *worker, diff --git a/gdb/python/python.c b/gdb/python/python.c index ee86680..4f88b0e 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -192,6 +192,7 @@ const struct extension_language_ops python_extension_ops = gdbpy_free_xmethod_worker_data, gdbpy_get_matching_xmethod_workers, gdbpy_get_xmethod_arg_types, + gdbpy_get_xmethod_result_type, gdbpy_invoke_xmethod }; |