invoke_xmethod & array_view
authorPedro Alves <palves@redhat.com>
Wed, 21 Nov 2018 11:55:12 +0000 (11:55 +0000)
committerPedro Alves <palves@redhat.com>
Wed, 21 Nov 2018 12:06:20 +0000 (12:06 +0000)
This replaces more pointer+length with gdb::array_view.  This time,
around invoke_xmethod, and then propagating the fallout around, which
inevitably leaks to the overload resolution code.

There are several places in the code that want to grab a slice of an
array, by advancing the array pointer, and decreasing the length
pointer.  This patch introduces a pair of new
gdb::array_view::slice(...) methods to make that convenient and clear.
Unit test included.

gdb/ChangeLog:
2018-11-21  Pedro Alves  <palves@redhat.com>

* common/array-view.h (array_view::splice(size_type, size_t)): New.
(array_view::splice(size_type)): New.
* eval.c (eval_call, evaluate_funcall): Adjust to use array_view.
* extension.c (xmethod_worker::get_arg_types): Adjust to return an
std::vector.
(xmethod_worker::get_result_type): Adjust to use gdb::array_view.
* extension.h: Include "common/array-view.h".
(xmethod_worker::invoke): Adjust to use gdb::array_view.
(xmethod_worker::get_arg_types): Adjust to return an std::vector.
(xmethod_worker::get_result_type): Adjust to use gdb::array_view.
(xmethod_worker::do_get_arg_types): Adjust to use std::vector.
(xmethod_worker::do_get_result_type): Adjust to use
gdb::array_view.
* gdbtypes.c (rank_function): Adjust to use gdb::array_view.
* gdbtypes.h: Include "common/array-view.h".
(rank_function): Adjust to use gdb::array_view.
* python/py-xmethods.c (python_xmethod_worker::invoke)
(python_xmethod_worker::do_get_arg_types)
(python_xmethod_worker::do_get_result_type)
(python_xmethod_worker::invoke): Adjust to new interfaces.
* valarith.c (value_user_defined_cpp_op, value_user_defined_op)
(value_x_binop, value_x_unop): Adjust to use gdb::array_view.
* valops.c (find_overload_match, find_oload_champ_namespace)
(find_oload_champ_namespace_loop, find_oload_champ): Adjust to use
gdb:array_view and the new xmethod_worker interfaces.
* value.c (result_type_of_xmethod, call_xmethod): Adjust to use
gdb::array_view.
* value.h (find_overload_match, result_type_of_xmethod)
(call_xmethod): Adjust to use gdb::array_view.
* unittests/array-view-selftests.c: Add slicing tests.

13 files changed:
gdb/ChangeLog
gdb/common/array-view.h
gdb/eval.c
gdb/extension.c
gdb/extension.h
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/python/py-xmethods.c
gdb/unittests/array-view-selftests.c
gdb/valarith.c
gdb/valops.c
gdb/value.c
gdb/value.h

index e315f34..27da643 100644 (file)
@@ -1,5 +1,38 @@
 2018-11-21  Pedro Alves  <palves@redhat.com>
 
+       * common/array-view.h (array_view::splice(size_type, size_t)): New.
+       (array_view::splice(size_type)): New.
+       * eval.c (eval_call, evaluate_funcall): Adjust to use array_view.
+       * extension.c (xmethod_worker::get_arg_types): Adjust to return an
+       std::vector.
+       (xmethod_worker::get_result_type): Adjust to use gdb::array_view.
+       * extension.h: Include "common/array-view.h".
+       (xmethod_worker::invoke): Adjust to use gdb::array_view.
+       (xmethod_worker::get_arg_types): Adjust to return an std::vector.
+       (xmethod_worker::get_result_type): Adjust to use gdb::array_view.
+       (xmethod_worker::do_get_arg_types): Adjust to use std::vector.
+       (xmethod_worker::do_get_result_type): Adjust to use
+       gdb::array_view.
+       * gdbtypes.c (rank_function): Adjust to use gdb::array_view.
+       * gdbtypes.h: Include "common/array-view.h".
+       (rank_function): Adjust to use gdb::array_view.
+       * python/py-xmethods.c (python_xmethod_worker::invoke)
+       (python_xmethod_worker::do_get_arg_types)
+       (python_xmethod_worker::do_get_result_type)
+       (python_xmethod_worker::invoke): Adjust to new interfaces.
+       * valarith.c (value_user_defined_cpp_op, value_user_defined_op)
+       (value_x_binop, value_x_unop): Adjust to use gdb::array_view.
+       * valops.c (find_overload_match, find_oload_champ_namespace)
+       (find_oload_champ_namespace_loop, find_oload_champ): Adjust to use
+       gdb:array_view and the new xmethod_worker interfaces.
+       * value.c (result_type_of_xmethod, call_xmethod): Adjust to use
+       gdb::array_view.
+       * value.h (find_overload_match, result_type_of_xmethod)
+       (call_xmethod): Adjust to use gdb::array_view.
+       * unittests/array-view-selftests.c: Add slicing tests.
+
+2018-11-21  Pedro Alves  <palves@redhat.com>
+
        * ada-lang.c (ada_evaluate_subexp): Adjust to pass an array_view.
        * common/array-view.h (make_array_view): New.
        * compile/compile-object-run.c (compile_object_run): Adjust to
