aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog84
-rw-r--r--gdb/extension-priv.h75
-rw-r--r--gdb/extension.c158
-rw-r--r--gdb/extension.h108
-rw-r--r--gdb/python/py-xmethods.c154
-rw-r--r--gdb/python/python-internal.h21
-rw-r--r--gdb/python/python.c5
-rw-r--r--gdb/valops.c52
-rw-r--r--gdb/value.c30
-rw-r--r--gdb/value.h7
10 files changed, 292 insertions, 402 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 24ccfe6..65b9ef9 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,87 @@
+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
diff --git a/gdb/extension-priv.h b/gdb/extension-priv.h
index 8fbf1b0..5843479 100644
--- a/gdb/extension-priv.h
+++ b/gdb/extension-priv.h
@@ -25,26 +25,6 @@
#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
@@ -261,63 +241,18 @@ struct extension_language_ops
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. */
diff --git a/gdb/extension.c b/gdb/extension.c
index a1ee351..224b05c 100644
--- a/gdb/extension.c
+++ b/gdb/extension.c
@@ -850,68 +850,18 @@ check_quit_flag (void)
return result;
}
-
-/* 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
@@ -921,115 +871,45 @@ get_matching_xmethod_workers (struct type *type, const char *method_name)
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);
-}
-
/* 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,
diff --git a/gdb/extension.h b/gdb/extension.h
index 04f9049..475d712 100644
--- a/gdb/extension.h
+++ b/gdb/extension.h
@@ -146,26 +146,85 @@ struct ext_lang_type_printers
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;
-
/* The interface for gdb's own extension(/scripting) language. */
extern const struct extension_language_defn extension_language_gdb;
@@ -242,26 +301,13 @@ extern const struct extension_language_defn *get_breakpoint_cond_ext_lang
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 */
diff --git a/gdb/python/py-xmethods.c b/gdb/python/py-xmethods.c
index 750f263..f4064c2 100644
--- a/gdb/python/py-xmethods.c
+++ b/gdb/python/py-xmethods.c
@@ -37,54 +37,60 @@ static const char matchers_attr_str[] = "xmethods";
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
@@ -130,10 +136,9 @@ 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)
+ 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);
@@ -282,39 +287,33 @@ gdbpy_get_matching_xmethod_workers
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;
@@ -324,7 +323,7 @@ gdbpy_get_xmethod_arg_types (const struct extension_language_defn *extlang,
*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 ();
@@ -332,7 +331,7 @@ gdbpy_get_xmethod_arg_types (const struct extension_language_defn *extlang,
}
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)
{
@@ -418,7 +417,7 @@ gdbpy_get_xmethod_arg_types (const struct extension_language_defn *extlang,
/* 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;
@@ -427,18 +426,12 @@ gdbpy_get_xmethod_arg_types (const struct extension_language_defn *extlang,
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;
@@ -447,7 +440,7 @@ gdbpy_get_xmethod_result_type (const struct extension_language_defn *extlang,
/* 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 ();
@@ -456,7 +449,7 @@ gdbpy_get_xmethod_result_type (const struct extension_language_defn *extlang,
}
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);
@@ -528,24 +521,20 @@ gdbpy_get_xmethod_result_type (const struct extension_language_defn *extlang,
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);
@@ -597,7 +586,7 @@ gdbpy_invoke_xmethod (const struct extension_language_defn *extlang,
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)
{
@@ -623,24 +612,15 @@ gdbpy_invoke_xmethod (const struct extension_language_defn *extlang,
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
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index f32a258..f38f0b3 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -463,28 +463,11 @@ extern enum ext_lang_bp_stop gdbpy_breakpoint_cond_says_stop
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);
+
PyObject *gdbpy_history (PyObject *self, PyObject *args);
PyObject *gdbpy_breakpoints (PyObject *, PyObject *);
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 4844c86..9eae8a1 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -190,12 +190,7 @@ const struct extension_language_ops python_extension_ops =
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
diff --git a/gdb/valops.c b/gdb/valops.c
index 9525dc8..8fccfe9 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -68,7 +68,8 @@ int find_oload_champ_namespace_loop (struct value **, int,
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);
@@ -98,7 +99,7 @@ static struct value *cast_into_complex (struct type *, struct value *);
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
@@ -2282,12 +2283,11 @@ static void
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);
@@ -2328,12 +2328,7 @@ find_method_list (struct value **argp, const char *method,
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
@@ -2382,7 +2377,7 @@ static void
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;
@@ -2409,7 +2404,7 @@ value_find_oload_method_list (struct value **argp, const char *method,
/* 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);
@@ -2488,8 +2483,8 @@ find_overload_match (struct value **args, int nargs,
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;
@@ -2534,8 +2529,8 @@ find_overload_match (struct value **args, int nargs,
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) ? "::" : "",
@@ -2558,15 +2553,14 @@ find_overload_match (struct value **args, int nargs,
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)
@@ -2783,11 +2777,8 @@ find_overload_match (struct value **args, int nargs,
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];
@@ -2992,12 +2983,11 @@ find_oload_champ_namespace_loop (struct value **args, int nargs,
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. */
@@ -3014,9 +3004,8 @@ find_oload_champ (struct value **args, int nargs,
*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++)
{
@@ -3024,12 +3013,11 @@ find_oload_champ (struct value **args, int nargs,
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
{
diff --git a/gdb/value.c b/gdb/value.c
index d4b4673..9a144fb 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -1627,7 +1627,7 @@ value_free (struct value *val)
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);
@@ -2697,23 +2697,20 @@ show_convenience (const char *ignore, int from_tty)
}
}
-/* 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. */
@@ -2724,8 +2721,8 @@ result_type_of_xmethod (struct value *method, int argc, struct value **argv)
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. */
@@ -2736,8 +2733,7 @@ call_xmethod (struct value *method, int argc, struct value **argv)
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);
}
/* Extract a value as a C number (either long or double).
diff --git a/gdb/value.h b/gdb/value.h
index 7dc67dc..e0ea22d 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -21,6 +21,7 @@
#define VALUE_H 1
#include "frame.h" /* For struct frame_id. */
+#include "extension.h"
struct block;
struct expression;
@@ -30,7 +31,6 @@ struct type;
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
@@ -1158,7 +1158,10 @@ struct value *call_internal_function (struct gdbarch *gdbarch,
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);