[PATCH] [gdb/python] Convert valpy_call to the "python safety" approach

Tom de Vries <[email protected]>
Newsgroups gmane.comp.gdb.patches
Message-ID <[email protected]>
Update function valpy_call to the "python safety" approach.

I added a wrap_tp_call template to enforce and handle the new prototype of
valpy_call:
...
-  valpy_call,                    /*tp_call*/
+  wrap_tp_call<valpy_call>,      /*tp_call*/
...

I also made it explicit that the keywords argument is unused.

I added wrapper function gdbpy_tuple_check to wrap PyTuple_Check.  It always
succeeds, so strictly speaking it doesn't need a wrapper, but always using
wrapper function and trusting them to DDRT is easier than remembering which
functions always succeed.

I also added this template:
...
template<typename T>
T
gdbpy_require_nonnull (T val)
{
  if (val == nullptr)
    throw gdb_python_exception ();
  return val;
}
...
to do this simplification:
...
-         vargs[i] = convert_value_from_python (item);
+         vargs[i] = gdbpy_require_nonnull (convert_value_from_python (item));
-         if (vargs[i] == NULL)
-           throw gdb_python_exception ();
...
as a placeholder until convert_value_from_python is converted.

Tested on x86_64-linux.
---
 gdb/python/py-safety.h   |  9 ++++
 gdb/python/py-value.c    | 89 +++++++++++++++-------------------------
 gdb/python/py-wrappers.h | 18 ++++++++
 3 files changed, 61 insertions(+), 55 deletions(-)

diff --git a/gdb/python/py-safety.h b/gdb/python/py-safety.h
index 3294f38c8b6..56f7ddd3b85 100644
--- a/gdb/python/py-safety.h
+++ b/gdb/python/py-safety.h
@@ -343,4 +343,13 @@ wrap_setter (PyObject *arg, PyObject *value, void *closure)
   return 0;
 }
 
