+2018-01-07 Simon Marchi <simon.marchi@polymtl.ca>
+
+ * extension-priv.h (enum ext_lang_rc): Remove, move to extension.h.
+ (struct extension_language_ops) <clone_xmethod_worker_data>: Remove.
+ <free_xmethod_worker_data>: Remove.
+ <get_matching_xmethod_workers>: Chance VEC to std::vector.
+ <get_xmethod_arg_types>: Remove.
+ <get_xmethod_result_type>: Remove.
+ <invoke_xmethod>: Remove.
+ * extension.c (new_xmethod_worker): Remove.
+ (clone_xmethod_worker): Remove.
+ (get_matching_xmethod_workers): Return void, pass std::vector by
+ pointer.
+ (get_xmethod_arg_types): Rename to...
+ (xmethod_worker::get_arg_types): ... this, and adjust.
+ (get_xmethod_result_type): Rename to...
+ (xmethod_worker::get_result_type): ... this, and adjust.
+ (invoke_xmethod): Remove.
+ (free_xmethod_worker): Remove.
+ (free_xmethod_worker_vec): Remove.
+ * extension.h (enum ext_lang_rc): Move here from
+ extension-priv.h.
+ (struct xmethod_worker): Add constructor and destructor.
+ <data>: Remove.
+ <value>: Remove.
+ <invoke, clone, do_get_result_type, do_get_arg_types>: New
+ virtual pure methods.
+ <get_arg_types, get_result_type>: New methods.
+ (xmethod_worker_ptr): Remove typedef.
+ (DEF_VEC_P (xmethod_worker_ptr)): Remove.
+ (xmethod_worker_vec): Remove typedef.
+ (xmethod_worker_up): New typedef.
+ (invoke_xmethod): Remove.
+ (clone_xmethod_worker): Remove.
+ (free_xmethod_worker): Remove.
+ (free_xmethod_worker_vec): Remove.
+ (get_xmethod_arg_types): Remove.
+ (get_xmethod_result_type): Remove.
+ * valops.c (find_method_list): Use std::vector, don't use
+ intermediate vector.
+ (value_find_oload_method_list): Use std::vector.
+ (find_overload_match): Use std::vector.
+ (find_oload_champ): Use std::vector.
+ * value.c (value_free): Use operator delete.
+ (value_of_xmethod): Rename to...
+ (value_from_xmethod): ... this. Don't assign
+ xmethod_worker::value, take rvalue-reference.
+ (result_type_of_xmethod): Adjust.
+ (call_xmethod): Adjust.
+ * value.h: Include extension.h.
+ (struct xmethod_worker): Don't forward-declare.
+ (value_of_xmethod): Rename to...
+ (value_from_xmethod): ... this, take rvalue-reference.
+ * python/py-xmethods.c (struct gdbpy_worker_data): Rename to...
+ (struct python_xmethod_worker): ... this, add constructor and
+ destructor.
+ <invoke, clone, do_get_arg_types, do_get_result_type>: Implement.
+ (gdbpy_free_xmethod_worker_data): Rename to...
+ (python_xmethod_worker::~python_xmethod_worker): ... this and
+ adjust.
+ (gdbpy_clone_xmethod_worker_data): Rename to...
+ (python_xmethod_worker::clone): ... this and adjust.
+ (gdbpy_get_matching_xmethod_workers): Use std::vector, don't use
+ temporary vector.
+ (gdbpy_get_xmethod_arg_types): Rename to...
+ (python_xmethod_worker::do_get_arg_types): ... this and adjust.
+ (gdbpy_get_xmethod_result_type): Rename to...
+ (python_xmethod_worker::do_get_result_type): ... this and
+ adjust.
+ (gdbpy_invoke_xmethod): Rename to...
+ (python_xmethod_worker::invoke): ... this and adjust.
+ (new_python_xmethod_worker): Rename to...
+ (python_xmethod_worker::python_xmethod_worker): ... this and
+ adjust.
+ * python/python-internal.h (gdbpy_clone_xmethod_worker_data):
+ Remove.
+ (gdbpy_free_xmethod_worker_data): Remove.
+ (gdbpy_get_matching_xmethod_workers): Use std::vector.
+ (gdbpy_get_xmethod_arg_types): Remove.
+ (gdbpy_get_xmethod_result_type): Remove.
+ (gdbpy_invoke_xmethod): Remove.
+ * python/python.c (python_extension_ops): Remove obsolete
+ callbacks.
+
2018-01-05 Pedro Alves <palves@redhat.com>
PR gdb/18653
#include <signal.h>
#include "cli/cli-script.h"
-/* The return code for some API calls. */
-
-enum ext_lang_rc
- {
- /* The operation completed successfully. */
- EXT_LANG_RC_OK,
-
- /* The operation was not performed (e.g., no pretty-printer). */
- EXT_LANG_RC_NOP,
-
- /* There was an error (e.g., Python error while printing a value).
- When an error occurs no further extension languages are tried.
- This is to preserve existing behaviour, and because it's convenient
- for Python developers.
- Note: This is different than encountering a memory error trying to read
- a value for pretty-printing. Here we're referring to, e.g., programming
- errors that trigger an exception in the extension language. */
- EXT_LANG_RC_ERROR
- };
-
/* High level description of an extension/scripting language.
An entry for each is compiled into GDB regardless of whether the support
is present. This is done so that we can issue meaningful errors if the
enum ext_lang_rc (*before_prompt) (const struct extension_language_defn *,
const char *current_gdb_prompt);
- /* xmethod support:
- clone_xmethod_worker_data, free_xmethod_worker_data,
- get_matching_xmethod_workers, get_xmethod_arg_types,
- get_xmethod_return_type, invoke_xmethod.
- These methods are optional and may be NULL, but if one of them is
- implemented then they all must be. */
-
- /* Clone DATA and return a new but identical xmethod worker data
- object for this extension language. */
- void * (*clone_xmethod_worker_data)
- (const struct extension_language_defn *extlang, void *data);
-
- /* Free the DATA object of this extension language. */
- void (*free_xmethod_worker_data)
- (const struct extension_language_defn *extlang, void *data);
-
/* Return a vector of matching xmethod workers defined in this
extension language. The workers service methods with name
METHOD_NAME on objects of type OBJ_TYPE. The vector is returned
- in DM_VEC. */
+ in DM_VEC.
+
+ This field may be NULL if the extension language does not support
+ xmethods. */
enum ext_lang_rc (*get_matching_xmethod_workers)
(const struct extension_language_defn *extlang,
struct type *obj_type,
const char *method_name,
- xmethod_worker_vec **dm_vec);
-
- /* Given a WORKER servicing a particular method, return the types
- of the arguments the method takes. The number of arguments is
- returned in NARGS, and their types are returned in the array
- ARGTYPES. */
- enum ext_lang_rc (*get_xmethod_arg_types)
- (const struct extension_language_defn *extlang,
- struct xmethod_worker *worker,
- int *nargs,
- struct type ***arg_types);
-
- /* Given a WORKER servicing a particular method, fetch the type of the
- result of the method. OBJECT, ARGS, NARGS are the same as for
- invoke_xmethod. The result type is stored in *RESULT_TYPE.
- For backward compatibility with 7.9, which did not support getting the
- result type, if the get_result_type operation is not provided by WORKER
- then EXT_LANG_RC_OK is returned and NULL is returned in *RESULT_TYPE. */
- enum ext_lang_rc (*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);
-
- /* Invoke the xmethod serviced by WORKER. The xmethod is invoked
- on OBJECT with arguments in the array ARGS. NARGS is the length of
- this array. Returns the value returned by the xmethod. */
- struct value * (*invoke_xmethod)
- (const struct extension_language_defn *extlang,
- struct xmethod_worker *worker,
- struct value *object,
- struct value **args,
- int nargs);
+ std::vector<xmethod_worker_up> *dm_vec);
};
/* State necessary to restore a signal handler to its previous value. */
return result;
}
-\f
-/* xmethod support. */
-
-/* The xmethod API routines do not have "ext_lang" in the name because
- the name "xmethod" implies that this routine deals with extension
- languages. Plus some of the methods take a xmethod_foo * "self/this"
- arg, not an extension_language_defn * arg. */
-
-/* Returns a new xmethod_worker with EXTLANG and DATA. Space for the
- result must be freed with free_xmethod_worker. */
-
-struct xmethod_worker *
-new_xmethod_worker (const struct extension_language_defn *extlang, void *data)
-{
- struct xmethod_worker *worker = XCNEW (struct xmethod_worker);
-
- worker->extlang = extlang;
- worker->data = data;
- worker->value = NULL;
-
- return worker;
-}
-
-/* Clones WORKER and returns a new but identical worker.
- The function get_matching_xmethod_workers (see below), returns a
- vector of matching workers. If a particular worker is selected by GDB
- to invoke a method, then this function can help in cloning the
- selected worker and freeing up the vector via a cleanup.
-
- Space for the result must be freed with free_xmethod_worker. */
-
-struct xmethod_worker *
-clone_xmethod_worker (struct xmethod_worker *worker)
-{
- struct xmethod_worker *new_worker;
- const struct extension_language_defn *extlang = worker->extlang;
-
- gdb_assert (extlang->ops->clone_xmethod_worker_data != NULL);
-
- new_worker = new_xmethod_worker
- (extlang,
- extlang->ops->clone_xmethod_worker_data (extlang, worker->data));
- return new_worker;
-}
-
-/* If a method with name METHOD_NAME is to be invoked on an object of type
- TYPE, then all entension languages are searched for implementations of
- methods with name METHOD. All matches found are returned as a vector
- of 'xmethod_worker_ptr' objects. If no matching methods are
- found, NULL is returned. */
+/* See extension.h. */
-VEC (xmethod_worker_ptr) *
-get_matching_xmethod_workers (struct type *type, const char *method_name)
+void
+get_matching_xmethod_workers (struct type *type, const char *method_name,
+ std::vector<xmethod_worker_up> *workers)
{
- VEC (xmethod_worker_ptr) *workers = NULL;
int i;
const struct extension_language_defn *extlang;
ALL_ENABLED_EXTENSION_LANGUAGES (i, extlang)
{
- VEC (xmethod_worker_ptr) *lang_workers, *new_vec;
enum ext_lang_rc rc;
/* If an extension language does not support xmethods, ignore
rc = extlang->ops->get_matching_xmethod_workers (extlang,
type, method_name,
- &lang_workers);
+ workers);
if (rc == EXT_LANG_RC_ERROR)
- {
- free_xmethod_worker_vec (workers);
- error (_("Error while looking for matching xmethod workers "
- "defined in %s."), extlang->capitalized_name);
- }
-
- new_vec = VEC_merge (xmethod_worker_ptr, workers, lang_workers);
- /* Free only the vectors and not the elements as NEW_VEC still
- contains them. */
- VEC_free (xmethod_worker_ptr, workers);
- VEC_free (xmethod_worker_ptr, lang_workers);
- workers = new_vec;
+ error (_("Error while looking for matching xmethod workers "
+ "defined in %s."), extlang->capitalized_name);
}
-
- return workers;
}
-/* Return the arg types of the xmethod encapsulated in WORKER.
- An array of arg types is returned. The length of the array is returned in
- NARGS. The type of the 'this' object is returned as the first element of
- array. */
+/* See extension.h. */
-struct type **
-get_xmethod_arg_types (struct xmethod_worker *worker, int *nargs)
+type **
+xmethod_worker::get_arg_types (int *nargs)
{
- enum ext_lang_rc rc;
- struct type **type_array = NULL;
- const struct extension_language_defn *extlang = worker->extlang;
-
- gdb_assert (extlang->ops->get_xmethod_arg_types != NULL);
+ type **type_array = NULL;
- rc = extlang->ops->get_xmethod_arg_types (extlang, worker, nargs,
- &type_array);
+ ext_lang_rc rc = do_get_arg_types (nargs, &type_array);
if (rc == EXT_LANG_RC_ERROR)
- {
- error (_("Error while looking for arg types of a xmethod worker "
- "defined in %s."), extlang->capitalized_name);
- }
+ error (_("Error while looking for arg types of a xmethod worker "
+ "defined in %s."), m_extlang->capitalized_name);
return type_array;
}
-/* Return the type of the result of the xmethod encapsulated in WORKER.
- OBJECT, ARGS, NARGS are the same as for invoke_xmethod. */
+/* See extension.h. */
struct type *
-get_xmethod_result_type (struct xmethod_worker *worker,
- struct value *object, struct value **args, int nargs)
+xmethod_worker::get_result_type (value *object, value **args, int nargs)
{
- enum ext_lang_rc rc;
- struct type *result_type;
- const struct extension_language_defn *extlang = worker->extlang;
-
- gdb_assert (extlang->ops->get_xmethod_arg_types != NULL);
+ type *result_type;
- rc = extlang->ops->get_xmethod_result_type (extlang, worker,
- object, args, nargs,
- &result_type);
+ ext_lang_rc rc = do_get_result_type (object, args, nargs, &result_type);
if (rc == EXT_LANG_RC_ERROR)
{
error (_("Error while fetching result type of an xmethod worker "
- "defined in %s."), extlang->capitalized_name);
+ "defined in %s."), m_extlang->capitalized_name);
}
return result_type;
}
-/* Invokes the xmethod encapsulated in WORKER and returns the result.
- The method is invoked on OBJ with arguments in the ARGS array. NARGS is
- the length of the this array. */
-
-struct value *
-invoke_xmethod (struct xmethod_worker *worker, struct value *obj,
- struct value **args, int nargs)
-{
- gdb_assert (worker->extlang->ops->invoke_xmethod != NULL);
-
- return worker->extlang->ops->invoke_xmethod (worker->extlang, worker,
- obj, args, nargs);
-}
-
-/* Frees the xmethod worker WORKER. */
-
-void
-free_xmethod_worker (struct xmethod_worker *worker)
-{
- gdb_assert (worker->extlang->ops->free_xmethod_worker_data != NULL);
- worker->extlang->ops->free_xmethod_worker_data (worker->extlang,
- worker->data);
- xfree (worker);
-}
-
-/* Frees a vector of xmethod_workers VEC. */
-
-void
-free_xmethod_worker_vec (void *vec)
-{
- int i;
- struct xmethod_worker *worker;
- VEC (xmethod_worker_ptr) *v = (VEC (xmethod_worker_ptr) *) vec;
-
- for (i = 0; VEC_iterate (xmethod_worker_ptr, v, i, worker); i++)
- free_xmethod_worker (worker);
-
- VEC_free (xmethod_worker_ptr, v);
-}
-\f
/* Called via an observer before gdb prints its prompt.
Iterate over the extension languages giving them a chance to
change the prompt. The first one to change the prompt wins,
void *py_type_printers;
};
+/* The return code for some API calls. */
+
+enum ext_lang_rc
+{
+ /* The operation completed successfully. */
+ EXT_LANG_RC_OK,
+
+ /* The operation was not performed (e.g., no pretty-printer). */
+ EXT_LANG_RC_NOP,
+
+ /* There was an error (e.g., Python error while printing a value).
+ When an error occurs no further extension languages are tried.
+ This is to preserve existing behaviour, and because it's convenient
+ for Python developers.
+ Note: This is different than encountering a memory error trying to read
+ a value for pretty-printing. Here we're referring to, e.g., programming
+ errors that trigger an exception in the extension language. */
+ EXT_LANG_RC_ERROR
+};
+
/* A type which holds its extension language specific xmethod worker data. */
struct xmethod_worker
{
- /* The language the xmethod worker is implemented in. */
- const struct extension_language_defn *extlang;
+ xmethod_worker (const extension_language_defn *extlang)
+ : m_extlang (extlang)
+ {}
+
+ virtual ~xmethod_worker () = default;
+
+ /* Invoke the xmethod encapsulated in this worker and return the result.
+ The method is invoked on OBJ with arguments in the ARGS array. NARGS is
+ the length of the this array. */
+
+ virtual value *invoke (value *obj, value **args, int nargs) = 0;
+
+ /* Clone this worker, returns a new but identical worker.
+ The function get_matching_xmethod_workers returns a vector of matching
+ workers. If a particular worker is selected by GDB to invoke a method,
+ then this function can help in cloning the selected worker. */
+
+ virtual std::unique_ptr<xmethod_worker> clone () = 0;
+
+ /* Return the arg types of the xmethod encapsulated in this worker.
+ An array of arg types is returned. The length of the array is returned in
+ NARGS. The type of the 'this' object is returned as the first element of
+ array. */
+
+ type **get_arg_types (int *nargs);
+
+ /* Return the type of the result of the xmethod encapsulated in this worker.
+ OBJECT, ARGS, NARGS are the same as for invoke. */
- /* The extension language specific data for this xmethod worker. */
- void *data;
+ type *get_result_type (value *object, value **args, int nargs);
- /* The TYPE_CODE_XMETHOD value corresponding to this worker.
- Always use value_of_xmethod to access it. */
- struct value *value;
+private:
+
+ /* Return the types of the arguments the method takes. The number of
+ arguments is returned in NARGS, and their types are returned in the array
+ ARGTYPES. */
+
+ virtual enum ext_lang_rc do_get_arg_types
+ (int *nargs, struct type ***arg_types) = 0;
+
+ /* Fetch the type of the result of the method implemented by this worker.
+ OBJECT, ARGS, NARGS are the same as for the invoked method. The result
+ type is stored in *RESULT_TYPE. */
+
+ virtual enum ext_lang_rc do_get_result_type
+ (struct value *obj, struct value **args, int nargs,
+ struct type **result_type_ptr) = 0;
+
+ /* The language the xmethod worker is implemented in. */
+
+ const extension_language_defn *m_extlang;
};
-typedef struct xmethod_worker *xmethod_worker_ptr;
-DEF_VEC_P (xmethod_worker_ptr);
-typedef VEC (xmethod_worker_ptr) xmethod_worker_vec;
+typedef std::unique_ptr<xmethod_worker> xmethod_worker_up;
-\f
/* The interface for gdb's own extension(/scripting) language. */
extern const struct extension_language_defn extension_language_gdb;
extern int breakpoint_ext_lang_cond_says_stop (struct breakpoint *);
-extern struct value *invoke_xmethod (struct xmethod_worker *,
- struct value *,
- struct value **, int nargs);
-
-extern struct xmethod_worker *clone_xmethod_worker (struct xmethod_worker *);
-
-extern struct xmethod_worker *new_xmethod_worker
- (const struct extension_language_defn *extlang, void *data);
-
-extern void free_xmethod_worker (struct xmethod_worker *);
-
-extern void free_xmethod_worker_vec (void *vec);
-
-extern xmethod_worker_vec *get_matching_xmethod_workers
- (struct type *, const char *);
-
-extern struct type **get_xmethod_arg_types (struct xmethod_worker *, int *);
+/* If a method with name METHOD_NAME is to be invoked on an object of type
+ TYPE, then all extension languages are searched for implementations of
+ methods with name METHOD_NAME. All matches found are appended to the WORKERS
+ vector. */
-extern struct type *get_xmethod_result_type (struct xmethod_worker *,
- struct value *object,
- struct value **args, int nargs);
+extern void get_matching_xmethod_workers
+ (struct type *type, const char *method_name,
+ std::vector<xmethod_worker_up> *workers);
#endif /* EXTENSION_H */
static PyObject *py_match_method_name = NULL;
static PyObject *py_get_arg_types_method_name = NULL;
-struct gdbpy_worker_data
+struct python_xmethod_worker : xmethod_worker
{
- PyObject *worker;
- PyObject *this_type;
-};
+ python_xmethod_worker (PyObject *worker, PyObject *this_type);
+ ~python_xmethod_worker ();
-static struct xmethod_worker *new_python_xmethod_worker (PyObject *item,
- PyObject *py_obj_type);
+ DISABLE_COPY_AND_ASSIGN (python_xmethod_worker);
-/* Implementation of free_xmethod_worker_data for Python. */
+ /* Implementation of xmethod_worker::invoke for Python. */
-void
-gdbpy_free_xmethod_worker_data (const struct extension_language_defn *extlang,
- void *data)
-{
- struct gdbpy_worker_data *worker_data = (struct gdbpy_worker_data *) data;
+ value *invoke (value *obj, value **args, int nargs) override;
+
+ /* Implementation of xmethod_worker::clone for Python. */
+
+ xmethod_worker_up clone () override;
+
+ /* Implementation of xmethod_worker::do_get_arg_types for Python. */
+
+ ext_lang_rc do_get_arg_types (int *nargs, type ***arg_types) override;
+
+ /* Implementation of xmethod_worker::do_get_result_type for Python.
- gdb_assert (worker_data->worker != NULL && worker_data->this_type != NULL);
+ For backward compatibility with 7.9, which did not support getting the
+ result type, if the get_result_type operation is not provided by WORKER
+ then EXT_LANG_RC_OK is returned and NULL is returned in *RESULT_TYPE. */
+ ext_lang_rc do_get_result_type (value *obj, value **args, int nargs,
+ type **result_type_ptr) override;
+
+private:
+
+ PyObject *m_py_worker;
+ PyObject *m_this_type;
+};
+
+python_xmethod_worker::~python_xmethod_worker ()
+{
/* We don't do much here, but we still need the GIL. */
gdbpy_enter enter_py (get_current_arch (), current_language);
- Py_DECREF (worker_data->worker);
- Py_DECREF (worker_data->this_type);
- xfree (worker_data);
+ Py_DECREF (m_py_worker);
+ Py_DECREF (m_this_type);
}
-/* Implementation of clone_xmethod_worker_data for Python. */
+/* See declaration. */
-void *
-gdbpy_clone_xmethod_worker_data (const struct extension_language_defn *extlang,
- void *data)
+xmethod_worker_up
+python_xmethod_worker::clone ()
{
- struct gdbpy_worker_data *worker_data
- = (struct gdbpy_worker_data *) data, *new_data;
-
- gdb_assert (worker_data->worker != NULL && worker_data->this_type != NULL);
-
/* We don't do much here, but we still need the GIL. */
gdbpy_enter enter_py (get_current_arch (), current_language);
- new_data = XCNEW (struct gdbpy_worker_data);
- new_data->worker = worker_data->worker;
- new_data->this_type = worker_data->this_type;
- Py_INCREF (new_data->worker);
- Py_INCREF (new_data->this_type);
+ xmethod_worker *worker = new python_xmethod_worker (m_py_worker, m_this_type);
- return new_data;
+ return xmethod_worker_up (worker);
}
/* Invoke the "match" method of the MATCHER and return a new reference
gdbpy_get_matching_xmethod_workers
(const struct extension_language_defn *extlang,
struct type *obj_type, const char *method_name,
- xmethod_worker_vec **dm_vec)
+ std::vector<xmethod_worker_up> *dm_vec)
{
struct objfile *objfile;
- VEC (xmethod_worker_ptr) *worker_vec = NULL;
PyObject *py_progspace;
gdb_assert (obj_type != NULL && method_name != NULL);
break;
}
- worker = new_python_xmethod_worker (py_worker.get (),
+ worker = new python_xmethod_worker (py_worker.get (),
py_type.get ());
- VEC_safe_push (xmethod_worker_ptr, worker_vec, worker);
+
+ dm_vec->emplace_back (worker);
}
}
else
{
struct xmethod_worker *worker;
- worker = new_python_xmethod_worker (match_result.get (),
+ worker = new python_xmethod_worker (match_result.get (),
py_type.get ());
- VEC_safe_push (xmethod_worker_ptr, worker_vec, worker);
+ dm_vec->emplace_back (worker);
}
}
- *dm_vec = worker_vec;
-
return EXT_LANG_RC_OK;
}
-/* Implementation of get_xmethod_arg_types for Python. */
+/* See declaration. */
-enum ext_lang_rc
-gdbpy_get_xmethod_arg_types (const struct extension_language_defn *extlang,
- struct xmethod_worker *worker,
- int *nargs, struct type ***arg_types)
+ext_lang_rc
+python_xmethod_worker::do_get_arg_types (int *nargs, type ***arg_types)
{
/* The gdbpy_enter object needs to be placed first, so that it's the last to
be destroyed. */
gdbpy_enter enter_py (get_current_arch (), current_language);
- struct gdbpy_worker_data *worker_data
- = (struct gdbpy_worker_data *) worker->data;
- PyObject *py_worker = worker_data->worker;
struct type *obj_type;
int i = 1, arg_count;
gdbpy_ref<> list_iter;
*nargs = -1;
gdbpy_ref<> get_arg_types_method
- (PyObject_GetAttrString (py_worker, get_arg_types_method_name));
+ (PyObject_GetAttrString (m_py_worker, get_arg_types_method_name));
if (get_arg_types_method == NULL)
{
gdbpy_print_stack ();
}
gdbpy_ref<> py_argtype_list
- (PyObject_CallMethodObjArgs (py_worker, py_get_arg_types_method_name,
+ (PyObject_CallMethodObjArgs (m_py_worker, py_get_arg_types_method_name,
NULL));
if (py_argtype_list == NULL)
{
/* Add the type of 'this' as the first argument. The 'this' pointer should
be a 'const' value. Hence, create a 'const' variant of the 'this' pointer
type. */
- obj_type = type_object_to_type (worker_data->this_type);
+ obj_type = type_object_to_type (m_this_type);
(type_array.get ())[0] = make_cv_type (1, 0, lookup_pointer_type (obj_type),
NULL);
*nargs = i;
return EXT_LANG_RC_OK;
}
-/* Implementation of get_xmethod_result_type for Python. */
+/* See declaration. */
-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)
+ext_lang_rc
+python_xmethod_worker::do_get_result_type (value *obj, value **args, int nargs,
+ type **result_type_ptr)
{
- struct gdbpy_worker_data *worker_data
- = (struct gdbpy_worker_data *) worker->data;
- PyObject *py_worker = worker_data->worker;
struct type *obj_type, *this_type;
int i;
/* First see if there is a get_result_type method.
If not this could be an old xmethod (pre 7.9.1). */
gdbpy_ref<> get_result_type_method
- (PyObject_GetAttrString (py_worker, get_result_type_method_name));
+ (PyObject_GetAttrString (m_py_worker, get_result_type_method_name));
if (get_result_type_method == NULL)
{
PyErr_Clear ();
}
obj_type = check_typedef (value_type (obj));
- this_type = check_typedef (type_object_to_type (worker_data->this_type));
+ this_type = check_typedef (type_object_to_type (m_this_type));
if (TYPE_CODE (obj_type) == TYPE_CODE_PTR)
{
struct type *this_ptr = lookup_pointer_type (this_type);
return EXT_LANG_RC_OK;
}
-/* Implementation of invoke_xmethod for Python. */
+/* See declaration. */
struct value *
-gdbpy_invoke_xmethod (const struct extension_language_defn *extlang,
- struct xmethod_worker *worker,
- struct value *obj, struct value **args, int nargs)
+python_xmethod_worker::invoke (struct value *obj, struct value **args,
+ int nargs)
{
+ gdbpy_enter enter_py (get_current_arch (), current_language);
+
int i;
struct type *obj_type, *this_type;
struct value *res = NULL;
- struct gdbpy_worker_data *worker_data
- = (struct gdbpy_worker_data *) worker->data;
- PyObject *xmethod_worker = worker_data->worker;
-
- gdbpy_enter enter_py (get_current_arch (), current_language);
obj_type = check_typedef (value_type (obj));
- this_type = check_typedef (type_object_to_type (worker_data->this_type));
+ this_type = check_typedef (type_object_to_type (m_this_type));
if (TYPE_CODE (obj_type) == TYPE_CODE_PTR)
{
struct type *this_ptr = lookup_pointer_type (this_type);
PyTuple_SET_ITEM (py_arg_tuple.get (), i + 1, py_value_arg);
}
- gdbpy_ref<> py_result (PyObject_CallObject (xmethod_worker,
+ gdbpy_ref<> py_result (PyObject_CallObject (m_py_worker,
py_arg_tuple.get ()));
if (py_result == NULL)
{
return res;
}
-/* Creates a new Python xmethod_worker object.
- The new object has data of type 'struct gdbpy_worker_data' composed
- with the components PY_WORKER and THIS_TYPE. */
-
-static struct xmethod_worker *
-new_python_xmethod_worker (PyObject *py_worker, PyObject *this_type)
+python_xmethod_worker::python_xmethod_worker (PyObject *py_worker,
+ PyObject *this_type)
+: xmethod_worker (&extension_language_python),
+ m_py_worker (py_worker), m_this_type (this_type)
{
- struct gdbpy_worker_data *data;
-
- gdb_assert (py_worker != NULL && this_type != NULL);
+ gdb_assert (m_py_worker != NULL && m_this_type != NULL);
- data = XCNEW (struct gdbpy_worker_data);
- data->worker = py_worker;
- data->this_type = this_type;
Py_INCREF (py_worker);
Py_INCREF (this_type);
-
- return new_xmethod_worker (&extension_language_python, data);
}
int
extern int gdbpy_breakpoint_has_cond (const struct extension_language_defn *,
struct breakpoint *b);
-extern void *gdbpy_clone_xmethod_worker_data
- (const struct extension_language_defn *extlang, void *data);
-extern void gdbpy_free_xmethod_worker_data
- (const struct extension_language_defn *extlang, void *data);
extern enum ext_lang_rc gdbpy_get_matching_xmethod_workers
(const struct extension_language_defn *extlang,
struct type *obj_type, const char *method_name,
- xmethod_worker_vec **dm_vec);
-extern enum ext_lang_rc gdbpy_get_xmethod_arg_types
- (const struct extension_language_defn *extlang,
- 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,
- struct value *obj, struct value **args, int nargs);
+ std::vector<xmethod_worker_up> *dm_vec);
+
\f
PyObject *gdbpy_history (PyObject *self, PyObject *args);
PyObject *gdbpy_breakpoints (PyObject *, PyObject *);
gdbpy_before_prompt_hook,
- gdbpy_clone_xmethod_worker_data,
- gdbpy_free_xmethod_worker_data,
gdbpy_get_matching_xmethod_workers,
- gdbpy_get_xmethod_arg_types,
- gdbpy_get_xmethod_result_type,
- gdbpy_invoke_xmethod
};
/* Architecture and language to be used in callbacks from
const int no_adl);
static int find_oload_champ (struct value **, int, int,
- struct fn_field *, VEC (xmethod_worker_ptr) *,
+ struct fn_field *,
+ const std::vector<xmethod_worker_up> *,
struct symbol **, struct badness_vector **);
static int oload_method_static_p (struct fn_field *, int);
static void find_method_list (struct value **, const char *,
LONGEST, struct type *, struct fn_field **, int *,
- VEC (xmethod_worker_ptr) **,
+ std::vector<xmethod_worker_up> *,
struct type **, LONGEST *);
#if 0
find_method_list (struct value **argp, const char *method,
LONGEST offset, struct type *type,
struct fn_field **fn_list, int *num_fns,
- VEC (xmethod_worker_ptr) **xm_worker_vec,
+ std::vector<xmethod_worker_up> *xm_worker_vec,
struct type **basetype, LONGEST *boffset)
{
int i;
struct fn_field *f = NULL;
- VEC (xmethod_worker_ptr) *worker_vec = NULL, *new_vec = NULL;
gdb_assert (fn_list != NULL && xm_worker_vec != NULL);
type = check_typedef (type);
and hence there is no point restricting them with something like method
hiding. Moreover, if hiding is done for xmethods as well, then we will
have to provide a mechanism to un-hide (like the 'using' construct). */
- worker_vec = get_matching_xmethod_workers (type, method);
- new_vec = VEC_merge (xmethod_worker_ptr, *xm_worker_vec, worker_vec);
-
- VEC_free (xmethod_worker_ptr, *xm_worker_vec);
- VEC_free (xmethod_worker_ptr, worker_vec);
- *xm_worker_vec = new_vec;
+ get_matching_xmethod_workers (type, method, xm_worker_vec);
/* If source methods are not found in current class, look for them in the
base classes. We also have to go through the base classes to gather
value_find_oload_method_list (struct value **argp, const char *method,
LONGEST offset, struct fn_field **fn_list,
int *num_fns,
- VEC (xmethod_worker_ptr) **xm_worker_vec,
+ std::vector<xmethod_worker_up> *xm_worker_vec,
struct type **basetype, LONGEST *boffset)
{
struct type *t;
/* Clear the lists. */
*fn_list = NULL;
*num_fns = 0;
- *xm_worker_vec = NULL;
+ xm_worker_vec->clear ();
find_method_list (argp, method, 0, t, fn_list, num_fns, xm_worker_vec,
basetype, boffset);
struct fn_field *fns_ptr = NULL;
/* For non-methods, the list of overloaded function symbols. */
struct symbol **oload_syms = NULL;
- /* For xmethods, the VEC of xmethod workers. */
- VEC (xmethod_worker_ptr) *xm_worker_vec = NULL;
+ /* For xmethods, the vector of xmethod workers. */
+ std::vector<xmethod_worker_up> xm_worker_vec;
/* Number of overloaded instances being considered. */
int num_fns = 0;
struct type *basetype = NULL;
value_find_oload_method_list (&temp, name, 0, &fns_ptr, &num_fns,
&xm_worker_vec, &basetype, &boffset);
/* If this is a method only search, and no methods were found
- the search has faild. */
- if (method == METHOD && (!fns_ptr || !num_fns) && !xm_worker_vec)
+ the search has failed. */
+ if (method == METHOD && (!fns_ptr || !num_fns) && xm_worker_vec.empty ())
error (_("Couldn't find method %s%s%s"),
obj_type_name,
(obj_type_name && *obj_type_name) ? "::" : "",
make_cleanup (xfree, src_method_badness);
}
- if (VEC_length (xmethod_worker_ptr, xm_worker_vec) > 0)
+ if (!xm_worker_vec.empty ())
{
ext_method_oload_champ = find_oload_champ (args, nargs,
- 0, NULL, xm_worker_vec,
+ 0, NULL, &xm_worker_vec,
NULL, &ext_method_badness);
ext_method_match_quality = classify_oload_match (ext_method_badness,
nargs, 0);
make_cleanup (xfree, ext_method_badness);
- make_cleanup (free_xmethod_worker_vec, xm_worker_vec);
}
if (src_method_oload_champ >= 0 && ext_method_oload_champ >= 0)
basetype, boffset);
}
else
- {
- *valp = value_of_xmethod (clone_xmethod_worker
- (VEC_index (xmethod_worker_ptr, xm_worker_vec,
- ext_method_oload_champ)));
- }
+ *valp = value_from_xmethod
+ (xm_worker_vec[ext_method_oload_champ]->clone ());
}
else
*symp = oload_syms[func_oload_champ];
static int
find_oload_champ (struct value **args, int nargs,
int num_fns, struct fn_field *fns_ptr,
- VEC (xmethod_worker_ptr) *xm_worker_vec,
+ const std::vector<xmethod_worker_up> *xm_worker_vec,
struct symbol **oload_syms,
struct badness_vector **oload_champ_bv)
{
int ix;
- int fn_count;
/* A measure of how good an overloaded instance is. */
struct badness_vector *bv;
/* Index of best overloaded function. */
*oload_champ_bv = NULL;
- fn_count = (xm_worker_vec != NULL
- ? VEC_length (xmethod_worker_ptr, xm_worker_vec)
- : num_fns);
+ int fn_count = xm_worker_vec != NULL ? xm_worker_vec->size () : num_fns;
+
/* Consider each candidate in turn. */
for (ix = 0; ix < fn_count; ix++)
{
int static_offset = 0;
int nparms;
struct type **parm_types;
- struct xmethod_worker *worker = NULL;
if (xm_worker_vec != NULL)
{
- worker = VEC_index (xmethod_worker_ptr, xm_worker_vec, ix);
- parm_types = get_xmethod_arg_types (worker, &nparms);
+ xmethod_worker *worker = (*xm_worker_vec)[ix].get ();
+ parm_types = worker->get_arg_types (&nparms);
}
else
{
funcs->free_closure (val);
}
else if (VALUE_LVAL (val) == lval_xcallable)
- free_xmethod_worker (val->location.xm_worker);
+ delete val->location.xm_worker;
xfree (val->contents);
VEC_free (range_s, val->unavailable);
}
}
\f
-/* Return the TYPE_CODE_XMETHOD value corresponding to WORKER. */
+
+/* See value.h. */
struct value *
-value_of_xmethod (struct xmethod_worker *worker)
+value_from_xmethod (xmethod_worker_up &&worker)
{
- if (worker->value == NULL)
- {
- struct value *v;
+ struct value *v;
- v = allocate_value (builtin_type (target_gdbarch ())->xmethod);
- v->lval = lval_xcallable;
- v->location.xm_worker = worker;
- v->modifiable = 0;
- worker->value = v;
- }
+ v = allocate_value (builtin_type (target_gdbarch ())->xmethod);
+ v->lval = lval_xcallable;
+ v->location.xm_worker = worker.release ();
+ v->modifiable = 0;
- return worker->value;
+ return v;
}
/* Return the type of the result of TYPE_CODE_XMETHOD value METHOD. */
gdb_assert (TYPE_CODE (value_type (method)) == TYPE_CODE_XMETHOD
&& method->lval == lval_xcallable && argc > 0);
- return get_xmethod_result_type (method->location.xm_worker,
- argv[0], argv + 1, argc - 1);
+ return method->location.xm_worker->get_result_type
+ (argv[0], argv + 1, argc - 1);
}
/* Call the xmethod corresponding to the TYPE_CODE_XMETHOD value METHOD. */
gdb_assert (TYPE_CODE (value_type (method)) == TYPE_CODE_XMETHOD
&& method->lval == lval_xcallable && argc > 0);
- return invoke_xmethod (method->location.xm_worker,
- argv[0], argv + 1, argc - 1);
+ return method->location.xm_worker->invoke (argv[0], argv + 1, argc - 1);
}
\f
/* Extract a value as a C number (either long or double).
#define VALUE_H 1
#include "frame.h" /* For struct frame_id. */
+#include "extension.h"
struct block;
struct expression;
struct ui_file;
struct language_defn;
struct value_print_options;
-struct xmethod_worker;
/* Values can be partially 'optimized out' and/or 'unavailable'.
These are distinct states and have different string representations
char *value_internal_function_name (struct value *);
-extern struct value *value_of_xmethod (struct xmethod_worker *);
+/* Build a value wrapping and representing WORKER. The value takes ownership
+ of the xmethod_worker object. */
+
+extern struct value *value_from_xmethod (xmethod_worker_up &&worker);
extern struct type *result_type_of_xmethod (struct value *method,
int argc, struct value **argv);