index 9c5fa2a..d7293c7 100644 (file)
@@ -169,6 +169,17 @@ public:
   constexpr size_type size () const noexcept { return m_size; }
   constexpr bool empty () const noexcept { return m_size == 0; }
 
+  /* Slice an array view.  */
+
+  /* Return a new array view over SIZE elements starting at START.  */
+  constexpr array_view<T> slice (size_type start, size_type size) const noexcept
+  { return {m_array + start, size}; }
+
+  /* Return a new array view over all the elements after START,
+     inclusive.  */
+  constexpr array_view<T> slice (size_type start) const noexcept
+  { return {m_array + start, size () - start}; }
+
 private:
   T *m_array;
   size_type m_size;
index 6eb210d..cb40867 100644 (file)
@@ -789,7 +789,9 @@ eval_call (expression *exp, enum noside noside,
       else if (TYPE_CODE (ftype) == TYPE_CODE_XMETHOD)
        {
          type *return_type
-           = result_type_of_xmethod (argvec[0], nargs, argvec + 1);
+           = result_type_of_xmethod (argvec[0],
+                                     gdb::make_array_view (argvec + 1,
+                                                           nargs));
 
          if (return_type == NULL)
            error (_("Xmethod is missing return type."));
@@ -827,7 +829,7 @@ eval_call (expression *exp, enum noside noside,
       return call_internal_function (exp->gdbarch, exp->language_defn,
                                     argvec[0], nargs, argvec + 1);
     case TYPE_CODE_XMETHOD:
-      return call_xmethod (argvec[0], nargs, argvec + 1);
+      return call_xmethod (argvec[0], gdb::make_array_view (argvec + 1, nargs));
     default:
       return call_function_by_hand (argvec[0], default_return_type,
                                    gdb::make_array_view (argvec + 1, nargs));
@@ -1100,7 +1102,8 @@ evaluate_funcall (type *expect_type, expression *exp, int *pos,
       func_name = (char *) alloca (name_len + 1);
       strcpy (func_name, &exp->elts[string_pc + 1].string);
 
-      find_overload_match (&argvec[1], nargs, func_name,
+      find_overload_match (gdb::make_array_view (&argvec[1], nargs),
+                          func_name,
                           NON_METHOD, /* not method */
                           NULL, NULL, /* pass NULL symbol since
                                          symbol is unknown */
@@ -1136,7 +1139,8 @@ evaluate_funcall (type *expect_type, expression *exp, int *pos,
             evaluation.  */
          struct value *valp = NULL;
 
-         (void) find_overload_match (&argvec[1], nargs, tstr,
+         (void) find_overload_match (gdb::make_array_view (&argvec[1], nargs),
+                                     tstr,
                                      METHOD, /* method */
                                      &arg2,  /* the object */
                                      NULL, &valp, NULL,
@@ -1207,7 +1211,7 @@ evaluate_funcall (type *expect_type, expression *exp, int *pos,
          if (op == OP_VAR_VALUE)
            function = exp->elts[save_pos1+2].symbol;
 
-         (void) find_overload_match (&argvec[1], nargs,
+         (void) find_overload_match (gdb::make_array_view (&argvec[1], nargs),
                                      NULL,        /* no need for name */
                                      NON_METHOD,  /* not method */
                                      NULL, function, /* the function */
index e5c0146..31d19b5 100644 (file)
@@ -870,12 +870,12 @@ get_matching_xmethod_workers (struct type *type, const char *method_name,
 
 /* See extension.h.  */
 
-type **
-xmethod_worker::get_arg_types (int *nargs)
+std::vector<type *>
+xmethod_worker::get_arg_types ()
 {
-  type **type_array = NULL;
+  std::vector<type *> type_array;
 
-  ext_lang_rc rc = do_get_arg_types (nargs, &type_array);
+  ext_lang_rc rc = do_get_arg_types (&type_array);
   if (rc == EXT_LANG_RC_ERROR)
     error (_("Error while looking for arg types of a xmethod worker "
             "defined in %s."), m_extlang->capitalized_name);
@@ -886,11 +886,11 @@ xmethod_worker::get_arg_types (int *nargs)
 /* See extension.h.  */
 
 struct type *
-xmethod_worker::get_result_type (value *object, value **args, int nargs)
+xmethod_worker::get_result_type (value *object, gdb::array_view<value *> args)
 {
   type *result_type;
 
-  ext_lang_rc rc = do_get_result_type (object, args, nargs, &result_type);
+  ext_lang_rc rc = do_get_result_type (object, args, &result_type);
   if (rc == EXT_LANG_RC_ERROR)
     {
       error (_("Error while fetching result type of an xmethod worker "
index 0c8c4ee..b9314c0 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "mi/mi-cmds.h" /* For PRINT_NO_VALUES, etc.  */
 #include "common/vec.h"
+#include "common/array-view.h"
 
 struct breakpoint;
 struct command_line;
@@ -186,38 +187,35 @@ struct xmethod_worker
   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.  */
+     The method is invoked on OBJ with arguments in the ARGS array.  */
 
-  virtual value *invoke (value *obj, value **args, int nargs) = 0;
+  virtual value *invoke (value *obj, gdb::array_view<value *> args) = 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.  */
+     The type of the 'this' object is returned as the first element of
+     the vector.  */
 
-  type **get_arg_types (int *nargs);
+  std::vector<type *> get_arg_types ();
 
   /* Return the type of the result of the xmethod encapsulated in this worker.
-     OBJECT, ARGS, NARGS are the same as for invoke.  */
+     OBJECT and ARGS are the same as for invoke.  */
 
-  type *get_result_type (value *object, value **args, int nargs);
+  type *get_result_type (value *object, gdb::array_view<value *> args);
 
 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.  */
+  /* Return the types of the arguments the method takes.  The types
+     are returned in TYPE_ARGS, one per argument.  */
 
   virtual enum ext_lang_rc do_get_arg_types
-    (int *nargs, struct type ***arg_types) = 0;
+    (std::vector<type *> *type_args) = 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.  */
+  /* Fetch the type of the result of the method implemented by this
+     worker.  OBJECT and ARGS 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 value *obj, gdb::array_view<value *> args,
      struct type **result_type_ptr) = 0;
 
   /* The language the xmethod worker is implemented in.  */
index 9e87b8f..4160d99 100644 (file)
@@ -3464,21 +3464,20 @@ compare_badness (struct badness_vector *a, struct badness_vector *b)
     }
 }
 
-/* Rank a function by comparing its parameter types (PARMS, length
-   NPARMS), to the types of an argument list (ARGS, length NARGS).
-   Return a pointer to a badness vector.  This has NARGS + 1
-   entries.  */
+/* Rank a function by comparing its parameter types (PARMS), to the
+   types of an argument list (ARGS).  Return a pointer to a badness
+   vector.  This has ARGS.size() + 1 entries.  */
 
 struct badness_vector *
-rank_function (struct type **parms, int nparms, 
-              struct value **args, int nargs)
+rank_function (gdb::array_view<type *> parms,
+              gdb::array_view<value *> args)
 {
   int i;
   struct badness_vector *bv = XNEW (struct badness_vector);
-  int min_len = nparms < nargs ? nparms : nargs;
+  size_t min_len = std::min (parms.size (), args.size ());
 
-  bv->length = nargs + 1;      /* add 1 for the length-match rank.  */
-  bv->rank = XNEWVEC (struct rank, nargs + 1);
+  bv->length = args.size () + 1;       /* add 1 for the length-match rank.  */
+  bv->rank = XNEWVEC (struct rank, args.size () + 1);
 
   /* First compare the lengths of the supplied lists.
      If there is a mismatch, set it to a high value.  */
@@ -3487,7 +3486,7 @@ rank_function (struct type **parms, int nparms,
      arguments and ellipsis parameter lists, we should consider those
      and rank the length-match more finely.  */
 
-  LENGTH_MATCH (bv) = (nargs != nparms)
+  LENGTH_MATCH (bv) = (args.size () != parms.size ())
                      ? LENGTH_MISMATCH_BADNESS
                      : EXACT_MATCH_BADNESS;
 
@@ -3497,7 +3496,7 @@ rank_function (struct type **parms, int nparms,
                                 args[i - 1]);
 
   /* If more arguments than parameters, add dummy entries.  */
-  for (i = min_len + 1; i <= nargs; i++)
+  for (i = min_len + 1; i <= args.size (); i++)
     bv->rank[i] = TOO_FEW_PARAMS_BADNESS;
 
   return bv;
index a115857..731b18d 100644 (file)
@@ -45,6 +45,7 @@
  */
 
 #include "hashtab.h"
+#include "common/array-view.h"
 #include "common/offset-type.h"
 #include "common/enum-flags.h"
 #include "common/underlying.h"
@@ -2044,8 +2045,8 @@ extern int compare_ranks (struct rank a, struct rank b);
 
 extern int compare_badness (struct badness_vector *, struct badness_vector *);
 
-extern struct badness_vector *rank_function (struct type **, int,
-                                            struct value **, int);
+extern struct badness_vector *rank_function (gdb::array_view<type *> parms,
+                                            gdb::array_view<value *> args);
 
 extern struct rank rank_one_type (struct type *, struct type *,
                                  struct value *);
index 8e616cd..1c96b58 100644 (file)
@@ -46,11 +46,11 @@ struct python_xmethod_worker : xmethod_worker
 
   /* Implementation of xmethod_worker::invoke for Python.  */
 
-  value *invoke (value *obj, value **args, int nargs) override;
+  value *invoke (value *obj, gdb::array_view<value *> args) override;
 
   /* Implementation of xmethod_worker::do_get_arg_types for Python.  */
 
-  ext_lang_rc do_get_arg_types (int *nargs, type ***arg_types) override;
+  ext_lang_rc do_get_arg_types (std::vector<type *> *type_args) override;
 
   /* Implementation of xmethod_worker::do_get_result_type for Python.
 
@@ -58,7 +58,7 @@ struct python_xmethod_worker : xmethod_worker
      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,
+  ext_lang_rc do_get_result_type (value *obj, gdb::array_view<value *> args,
                                  type **result_type_ptr) override;
 
 private:
@@ -293,7 +293,7 @@ gdbpy_get_matching_xmethod_workers
 /* See declaration.  */
 
 ext_lang_rc
-python_xmethod_worker::do_get_arg_types (int *nargs, type ***arg_types)
+python_xmethod_worker::do_get_arg_types (std::vector<type *> *arg_types)
 {
   /* The gdbpy_enter object needs to be placed first, so that it's the last to
      be destroyed.  */
@@ -302,10 +302,6 @@ python_xmethod_worker::do_get_arg_types (int *nargs, type ***arg_types)
   int i = 1, arg_count;
   gdbpy_ref<> list_iter;
 
-  /* Set nargs to -1 so that any premature return from this function returns
-     an invalid/unusable number of arg types.  */
-  *nargs = -1;
-
   gdbpy_ref<> get_arg_types_method
     (PyObject_GetAttrString (m_py_worker, get_arg_types_method_name));
   if (get_arg_types_method == NULL)
@@ -345,8 +341,7 @@ python_xmethod_worker::do_get_arg_types (int *nargs, type ***arg_types)
     arg_count = 1;
 
   /* Include the 'this' argument in the size.  */
-  gdb::unique_xmalloc_ptr<struct type *> type_array
-    (XCNEWVEC (struct type *, arg_count + 1));
+  arg_types->resize (arg_count + 1);
   i = 1;
   if (list_iter != NULL)
     {
@@ -373,7 +368,7 @@ python_xmethod_worker::do_get_arg_types (int *nargs, type ***arg_types)
              return EXT_LANG_RC_ERROR;
            }
 
-         (type_array.get ())[i] = arg_type;
+         (*arg_types)[i] = arg_type;
          i++;
        }
     }
@@ -393,7 +388,7 @@ python_xmethod_worker::do_get_arg_types (int *nargs, type ***arg_types)
        }
       else
        {
-         (type_array.get ())[i] = arg_type;
+         (*arg_types)[i] = arg_type;
          i++;
        }
     }
@@ -402,10 +397,8 @@ python_xmethod_worker::do_get_arg_types (int *nargs, type ***arg_types)
      be a 'const' value.  Hence, create a 'const' variant of the 'this' pointer
      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;
-  *arg_types = type_array.release ();
+  (*arg_types)[0] = make_cv_type (1, 0, lookup_pointer_type (obj_type),
+                                 NULL);
 
   return EXT_LANG_RC_OK;
 }
@@ -413,7 +406,8 @@ python_xmethod_worker::do_get_arg_types (int *nargs, type ***arg_types)
 /* See declaration.  */
 
 ext_lang_rc
-python_xmethod_worker::do_get_result_type (value *obj, value **args, int nargs,
+python_xmethod_worker::do_get_result_type (value *obj,
+                                          gdb::array_view<value *> args,
                                           type **result_type_ptr)
 {
   struct type *obj_type, *this_type;
@@ -461,7 +455,7 @@ python_xmethod_worker::do_get_result_type (value *obj, value **args, int nargs,
       return EXT_LANG_RC_ERROR;
     }
 
-  gdbpy_ref<> py_arg_tuple (PyTuple_New (nargs + 1));
+  gdbpy_ref<> py_arg_tuple (PyTuple_New (args.size () + 1));
   if (py_arg_tuple == NULL)
     {
       gdbpy_print_stack ();
@@ -472,7 +466,7 @@ python_xmethod_worker::do_get_result_type (value *obj, value **args, int nargs,
      release.  */
   PyTuple_SET_ITEM (py_arg_tuple.get (), 0, py_value_obj.release ());
 
-  for (i = 0; i < nargs; i++)
+  for (i = 0; i < args.size (); i++)
     {
       PyObject *py_value_arg = value_to_value_object (args[i]);
 
@@ -508,8 +502,8 @@ python_xmethod_worker::do_get_result_type (value *obj, value **args, int nargs,
 /* See declaration.  */
 
 struct value *
-python_xmethod_worker::invoke (struct value *obj, struct value **args,
-                              int nargs)
+python_xmethod_worker::invoke (struct value *obj,
+                              gdb::array_view<value *> args)
 {
   gdbpy_enter enter_py (get_current_arch (), current_language);
 
@@ -546,7 +540,7 @@ python_xmethod_worker::invoke (struct value *obj, struct value **args,
       error (_("Error while executing Python code."));
     }
 
-  gdbpy_ref<> py_arg_tuple (PyTuple_New (nargs + 1));
+  gdbpy_ref<> py_arg_tuple (PyTuple_New (args.size () + 1));
   if (py_arg_tuple == NULL)
     {
       gdbpy_print_stack ();
@@ -557,7 +551,7 @@ python_xmethod_worker::invoke (struct value *obj, struct value **args,
      release.  */
   PyTuple_SET_ITEM (py_arg_tuple.get (), 0, py_value_obj.release ());
 
-  for (i = 0; i < nargs; i++)
+  for (i = 0; i < args.size (); i++)
     {
       PyObject *py_value_arg = value_to_value_object (args[i]);
 
index 74defa1..746062c 100644 (file)
@@ -496,6 +496,28 @@ run_tests ()
     for (size_t i = 0; i < len; i++)
       SELF_CHECK (view[i] == data[i]);
   }
+
+  /* Test slicing.  */
+  {
+    gdb_byte data[] = {0x55, 0x66, 0x77, 0x88, 0x99};
+    gdb::array_view<gdb_byte> view = data;
+
+    {
+      auto slc = view.slice (1, 3);
+      SELF_CHECK (slc.data () == data + 1);
+      SELF_CHECK (slc.size () == 3);
+      SELF_CHECK (slc[0] == data[1]);
+      SELF_CHECK (slc[0] == view[1]);
+    }
+
+    {
+      auto slc = view.slice (2);
+      SELF_CHECK (slc.data () == data + 2);
+      SELF_CHECK (slc.size () == 3);
+      SELF_CHECK (slc[0] == view[2]);
+      SELF_CHECK (slc[0] == data[2]);
+    }
+  }
 }
 
 } /* namespace array_view_tests */
index 875f547..3a59ada 100644 (file)
@@ -281,14 +281,14 @@ unop_user_defined_p (enum exp_opcode op, struct value *arg1)
    situations or combinations thereof.  */
 
 static struct value *
-value_user_defined_cpp_op (struct value **args, int nargs, char *oper,
+value_user_defined_cpp_op (gdb::array_view<value *> args, char *oper,
                            int *static_memfuncp, enum noside noside)
 {
 
   struct symbol *symp = NULL;
   struct value *valp = NULL;
 
-  find_overload_match (args, nargs, oper, BOTH /* could be method */,
+  find_overload_match (args, oper, BOTH /* could be method */,
                        &args[0] /* objp */,
                        NULL /* pass NULL symbol since symbol is unknown */,
                        &valp, &symp, static_memfuncp, 0, noside);
@@ -312,19 +312,19 @@ value_user_defined_cpp_op (struct value **args, int nargs, char *oper,
    function, otherwise return NULL.  */
 
 static struct value *
-value_user_defined_op (struct value **argp, struct value **args, char *name,
-                       int *static_memfuncp, int nargs, enum noside noside)
+value_user_defined_op (struct value **argp, gdb::array_view<value *> args,
+                      char *name, int *static_memfuncp, enum noside noside)
 {
   struct value *result = NULL;
 
   if (current_language->la_language == language_cplus)
     {
-      result = value_user_defined_cpp_op (args, nargs, name, static_memfuncp,
+      result = value_user_defined_cpp_op (args, name, static_memfuncp,
                                          noside);
     }
   else
-    result = value_struct_elt (argp, args, name, static_memfuncp,
-                               "structure");
+    result = value_struct_elt (argp, args.data (), name, static_memfuncp,
+                              "structure");
 
   return result;
 }
@@ -342,7 +342,6 @@ struct value *
 value_x_binop (struct value *arg1, struct value *arg2, enum exp_opcode op,
               enum exp_opcode otherop, enum noside noside)
 {
-  struct value **argvec;
   char *ptr;
   char tstr[13];
   int static_memfuncp;
@@ -356,10 +355,11 @@ value_x_binop (struct value *arg1, struct value *arg2, enum exp_opcode op,
   if (TYPE_CODE (check_typedef (value_type (arg1))) != TYPE_CODE_STRUCT)
     error (_("Can't do that binary op on that type")); /* FIXME be explicit */
 
-  argvec = (struct value **) alloca (sizeof (struct value *) * 4);
+  value *argvec_storage[3];
+  gdb::array_view<value *> argvec = argvec_storage;
+
   argvec[1] = value_addr (arg1);
   argvec[2] = arg2;
-  argvec[3] = 0;
 
   /* Make the right function name up.  */
   strcpy (tstr, "operator__");
@@ -469,15 +469,15 @@ value_x_binop (struct value *arg1, struct value *arg2, enum exp_opcode op,
       error (_("Invalid binary operation specified."));
     }
 
-  argvec[0] = value_user_defined_op (&arg1, argvec + 1, tstr,
-                                     &static_memfuncp, 2, noside);
+  argvec[0] = value_user_defined_op (&arg1, argvec.slice (1), tstr,
+                                    &static_memfuncp, noside);
 
   if (argvec[0])
     {
       if (static_memfuncp)
        {
          argvec[1] = argvec[0];
-         argvec++;
+         argvec = argvec.slice (1);
        }
       if (TYPE_CODE (value_type (argvec[0])) == TYPE_CODE_XMETHOD)
        {
@@ -486,13 +486,13 @@ value_x_binop (struct value *arg1, struct value *arg2, enum exp_opcode op,
          if (noside == EVAL_AVOID_SIDE_EFFECTS)
            {
              struct type *return_type
-               = result_type_of_xmethod (argvec[0], 2, argvec + 1);
+               = result_type_of_xmethod (argvec[0], argvec.slice (1));
 
              if (return_type == NULL)
                error (_("Xmethod is missing return type."));
              return value_zero (return_type, VALUE_LVAL (arg1));
            }
-         return call_xmethod (argvec[0], 2, argvec + 1);
+         return call_xmethod (argvec[0], argvec.slice (1));
        }
       if (noside == EVAL_AVOID_SIDE_EFFECTS)
        {
@@ -503,7 +503,7 @@ value_x_binop (struct value *arg1, struct value *arg2, enum exp_opcode op,
          return value_zero (return_type, VALUE_LVAL (arg1));
        }
       return call_function_by_hand (argvec[0], NULL,
-                                   {argvec + 1, 2u - static_memfuncp});
+                                   argvec.slice (1, 2 - static_memfuncp));
     }
   throw_error (NOT_FOUND_ERROR,
                _("member function %s not found"), tstr);
@@ -519,7 +519,6 @@ struct value *
 value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside)
 {
   struct gdbarch *gdbarch = get_type_arch (value_type (arg1));
-  struct value **argvec;
   char *ptr;
   char tstr[13], mangle_tstr[13];
   int static_memfuncp, nargs;
@@ -532,7 +531,9 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside)
   if (TYPE_CODE (check_typedef (value_type (arg1))) != TYPE_CODE_STRUCT)
     error (_("Can't do that unary op on that type"));  /* FIXME be explicit */
 
-  argvec = (struct value **) alloca (sizeof (struct value *) * 4);
+  value *argvec_storage[3];
+  gdb::array_view<value *> argvec = argvec_storage;
+
   argvec[1] = value_addr (arg1);
   argvec[2] = 0;
 
@@ -584,16 +585,15 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside)
       error (_("Invalid unary operation specified."));
     }
 
-  argvec[0] = value_user_defined_op (&arg1, argvec + 1, tstr,
-                                     &static_memfuncp, nargs, noside);
+  argvec[0] = value_user_defined_op (&arg1, argvec.slice (1, nargs), tstr,
+                                    &static_memfuncp, noside);
 
   if (argvec[0])
     {
       if (static_memfuncp)
        {
          argvec[1] = argvec[0];
-         nargs --;
-         argvec++;
+         argvec = argvec.slice (1);
        }
       if (TYPE_CODE (value_type (argvec[0])) == TYPE_CODE_XMETHOD)
        {
@@ -602,13 +602,13 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside)
          if (noside == EVAL_AVOID_SIDE_EFFECTS)
            {
              struct type *return_type
-               = result_type_of_xmethod (argvec[0], 1, argvec + 1);
+               = result_type_of_xmethod (argvec[0], argvec[1]);
 
              if (return_type == NULL)
                error (_("Xmethod is missing return type."));
              return value_zero (return_type, VALUE_LVAL (arg1));
            }
-         return call_xmethod (argvec[0], 1, argvec + 1);
+         return call_xmethod (argvec[0], argvec[1]);
        }
       if (noside == EVAL_AVOID_SIDE_EFFECTS)
        {
@@ -619,7 +619,7 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside)
          return value_zero (return_type, VALUE_LVAL (arg1));
        }
       return call_function_by_hand (argvec[0], NULL,
-                                   gdb::make_array_view (argvec + 1, nargs));
+                                   argvec.slice (1, nargs));
     }
   throw_error (NOT_FOUND_ERROR,
                _("member function %s not found"), tstr);
index 4758b5c..f0e53a7 100644 (file)
@@ -54,20 +54,19 @@ static struct value *search_struct_method (const char *, struct value **,
                                           struct value **,
                                           LONGEST, int *, struct type *);
 
-static int find_oload_champ_namespace (struct value **, int,
+static int find_oload_champ_namespace (gdb::array_view<value *> args,
                                       const char *, const char *,
                                       struct symbol ***,
                                       struct badness_vector **,
                                       const int no_adl);
 
-static
-int find_oload_champ_namespace_loop (struct value **, int,
-                                    const char *, const char *,
-                                    int, struct symbol ***,
-                                    struct badness_vector **, int *,
-                                    const int no_adl);
+static int find_oload_champ_namespace_loop (gdb::array_view<value *> args,
+                                           const char *, const char *,
+                                           int, struct symbol ***,
+                                           struct badness_vector **, int *,
+                                           const int no_adl);
 
-static int find_oload_champ (struct value **, int, int,
+static int find_oload_champ (gdb::array_view<value *> args, int,
                             struct fn_field *,
                             const std::vector<xmethod_worker_up> *,
                             struct symbol **, struct badness_vector **);
@@ -2446,11 +2445,11 @@ value_find_oload_method_list (struct value **argp, const char *method,
                    basetype, boffset);
 }
 
-/* Given an array of arguments (ARGS) (which includes an
-   entry for "this" in the case of C++ methods), the number of
-   arguments NARGS, the NAME of a function, and whether it's a method or
-   not (METHOD), find the best function that matches on the argument types
-   according to the overload resolution rules.
+/* Given an array of arguments (ARGS) (which includes an entry for
+   "this" in the case of C++ methods), the NAME of a function, and
+   whether it's a method or not (METHOD), find the best function that
+   matches on the argument types according to the overload resolution
+   rules.
 
    METHOD can be one of three values:
      NON_METHOD for non-member functions.
@@ -2493,7 +2492,7 @@ value_find_oload_method_list (struct value **argp, const char *method,
    resolution is permitted.  */
 
 int
-find_overload_match (struct value **args, int nargs,
+find_overload_match (gdb::array_view<value *> args,
                     const char *name, enum oload_search_type method,
                     struct value **objp, struct symbol *fsym,
                     struct value **valp, struct symbol **symp, 
@@ -2578,12 +2577,12 @@ find_overload_match (struct value **args, int nargs,
        {
          gdb_assert (TYPE_SELF_TYPE (fns_ptr[0].type) != NULL);
 
-         src_method_oload_champ = find_oload_champ (args, nargs,
+         src_method_oload_champ = find_oload_champ (args,
                                                     num_fns, fns_ptr, NULL,
                                                     NULL, &src_method_badness);
 
          src_method_match_quality = classify_oload_match
-           (src_method_badness, nargs,
+           (src_method_badness, args.size (),
             oload_method_static_p (fns_ptr, src_method_oload_champ));
 
          make_cleanup (xfree, src_method_badness);
@@ -2591,11 +2590,10 @@ find_overload_match (struct value **args, int nargs,
 
       if (!xm_worker_vec.empty ())
        {
-         ext_method_oload_champ = find_oload_champ (args, nargs,
-                                                    0, NULL, &xm_worker_vec,
+         ext_method_oload_champ = find_oload_champ (args, 0, NULL, &xm_worker_vec,
                                                     NULL, &ext_method_badness);
          ext_method_match_quality = classify_oload_match (ext_method_badness,
-                                                          nargs, 0);
+                                                          args.size (), 0);
          make_cleanup (xfree, ext_method_badness);
        }
 
@@ -2708,7 +2706,7 @@ find_overload_match (struct value **args, int nargs,
           return 0;
         }
 
-      func_oload_champ = find_oload_champ_namespace (args, nargs,
+      func_oload_champ = find_oload_champ_namespace (args,
                                                      func_name,
                                                      qualified_name,
                                                      &oload_syms,
@@ -2716,7 +2714,8 @@ find_overload_match (struct value **args, int nargs,
                                                      no_adl);
 
       if (func_oload_champ >= 0)
-       func_match_quality = classify_oload_match (func_badness, nargs, 0);
+       func_match_quality = classify_oload_match (func_badness,
+                                                  args.size (), 0);
 
       make_cleanup (xfree, oload_syms);
       make_cleanup (xfree, func_badness);
@@ -2855,7 +2854,7 @@ find_overload_match (struct value **args, int nargs,
    performned.  */
 
 static int
-find_oload_champ_namespace (struct value **args, int nargs,
+find_oload_champ_namespace (gdb::array_view<value *> args,
                            const char *func_name,
                            const char *qualified_name,
                            struct symbol ***oload_syms,
@@ -2864,7 +2863,7 @@ find_oload_champ_namespace (struct value **args, int nargs,
 {
   int oload_champ;
 
-  find_oload_champ_namespace_loop (args, nargs,
+  find_oload_champ_namespace_loop (args,
                                   func_name,
                                   qualified_name, 0,
                                   oload_syms, oload_champ_bv,
@@ -2884,7 +2883,7 @@ find_oload_champ_namespace (struct value **args, int nargs,
    *OLOAD_CHAMP_BV.  */
 
 static int
-find_oload_champ_namespace_loop (struct value **args, int nargs,
+find_oload_champ_namespace_loop (gdb::array_view<value *> args,
                                 const char *func_name,
                                 const char *qualified_name,
                                 int namespace_len,
@@ -2921,7 +2920,7 @@ find_oload_champ_namespace_loop (struct value **args, int nargs,
     {
       searched_deeper = 1;
 
-      if (find_oload_champ_namespace_loop (args, nargs,
+      if (find_oload_champ_namespace_loop (args,
                                           func_name, qualified_name,
                                           next_namespace_len,
                                           oload_syms, oload_champ_bv,
@@ -2956,16 +2955,16 @@ find_oload_champ_namespace_loop (struct value **args, int nargs,
 
       /* Prepare list of argument types for overload resolution.  */
       arg_types = (struct type **)
-       alloca (nargs * (sizeof (struct type *)));
-      for (ix = 0; ix < nargs; ix++)
+       alloca (args.size () * (sizeof (struct type *)));
+      for (ix = 0; ix < args.size (); ix++)
        arg_types[ix] = value_type (args[ix]);
-      make_symbol_overload_list_adl (arg_types, nargs, func_name);
+      make_symbol_overload_list_adl (arg_types, args.size (), func_name);
     }
 
   while (new_oload_syms[num_fns])
     ++num_fns;
 
-  new_oload_champ = find_oload_champ (args, nargs, num_fns,
+  new_oload_champ = find_oload_champ (args, num_fns,
                                      NULL, NULL, new_oload_syms,
                                      &new_oload_champ_bv);
 
@@ -2977,7 +2976,7 @@ find_oload_champ_namespace_loop (struct value **args, int nargs,
      it's a bad match.  */
 
   if (new_oload_champ != -1
-      && classify_oload_match (new_oload_champ_bv, nargs, 0) == STANDARD)
+      && classify_oload_match (new_oload_champ_bv, args.size (), 0) == STANDARD)
     {
       *oload_syms = new_oload_syms;
       *oload_champ = new_oload_champ;
@@ -3002,11 +3001,10 @@ find_oload_champ_namespace_loop (struct value **args, int nargs,
     }
 }
 
-/* Look for a function to take NARGS args of ARGS.  Find
-   the best match from among the overloaded methods or functions
-   given by FNS_PTR or OLOAD_SYMS or XM_WORKER_VEC, respectively.
-   One, and only one of FNS_PTR, OLOAD_SYMS and XM_WORKER_VEC can be
-   non-NULL.
+/* Look for a function to take ARGS.  Find the best match from among
+   the overloaded methods or functions given by FNS_PTR or OLOAD_SYMS
+   or XM_WORKER_VEC, respectively.  One, and only one of FNS_PTR,
+   OLOAD_SYMS and XM_WORKER_VEC can be non-NULL.
 
    If XM_WORKER_VEC is NULL, then the length of the arrays FNS_PTR
    or OLOAD_SYMS (whichever is non-NULL) is specified in NUM_FNS.
@@ -3017,7 +3015,7 @@ find_oload_champ_namespace_loop (struct value **args, int nargs,
    It is the caller's responsibility to free *OLOAD_CHAMP_BV.  */
 
 static int
-find_oload_champ (struct value **args, int nargs,
+find_oload_champ (gdb::array_view<value *> args,
                  int num_fns, struct fn_field *fns_ptr,
                  const std::vector<xmethod_worker_up> *xm_worker_vec,
                  struct symbol **oload_syms,
@@ -3047,16 +3045,17 @@ find_oload_champ (struct value **args, int nargs,
     {
       int jj;
       int static_offset = 0;
-      int nparms;
-      struct type **parm_types;
+      std::vector<type *> parm_types;
 
       if (xm_worker_vec != NULL)
        {
          xmethod_worker *worker = (*xm_worker_vec)[ix].get ();
-         parm_types = worker->get_arg_types (&nparms);
+         parm_types = worker->get_arg_types ();
        }
       else
        {
+         size_t nparms;
+
          if (fns_ptr != NULL)
            {
              nparms = TYPE_NFIELDS (TYPE_FN_FIELD_TYPE (fns_ptr, ix));
@@ -3065,19 +3064,21 @@ find_oload_champ (struct value **args, int nargs,
          else
            nparms = TYPE_NFIELDS (SYMBOL_TYPE (oload_syms[ix]));
 
-         parm_types = XNEWVEC (struct type *, nparms);
+         parm_types.reserve (nparms);
          for (jj = 0; jj < nparms; jj++)
-           parm_types[jj] = (fns_ptr != NULL
-                             ? (TYPE_FN_FIELD_ARGS (fns_ptr, ix)[jj].type)
-                             : TYPE_FIELD_TYPE (SYMBOL_TYPE (oload_syms[ix]),
-                                                jj));
+           {
+             type *t = (fns_ptr != NULL
+                        ? (TYPE_FN_FIELD_ARGS (fns_ptr, ix)[jj].type)
+                        : TYPE_FIELD_TYPE (SYMBOL_TYPE (oload_syms[ix]),
+                                           jj));
+             parm_types.push_back (t);
+           }
        }
 
       /* Compare parameter types to supplied argument types.  Skip
          THIS for static methods.  */
-      bv = rank_function (parm_types, nparms, 
-                         args + static_offset,
-                         nargs - static_offset);
+      bv = rank_function (parm_types,
+                         args.slice (static_offset));
 
       if (!*oload_champ_bv)
        {
@@ -3103,24 +3104,23 @@ find_oload_champ (struct value **args, int nargs,
          default:
            break;
          }
-      xfree (parm_types);
       if (overload_debug)
        {
          if (fns_ptr != NULL)
            fprintf_filtered (gdb_stderr,
                              "Overloaded method instance %s, # of parms %d\n",
-                             fns_ptr[ix].physname, nparms);
+                             fns_ptr[ix].physname, (int) parm_types.size ());
          else if (xm_worker_vec != NULL)
            fprintf_filtered (gdb_stderr,
                              "Xmethod worker, # of parms %d\n",
-                             nparms);
+                             (int) parm_types.size ());
          else
            fprintf_filtered (gdb_stderr,
                              "Overloaded function instance "
                              "%s # of parms %d\n",
                              SYMBOL_DEMANGLED_NAME (oload_syms[ix]), 
-                             nparms);
-         for (jj = 0; jj < nargs - static_offset; jj++)
+                             (int) parm_types.size ());
+         for (jj = 0; jj < args.size () - static_offset; jj++)
            fprintf_filtered (gdb_stderr,
                              "...Badness @ %d : %d\n", 
                              jj, bv->rank[jj].rank);
index 38fc18e..c7b8468 100644 (file)
@@ -2583,24 +2583,23 @@ value_from_xmethod (xmethod_worker_up &&worker)
 /* Return the type of the result of TYPE_CODE_XMETHOD value METHOD.  */
 
 struct type *
-result_type_of_xmethod (struct value *method, int argc, struct value **argv)
+result_type_of_xmethod (struct value *method, gdb::array_view<value *> argv)
 {
   gdb_assert (TYPE_CODE (value_type (method)) == TYPE_CODE_XMETHOD
-             && method->lval == lval_xcallable && argc > 0);
+             && method->lval == lval_xcallable && !argv.empty ());
 
-  return method->location.xm_worker->get_result_type
-    (argv[0], argv + 1, argc - 1);
+  return method->location.xm_worker->get_result_type (argv[0], argv.slice (1));
 }
 
 /* Call the xmethod corresponding to the TYPE_CODE_XMETHOD value METHOD.  */
 
 struct value *
-call_xmethod (struct value *method, int argc, struct value **argv)
+call_xmethod (struct value *method, gdb::array_view<value *> argv)
 {
   gdb_assert (TYPE_CODE (value_type (method)) == TYPE_CODE_XMETHOD
-             && method->lval == lval_xcallable && argc > 0);
+             && method->lval == lval_xcallable && !argv.empty ());
 
-  return method->location.xm_worker->invoke (argv[0], argv + 1, argc - 1);
+  return method->location.xm_worker->invoke (argv[0], argv.slice (1));
 }
 \f
 /* Extract a value as a C number (either long or double).
index 4d75c96..54caa58 100644 (file)
@@ -835,7 +835,7 @@ extern struct value *value_static_field (struct type *type, int fieldno);
 
 enum oload_search_type { NON_METHOD, METHOD, BOTH };
 
-extern int find_overload_match (struct value **args, int nargs,
+extern int find_overload_match (gdb::array_view<value *> args,
                                const char *name,
                                enum oload_search_type method,
                                struct value **objp, struct symbol *fsym,
@@ -1175,10 +1175,10 @@ char *value_internal_function_name (struct value *);
 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);
+                                           gdb::array_view<value *> argv);
 
 extern struct value *call_xmethod (struct value *method,
-                                  int argc, struct value **argv);
+                                  gdb::array_view<value *> argv);
 
 /* Given a discriminated union type and some corresponding value
    contents, this will return the field index of the currently active