+/* A function that wraps a "tp_call" method.  */
+template<gdbpy_ref<> F (gdbpy_borrowed_ref<>, gdbpy_borrowed_ref<>,
+			gdbpy_opt_borrowed_ref<>)>
+PyObject *
+wrap_tp_call (PyObject *self, PyObject *args, PyObject *keywords)
+{
+  return safety_details::wrapped_function<F> (self, args, keywords);
+}
+
 #endif /* GDB_PYTHON_PY_SAFETY_H */
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 5b38110396e..222932a1549 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -1164,43 +1164,32 @@ valpy_setitem (PyObject *self, PyObject *key, PyObject *value)
 }
 
 /* Called by the Python interpreter to perform an inferior function
-   call on the value.  Returns NULL on error, with a python exception set.  */
-static PyObject *
-valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
+   call on the value.  */
+static gdbpy_ref<>
+valpy_call (gdbpy_borrowed_ref<> self, gdbpy_borrowed_ref<> args,
+	    gdbpy_opt_borrowed_ref<> keywords ATTRIBUTE_UNUSED)
 {
   Py_ssize_t args_count;
-  struct value *function = ((value_object *) self)->value;
+  struct value *function = ((value_object *) (PyObject *)self)->value;
   struct value **vargs = NULL;
   struct type *ftype = NULL;
   gdbpy_ref<> result;
 
-  try
-    {
-      ftype = check_typedef (function->type ());
-    }
-  catch (const gdb_exception &except)
-    {
-      return gdbpy_handle_gdb_exception (nullptr, except);
-    }
+  ftype = check_typedef (function->type ());
 
   if (ftype->code () != TYPE_CODE_FUNC && ftype->code () != TYPE_CODE_METHOD
       && ftype->code () != TYPE_CODE_INTERNAL_FUNCTION)
-    {
-      PyErr_SetString (PyExc_RuntimeError,
-		       _("Value is not callable (not TYPE_CODE_FUNC"
-			 " or TYPE_CODE_METHOD"
-			 " or TYPE_CODE_INTERNAL_FUNCTION)."));
-      return NULL;
-    }
+    gdbpy_err_set_string
+      (PyExc_RuntimeError,
+       _("Value is not callable (not TYPE_CODE_FUNC or TYPE_CODE_METHOD"
+	 " or TYPE_CODE_INTERNAL_FUNCTION)."));
 
-  if (! PyTuple_Check (args))
-    {
-      PyErr_SetString (PyExc_TypeError,
-		       _("Inferior arguments must be provided in a tuple."));
-      return NULL;
-    }
+  if (! gdbpy_tuple_check (args))
+    gdbpy_err_set_string
+      (PyExc_TypeError,
+       _("Inferior arguments must be provided in a tuple."));
 
-  args_count = PyTuple_Size (args);
+  args_count = gdbpy_tuple_size (args);
   if (args_count > 0)
     {
       int i;
@@ -1208,39 +1197,29 @@ valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
       vargs = XALLOCAVEC (struct value *, args_count);
       for (i = 0; i < args_count; i++)
 	{
-	  PyObject *item = PyTuple_GetItem (args, i);
-
-	  if (item == NULL)
-	    return NULL;
-
-	  vargs[i] = convert_value_from_python (item);
-	  if (vargs[i] == NULL)
-	    return NULL;
+	  gdbpy_borrowed_ref<> item = gdbpy_tuple_get_item (args, i);
+	  vargs[i] = gdbpy_require_nonnull (convert_value_from_python (item));
 	}
     }
 
-  try
-    {
-      scoped_value_mark free_values;
+  {
+    scoped_value_mark free_values;
 
-      value *return_value;
-      if (ftype->code () == TYPE_CODE_INTERNAL_FUNCTION)
-	return_value = call_internal_function (gdbpy_enter::get_gdbarch (),
-					       current_language,
-					       function, args_count, vargs,
-					       EVAL_NORMAL);
-      else
-	return_value
-	  = call_function_by_hand (function, NULL,
-				   gdb::make_array_view (vargs, args_count));
-      result = value_to_value_object (return_value);
-    }
-  catch (const gdb_exception &except)
-    {
-      return gdbpy_handle_gdb_exception (nullptr, except);
-    }
+    value *return_value;
+    if (ftype->code () == TYPE_CODE_INTERNAL_FUNCTION)
+      return_value = call_internal_function (gdbpy_enter::get_gdbarch (),
+					     current_language,
+					     function, args_count, vargs,
+					     EVAL_NORMAL);
+    else
+      return_value
+	= call_function_by_hand (function, NULL,
+				 gdb::make_array_view (vargs, args_count));
 
-  return result.release ();
+    result = value_to_value_object (return_value);
+  }
+
+  return result;
 }
 
 /* Called by the Python interpreter to obtain string representation
@@ -2376,7 +2355,7 @@ PyTypeObject value_object_type = {
   0,				  /*tp_as_sequence*/
   &value_object_as_mapping,	  /*tp_as_mapping*/
   valpy_hash,		          /*tp_hash*/
-  valpy_call,	                  /*tp_call*/
+  wrap_tp_call<valpy_call>,	  /*tp_call*/
   valpy_str,			  /*tp_str*/
   0,				  /*tp_getattro*/
   0,				  /*tp_setattro*/
diff --git a/gdb/python/py-wrappers.h b/gdb/python/py-wrappers.h
index 6c2b5e4d41e..79cc46fbebf 100644
--- a/gdb/python/py-wrappers.h
+++ b/gdb/python/py-wrappers.h
@@ -358,4 +358,22 @@ gdbpy_sequence_concat (gdbpy_borrowed_ref<> first, gdbpy_borrowed_ref<> second)
   return result;
 }
 
+/* Wrapper for PyTuple_Check.  */
+static inline bool
+gdbpy_tuple_check (gdbpy_borrowed_ref<> p)
+{
+  /* Always succeeds.  */
+  return PyTuple_Check (p);
+}
+
+/* Throw gdb_python_exception if VAL is nullptr.  */
+template<typename T>
+T
+gdbpy_require_nonnull (T val)
+{
+  if (val == nullptr)
+    throw gdb_python_exception ();
+  return val;
+}
+
 #endif /* GDB_PYTHON_PY_WRAPPERS_H */

base-commit: b7f5758529acb1a34dbe025cd3cc593d625e1538
-- 
2.51.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.