C++ify xmethod_worker, get rid of VEC(xmethod_worker_ptr)
authorSimon Marchi <simon.marchi@polymtl.ca>
Sun, 7 Jan 2018 14:25:32 +0000 (09:25 -0500)
committerSimon Marchi <simon.marchi@ericsson.com>
Sun, 7 Jan 2018 14:25:32 +0000 (09:25 -0500)
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.

gdb/ChangeLog
gdb/extension-priv.h
gdb/extension.c
gdb/extension.h
gdb/python/py-xmethods.c
gdb/python/python-internal.h
gdb/python/python.c
gdb/valops.c
gdb/value.c
gdb/value.h

index 24ccfe68824cb139fcf25a618fe1f38f2f3263e2..65b9ef9a86407fa985e115d4c88d4f072e2f34f1 100644 (file)
@@ -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
index 8fbf1b0c769187e5a064ac2d165d44f76e92927c..5843479f93c24f1f322c552d43bf4e0aa9dbd142 100644 (file)
 #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.  */
index a1ee3510a6f320fe487ca54f5e3633b99a9a5d64..224b05c7ed07114cb43da366a7d29a9345451e22 100644 (file)
@@ -850,68 +850,18 @@ check_quit_flag (void)
 
   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
@@ -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);
-}
-\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,
index 04f90490ebb16993064620b91af643f311a6271b..475d712b4209dab25d2ff10adc0ae39ed436d427 100644 (file)
@@ -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;
 
-\f
 /* 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 */
index 750f26357967b41cdd97d76af961def58954ae73..f4064c29dcff88e8a3a33320ac782bdf9f19f424 100644 (file)
@@ -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
index f32a2582093d67bc05933a6e4048d6a636f475f4..f38f0b30cb8a0fc6ca94dfc989d74d04c1514c95 100644 (file)
@@ -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);
+
 \f
 PyObject *gdbpy_history (PyObject *self, PyObject *args);
 PyObject *gdbpy_breakpoints (PyObject *, PyObject *);
index 4844c86c5433687cadf07ed091150b1855120e07..9eae8a1aef2dfce9763278d3512b509b9a874b74 100644 (file)
@@ -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
index 9525dc8499ecb03d7f2330df01cbd319bb1599a7..8fccfe930191c2cbf19c4bee41df5776d741bf64 100644 (file)
@@ -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
        {
index d4b4673f66e4d7bcd7c9beb7c045c7cbe3635e76..9a144fb7fb62439b52a4ec5ebd25c81c050b5957 100644 (file)
@@ -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)
     }
 }
 \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.  */
@@ -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);
 }
 \f
 /* Extract a value as a C number (either long or double).
index 7dc67dc72160cc191ef7b5f75823176b3b8cffbb..e0ea22d4e52f98a25a950d1c72ec5006a80ad1fd 100644 (file)
@@ -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);