mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-24 02:24:46 +08:00
C++ify xmethod_worker, get rid of VEC(xmethod_worker_ptr)
The initial goal of this patch was to remove the usage of VEC(xmethod_worker_ptr) and corresponding cleanups. I ended up having to C++ify the xmethod_worker code, to be able to have xmethod_workers free their data in destructors, and therefore be able to use vectors of xmethod_worker unique_ptr. The operations in extension_language_ops that act on one instance of xmethod_worker (get result type, get args type, invoke) are transformed to methods of xmethod_worker. xmethod_worker becomes an abstract base class with virtual pure methods which python_xmethod_worker implements. The only xmethod-related operation left in extension_language_ops is get_matching_xmethod_workers, which returns a list of xmethod_workers. The changes are relatively straightforward, but here are some notes on things that may raise eyebrows: - I was not really comfortable with the value_of_xmethod function. At first it looks like a simple getter, so I considered making it a method of xmethod_worker. But actually it creates a value and transfers the ownership of the xmethod_worker to it. It would be a bit weird and error-prone if calling a method on an object silently removed the ownership of the object from the caller. To reflect the behavior more accurately, I renamed it to value_from_xmethod and made it accept an rvalue-reference (so the caller knows it gives away the ownership). I noticed the backlink from xmethod_worker to its owning value was not used, so I removed it. - Some code, like get_matching_xmethod_workers, made each callee fill a new vector, which was then merged in the result vector. I think it's safe if we always pass the same vector around, and each implementation just appends to it. - The clone operation does not seem particularly useful, it is removed in the following patch. gdb/ChangeLog: * 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.
This commit is contained in:
parent
d672364615
commit
ba18742c3a
@ -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
|
||||
|
@ -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. */
|
||||
|
152
gdb/extension.c
152
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. */
|
||||
/* See extension.h. */
|
||||
|
||||
/* 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)
|
||||
void
|
||||
get_matching_xmethod_workers (struct type *type, const char *method_name,
|
||||
std::vector<xmethod_worker_up> *workers)
|
||||
{
|
||||
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. */
|
||||
|
||||
VEC (xmethod_worker_ptr) *
|
||||
get_matching_xmethod_workers (struct type *type, const char *method_name)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
return workers;
|
||||
}
|
||||
/* See extension.h. */
|
||||
|
||||
/* 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. */
|
||||
|
||||
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;
|
||||
type **type_array = NULL;
|
||||
|
||||
gdb_assert (extlang->ops->get_xmethod_arg_types != 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);
|
||||
}
|
||||
"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;
|
||||
type *result_type;
|
||||
|
||||
gdb_assert (extlang->ops->get_xmethod_arg_types != NULL);
|
||||
|
||||
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,
|
||||
|
108
gdb/extension.h
108
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
|
||||
{
|
||||
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. */
|
||||
|
||||
type *get_result_type (value *object, value **args, int nargs);
|
||||
|
||||
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 struct extension_language_defn *extlang;
|
||||
|
||||
/* The extension language specific data for this xmethod worker. */
|
||||
void *data;
|
||||
|
||||
/* The TYPE_CODE_XMETHOD value corresponding to this worker.
|
||||
Always use value_of_xmethod to access it. */
|
||||
struct value *value;
|
||||
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);
|
||||
/* 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 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 *);
|
||||
|
||||
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 */
|
||||
|
@ -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 ();
|
||||
|
||||
DISABLE_COPY_AND_ASSIGN (python_xmethod_worker);
|
||||
|
||||
/* Implementation of xmethod_worker::invoke for Python. */
|
||||
|
||||
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.
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
static struct xmethod_worker *new_python_xmethod_worker (PyObject *item,
|
||||
PyObject *py_obj_type);
|
||||
|
||||
/* Implementation of free_xmethod_worker_data for Python. */
|
||||
|
||||
void
|
||||
gdbpy_free_xmethod_worker_data (const struct extension_language_defn *extlang,
|
||||
void *data)
|
||||
python_xmethod_worker::~python_xmethod_worker ()
|
||||
{
|
||||
struct gdbpy_worker_data *worker_data = (struct gdbpy_worker_data *) 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);
|
||||
|
||||
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 (m_py_worker != NULL && m_this_type != NULL);
|
||||
|
||||
gdb_assert (py_worker != NULL && 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
|
||||
|
@ -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 *);
|
||||
|
@ -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
|
||||
|
52
gdb/valops.c
52
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
|
||||
{
|
||||
|
22
gdb/value.c
22
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)
|
||||
{
|
||||
if (worker->value == NULL)
|
||||
value_from_xmethod (xmethod_worker_up &&worker)
|
||||
{
|
||||
struct value *v;
|
||||
|
||||
v = allocate_value (builtin_type (target_gdbarch ())->xmethod);
|
||||
v->lval = lval_xcallable;
|
||||
v->location.xm_worker = worker;
|
||||
v->location.xm_worker = worker.release ();
|
||||
v->modifiable = 0;
|
||||
worker->value = v;
|
||||
}
|
||||
|
||||
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).
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user