[PATCH] Convert py-arch.c to "safety" approach

Tom Tromey <[email protected]>
Newsgroups gmane.comp.gdb.patches
Message-ID <[email protected]>
This patch converts py-arch.c to the new Python safety approach.  A
few changes outside this file were also needed: some updates to
py-register.c (changing some functions that are only called from
py-arch.c), the new noargs_function template, and the use of a wrapper
in python.c.

Regression tested on x86-64 Fedora 40.
---
 gdb/python/py-arch.c         | 306 +++++++++++++++--------------------
 gdb/python/py-registers.c    |  39 ++---
 gdb/python/py-safety.h       |  26 +++
 gdb/python/py-wrappers.h     |  11 ++
 gdb/python/python-internal.h |   8 +-
 gdb/python/python.c          |   4 +-
 6 files changed, 189 insertions(+), 205 deletions(-)

diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c
index 5b3cfbdc876..51dfcb97b36 100644
--- a/gdb/python/py-arch.c
+++ b/gdb/python/py-arch.c
@@ -25,6 +25,56 @@
 struct arch_object : public PyObject
 {
   struct gdbarch *gdbarch;
+
+  /* Return the gdbarch associated with OBJ.  Throws an exception on
+     error.  */
+  struct gdbarch *require ()
+  {
+    if (gdbarch == nullptr)
+      gdbpy_err_set_string (PyExc_RuntimeError, _("Architecture is invalid."));
+    return gdbarch;
+  }
+
+  /* Implementation of gdb.Architecture.name (self) -> String.
+     Returns the name of the architecture as a string value.  */
+  const char *name ()
+  {
+    return gdbarch_bfd_arch_info (require ())->printable_name;
+  }
+
+  /* __repr__ implementation for gdb.Architecture.  */
+  gdbpy_ref<> repr ();
+
+  /* Implementation of gdb.void_type.  */
+  gdbpy_ref<> void_type ()
+  {
+    return type_to_type_object (builtin_type (require ())->builtin_void);
+  }
+
+  /* Implementation of gdb.Architecture.register_groups (self) -> Iterator.
+     Returns an iterator that will give up all valid register groups in the
+     architecture SELF.  */
+  gdbpy_ref<> register_groups ()
+  {
+    return gdbpy_new_reggroup_iterator (require ());
+  }
+
+  /* Implementation of
+     gdb.Architecture.disassemble (self, start_pc [, end_pc [,count]]) -> List.
+     Returns a list of instructions in a memory address range.  Each instruction
+     in the list is a Python dict object.  */
+  gdbpy_ref<> disassemble (gdbpy_borrowed_ref<> args,
+			   gdbpy_opt_borrowed_ref<> kw);
+
+  /* Implementation of gdb.integer_type.  */
+  gdbpy_ref<> integer_type (gdbpy_borrowed_ref<> args,
+			    gdbpy_opt_borrowed_ref<> kw);
+
+  /* Implementation of gdb.Architecture.registers (self, reggroup) ->
+     Iterator.  Returns an iterator over register descriptors for
+     registers in GROUP within the architecture SELF.  */
+  gdbpy_ref<> registers (gdbpy_borrowed_ref<> args,
+			 gdbpy_opt_borrowed_ref<> kw);
 };
 
 static_assert (gdb::is_python_allocatable_v<arch_object>);
@@ -32,18 +82,6 @@ static_assert (gdb::is_python_allocatable_v<arch_object>);
 static const registry<gdbarch>::key<PyObject, gdb::noop_deleter<PyObject>>
      arch_object_data;
 
-/* Require a valid Architecture.  */
-#define ARCHPY_REQUIRE_VALID(arch_obj, arch)			\
-  do {								\
-    arch = arch_object_to_gdbarch (arch_obj);			\
-    if (arch == NULL)						\
-      {								\
-	PyErr_SetString (PyExc_RuntimeError,			\
-			 _("Architecture is invalid."));	\
-	return NULL;						\
-      }								\
-  } while (0)
-
 extern PyTypeObject arch_object_type;
 
 /* Associates an arch_object with GDBARCH as gdbarch_data via the gdbarch
@@ -102,80 +140,46 @@ gdbarch_to_arch_object (struct gdbarch *gdbarch)
   return gdbpy_ref<> (new_ref);
 }
 
-/* Implementation of gdb.Architecture.name (self) -> String.
-   Returns the name of the architecture as a string value.  */
-
-static PyObject *
-archpy_name (PyObject *self, PyObject *args)
-{
-  struct gdbarch *gdbarch = NULL;
-  const char *name;
-
-  ARCHPY_REQUIRE_VALID (self, gdbarch);
-
-  name = (gdbarch_bfd_arch_info (gdbarch))->printable_name;
-  return PyUnicode_FromString (name);
-}
-
-/* Implementation of
-   gdb.Architecture.disassemble (self, start_pc [, end_pc [,count]]) -> List.
-   Returns a list of instructions in a memory address range.  Each instruction
-   in the list is a Python dict object.
-*/
-
-static PyObject *
-archpy_disassemble (PyObject *self, PyObject *args, PyObject *kw)
+gdbpy_ref<>
+arch_object::disassemble (gdbpy_borrowed_ref<> args,
+			  gdbpy_opt_borrowed_ref<> kw)
 {
   static const char *keywords[] = {
     "start_pc", "end_pc", "count", "styling", nullptr
   };
-  CORE_ADDR start = 0, end = 0;
   CORE_ADDR pc;
   long count = 0, i;
   PyObject *start_obj = nullptr, *end_obj = nullptr, *count_obj = nullptr;
-  struct gdbarch *gdbarch = NULL;
   int styling_p = 0;
 
-  ARCHPY_REQUIRE_VALID (self, gdbarch);
+  struct gdbarch *gdbarch = require ();
 
-  if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "O|OOp",
-					keywords, &start_obj, &end_obj,
-					&count_obj, &styling_p))
-    return NULL;
+  gdbpy_arg_parse_tuple_and_keywords (args, kw, "O|OOp",
+				      keywords, &start_obj, &end_obj,
+				      &count_obj, &styling_p);
 
-  if (get_addr_from_python (start_obj, &start) < 0)
-    return nullptr;
+  CORE_ADDR start = gdbpy_get_address (start_obj);
 
+  CORE_ADDR end = 0;
   if (end_obj != nullptr)
     {
-      if (get_addr_from_python (end_obj, &end) < 0)
-	return nullptr;
+      end = gdbpy_get_address (end_obj);
 
       if (end < start)
-	{
-	  PyErr_SetString (PyExc_ValueError,
-			   _("Argument 'end_pc' should be greater than or "
-			     "equal to the argument 'start_pc'."));
-
-	  return NULL;
-	}
+	gdbpy_err_set_string (PyExc_ValueError,
+			      _("Argument 'end_pc' should be greater than or "
+				"equal to the argument 'start_pc'."));
     }
   if (count_obj)
     {
-      count = PyLong_AsLong (count_obj);
-      if (PyErr_Occurred () || count < 0)
-	{
-	  PyErr_SetString (PyExc_TypeError,
-			   _("Argument 'count' should be an non-negative "
-			     "integer."));
-
-	  return NULL;
-	}
+      count = gdbpy_long_as_long (count_obj);
+      if (count < 0)
+	gdbpy_err_set_string (PyExc_TypeError,
+			      _("Argument 'count' should be an non-negative "
+				"integer."));
     }
 
-  gdbpy_ref<> result_list (PyList_New (0));
-  if (result_list == NULL)
-    return NULL;
+  gdbpy_ref<> result_list = gdbpy_new_list (0);
 
   for (pc = start, i = 0;
        /* All args are specified.  */
@@ -187,105 +191,72 @@ archpy_disassemble (PyObject *self, PyObject *args, PyObject *kw)
        /* Both end_pc and count are not specified.  */
        || (end_obj == NULL && count_obj == NULL && pc == start);)
     {
-      int insn_len = 0;
-      gdbpy_ref<> insn_dict (PyDict_New ());
+      gdbpy_ref<> insn_dict = gdbpy_new_dict ();
 
-      if (insn_dict == NULL)
-	return NULL;
-      if (PyList_Append (result_list.get (), insn_dict.get ()))
-	return NULL;  /* PyList_Append Sets the exception.  */
+      gdbpy_list_append (result_list, insn_dict);
 
       string_file stb (styling_p);
+      int insn_len = gdb_print_insn (gdbarch, pc, &stb, NULL);
 
-      try
-	{
-	  insn_len = gdb_print_insn (gdbarch, pc, &stb, NULL);
-	}
-      catch (const gdb_exception &except)
-	{
-	  return gdbpy_handle_gdb_exception (nullptr, except);
-	}
-
+      /* FIXME: Python safety.  Eventually gdb_py_object_from_ulongest
+	 should throw.  */
       gdbpy_ref<> pc_obj = gdb_py_object_from_ulongest (pc);
       if (pc_obj == nullptr)
-	return nullptr;
+	throw gdb_python_exception ();
 
-      gdbpy_ref<> asm_obj
-	(PyUnicode_FromString (!stb.empty () ? stb.c_str () : "<unknown>"));
-      if (asm_obj == nullptr)
-	return nullptr;
+      gdbpy_ref<> asm_obj = gdbpy_unicode_from_string (!stb.empty ()
+						       ? stb.c_str ()
+						       : "<unknown>");
 
+      /* FIXME: Python safety.  Eventually gdb_py_object_from_longest
+	 should throw.  */
       gdbpy_ref<> len_obj = gdb_py_object_from_longest (insn_len);
       if (len_obj == nullptr)
-	return nullptr;
+	throw gdb_python_exception ();
 
-      if (PyDict_SetItemString (insn_dict.get (), "addr", pc_obj.get ())
-	  || PyDict_SetItemString (insn_dict.get (), "asm", asm_obj.get ())
-	  || PyDict_SetItemString (insn_dict.get (), "length", len_obj.get ()))
-	return NULL;
+      gdbpy_dict_set_item_string (insn_dict, "addr", pc_obj);
+      gdbpy_dict_set_item_string (insn_dict, "asm", asm_obj);
+      gdbpy_dict_set_item_string (insn_dict, "length", len_obj);
 
       pc += insn_len;
       i++;
     }
 
-  return result_list.release ();
+  return result_list;
 }
 
-/* Implementation of gdb.Architecture.registers (self, reggroup) -> Iterator.
-   Returns an iterator over register descriptors for registers in GROUP
-   within the architecture SELF.  */
-
-static PyObject *
-archpy_registers (PyObject *self, PyObject *args, PyObject *kw)
+gdbpy_ref<>
+arch_object::registers (gdbpy_borrowed_ref<> args,
+			gdbpy_opt_borrowed_ref<> kw)
 {
   static const char *keywords[] = { "reggroup", NULL };
-  struct gdbarch *gdbarch = NULL;
   const char *group_name = NULL;
 
   /* Parse method arguments.  */
-  if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "|s", keywords,
-					&group_name))
-    return NULL;
+  gdbpy_arg_parse_tuple_and_keywords (args, kw, "|s", keywords, &group_name);
 
   /* Extract the gdbarch from the self object.  */
-  ARCHPY_REQUIRE_VALID (self, gdbarch);
+  struct gdbarch *gdbarch = require ();
 
   return gdbpy_new_register_descriptor_iterator (gdbarch, group_name);
 }
 
-/* Implementation of gdb.Architecture.register_groups (self) -> Iterator.
-   Returns an iterator that will give up all valid register groups in the
-   architecture SELF.  */
-
-static PyObject *
-archpy_register_groups (PyObject *self, PyObject *args)
-{
-  struct gdbarch *gdbarch = NULL;
-
-  /* Extract the gdbarch from the self object.  */
-  ARCHPY_REQUIRE_VALID (self, gdbarch);
-  return gdbpy_new_reggroup_iterator (gdbarch);
-}
-
-/* Implementation of gdb.integer_type.  */
-static PyObject *
-archpy_integer_type (PyObject *self, PyObject *args, PyObject *kw)
+gdbpy_ref<>
+arch_object::integer_type (gdbpy_borrowed_ref<> args,
+			   gdbpy_opt_borrowed_ref<> kw)
 {
   static const char *keywords[] = { "size", "signed", NULL };
   int size;
   PyObject *is_signed_obj = Py_True;
 
-  if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "i|O!", keywords,
-					&size,
-					&PyBool_Type, &is_signed_obj))
-    return nullptr;
+  gdbpy_arg_parse_tuple_and_keywords (args, kw, "i|O!", keywords, &size,
+				      &PyBool_Type, &is_signed_obj);
 
   /* Assume signed by default.  */
   gdb_assert (PyBool_Check (is_signed_obj));
   bool is_signed = is_signed_obj == Py_True;
 
-  struct gdbarch *gdbarch;
-  ARCHPY_REQUIRE_VALID (self, gdbarch);
+  struct gdbarch *gdbarch = require ();
 
   const struct builtin_type *builtins = builtin_type (gdbarch);
   struct type *type = nullptr;
@@ -314,61 +285,41 @@ archpy_integer_type (PyObject *self, PyObject *args, PyObject *kw)
       break;
 
     default:
-      PyErr_SetString (PyExc_ValueError,
-		       _("no integer type of that size is available"));
-      return nullptr;
+      gdbpy_err_set_string (PyExc_ValueError,
+			    _("no integer type of that size is available"));
     }
 
-  return type_to_type_object (type).release ();
+  return type_to_type_object (type);
 }
 
-/* Implementation of gdb.void_type.  */
-static PyObject *
-archpy_void_type (PyObject *self, PyObject *args)
-{
-  struct gdbarch *gdbarch;
-  ARCHPY_REQUIRE_VALID (self, gdbarch);
-
-  return type_to_type_object (builtin_type (gdbarch)->builtin_void).release ();
-}
-
-/* __repr__ implementation for gdb.Architecture.  */
-
-static PyObject *
-archpy_repr (PyObject *self)
+gdbpy_ref<>
+arch_object::repr ()
 {
-  const auto gdbarch = arch_object_to_gdbarch (self);
   if (gdbarch == nullptr)
-    return gdb_py_invalid_object_repr (self);
+    /* FIXME: Python safety.  Eventually gdb_py_invalid_object_repr
+       should throw.  */
+    return gdbpy_ref<> (gdb_py_invalid_object_repr (this));
 
   auto arch_info = gdbarch_bfd_arch_info (gdbarch);
-  return PyUnicode_FromFormat ("<%s arch_name=%s printable_name=%s>",
-			       gdbpy_py_obj_tp_name (self).c_str (),
-			       arch_info->arch_name,
-			       arch_info->printable_name);
+  return gdbpy_unicode_from_format ("<%s arch_name=%s printable_name=%s>",
+				    gdbpy_py_obj_tp_name (this).c_str (),
+				    arch_info->arch_name,
+				    arch_info->printable_name);
 }
 
 /* Implementation of gdb.architecture_names().  Return a list of all the
    BFD architecture names that GDB understands.  */
 
-PyObject *
-gdbpy_all_architecture_names (PyObject *self, PyObject *args)
+gdbpy_ref<>
+gdbpy_all_architecture_names ()
 {
-  gdbpy_ref<> list (PyList_New (0));
-  if (list == nullptr)
-    return nullptr;
+  gdbpy_ref<> list = gdbpy_new_list (0);
 
   std::vector<const char *> name_list = gdbarch_printable_names ();
   for (const char *name : name_list)
-    {
-      gdbpy_ref <> py_name (PyUnicode_FromString (name));
-      if (py_name == nullptr)
-	return nullptr;
-      if (PyList_Append (list.get (), py_name.get ()) < 0)
-	return nullptr;
-    }
+    gdbpy_list_append (list, gdbpy_unicode_from_string (name));
 
- return list.release ();
+ return list;
 }
 
 /* Initializes the Architecture class in the gdb module.  */
@@ -385,32 +336,27 @@ GDBPY_INITIALIZE_FILE (gdbpy_initialize_arch);
 
 
 static PyMethodDef arch_object_methods [] = {
-  { "name", archpy_name, METH_NOARGS,
+  noargs_method<arch_object, &arch_object::name> ("name",
     "name () -> String.\n\
-Return the name of the architecture as a string value." },
-  { "disassemble", (PyCFunction) archpy_disassemble,
-    METH_VARARGS | METH_KEYWORDS,
+Return the name of the architecture as a string value."),
+  varargs_method<arch_object, &arch_object::disassemble> ("disassemble",
     "disassemble (start_pc [, end_pc [, count]]) -> List.\n\
 Return a list of at most COUNT disassembled instructions from START_PC to\n\
-END_PC." },
-  { "integer_type", (PyCFunction) archpy_integer_type,
-    METH_VARARGS | METH_KEYWORDS,
+END_PC."),
+  varargs_method<arch_object, &arch_object::integer_type> ("integer_type",
     "integer_type (size [, signed]) -> type\n\
 Return an integer Type corresponding to the given bitsize and signed-ness.\n\
-If not specified, the type defaults to signed." },
-  { "void_type", (PyCFunction) archpy_void_type,
-    METH_NOARGS,
+If not specified, the type defaults to signed."),
+  noargs_method<arch_object, &arch_object::void_type> ("void_type",
     "void_type () -> type\n\
-Return a void Type." },
-  { "registers", (PyCFunction) archpy_registers,
-    METH_VARARGS | METH_KEYWORDS,
+Return a void Type."),
+  varargs_method<arch_object, &arch_object::registers> ("registers",
     "registers ([ group-name ]) -> Iterator.\n\
 Return an iterator of register descriptors for the registers in register\n\
-group GROUP-NAME." },
-  { "register_groups", archpy_register_groups,
-    METH_NOARGS,
+group GROUP-NAME."),
+  noargs_method<arch_object, &arch_object::register_groups> ("register_groups",
     "register_groups () -> Iterator.\n\
-Return an iterator over all of the register groups in this architecture." },
+Return an iterator over all of the register groups in this architecture."),
   {NULL}  /* Sentinel */
 };
 
@@ -424,7 +370,7 @@ PyTypeObject arch_object_type = {
   0,                                  /* tp_getattr */
   0,                                  /* tp_setattr */
   0,                                  /* tp_compare */
-  archpy_repr,                        /* tp_repr */
+  wrap_tp_callback<arch_object, &arch_object::repr>, /* tp_repr */
   0,                                  /* tp_as_number */
   0,                                  /* tp_as_sequence */
   0,                                  /* tp_as_mapping */
diff --git a/gdb/python/py-registers.c b/gdb/python/py-registers.c
index e0180660715..80a57207b0a 100644
--- a/gdb/python/py-registers.c
+++ b/gdb/python/py-registers.c
@@ -43,6 +43,8 @@ struct register_descriptor_iterator_object : public PyObject
 
   /* Pointer back to the architecture we're finding registers for.  */
   struct gdbarch *gdbarch;
+
+  static PyTypeObject *corresponding_object_type;
 };
 
 static_assert (gdb::is_python_allocatable_v<register_descriptor_iterator_object>);
@@ -71,6 +73,8 @@ struct reggroup_iterator_object : public PyObject
 
   /* Pointer back to the architecture we're finding registers for.  */
   struct gdbarch *gdbarch;
+
+  static PyTypeObject *corresponding_object_type;
 };
 
 static_assert (gdb::is_python_allocatable_v<reggroup_iterator_object>);
@@ -231,20 +235,17 @@ gdbpy_reggroup_iter_next (PyObject *self)
 /* Return a new gdb.RegisterGroupsIterator over all the register groups in
    GDBARCH.  */
 
-PyObject *
+gdbpy_ref<>
 gdbpy_new_reggroup_iterator (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != nullptr);
 
   /* Create a new object and fill in its internal state.  */
-  reggroup_iterator_object *iter
-    = PyObject_New (reggroup_iterator_object,
-		    &reggroup_iterator_object_type);
-  if (iter == NULL)
-    return NULL;
+  gdbpy_ref<reggroup_iterator_object> iter
+    = gdbpy_new<reggroup_iterator_object> ();
   iter->index = 0;
   iter->gdbarch = gdbarch;
-  return (PyObject *) iter;
+  return iter;
 }
 
 /* Create and return a new gdb.RegisterDescriptorIterator object which
@@ -255,7 +256,7 @@ gdbpy_new_reggroup_iterator (struct gdbarch *gdbarch)
 
    This function can return NULL if GROUP_NAME isn't found.  */
 
-PyObject *
+gdbpy_ref<>
 gdbpy_new_register_descriptor_iterator (struct gdbarch *gdbarch,
 					const char *group_name)
 {
@@ -268,25 +269,19 @@ gdbpy_new_register_descriptor_iterator (struct gdbarch *gdbarch,
     {
       grp = reggroup_find (gdbarch, group_name);
       if (grp == NULL)
-	{
-	  PyErr_SetString (PyExc_ValueError,
-			   _("Unknown register group name."));
-	  return NULL;
-	}
+	gdbpy_err_set_string (PyExc_ValueError,
+			      _("Unknown register group name."));
     }
   /* Create a new iterator object initialised for this architecture and
      fill in all of the details.  */
-  register_descriptor_iterator_object *iter
-    = PyObject_New (register_descriptor_iterator_object,
-		    &register_descriptor_iterator_object_type);
-  if (iter == NULL)
-    return NULL;
+  gdbpy_ref<register_descriptor_iterator_object> iter
+    = gdbpy_new<register_descriptor_iterator_object> ();
   iter->regnum = 0;
   iter->gdbarch = gdbarch;
   gdb_assert (grp != NULL);
   iter->reggroup = grp;
 
-  return (PyObject *) iter;
+  return iter;
 }
 
 /* Return a reference to the gdb.RegisterDescriptorIterator object.  */
@@ -494,6 +489,9 @@ PyTypeObject register_descriptor_iterator_object_type = {
   register_descriptor_iterator_object_methods		/*tp_methods */
 };
 
+PyTypeObject *register_descriptor_iterator_object::corresponding_object_type
+  = &register_descriptor_iterator_object_type;
+
 static gdb_PyGetSetDef gdbpy_register_descriptor_getset[] = {
   { "name", gdbpy_register_descriptor_name, NULL,
     "The name of this register.", NULL },
@@ -564,6 +562,9 @@ PyTypeObject reggroup_iterator_object_type = {
   0				  /*tp_methods */
 };
 
+PyTypeObject *reggroup_iterator_object::corresponding_object_type
+  = &reggroup_iterator_object_type;
+
 static gdb_PyGetSetDef gdbpy_reggroup_getset[] = {
   { "name", gdbpy_reggroup_name, NULL,
     "The name of this register group.", NULL },
diff --git a/gdb/python/py-safety.h b/gdb/python/py-safety.h
index 3294f38c8b6..d47a34b760f 100644
--- a/gdb/python/py-safety.h
+++ b/gdb/python/py-safety.h
@@ -233,6 +233,32 @@ varargs_wrapper (PyObject *self, PyObject *args, PyObject *kw)
 
 } /* namespace safety_details */
 
+/* Create a PyMethodDef for a no-argument function.  It takes the
+   takes the underlying implementation function as a template
+   argument, and also arguments for the method name and documentation
+   string.
+
+   The underlying function should take no arguments.
+
+   The function can return any type (see the to_python overloads); and
+   should throw an exception on error.  If gdb_python_exception is
+   thrown, the Python exception must already have been set.  */
+template<auto F>
+constexpr PyMethodDef
+noargs_function (const char *name, const char *doc)
+{
+  using namespace safety_details;
+  return {
+    name,
+    [] (PyObject *self, PyObject *args) -> PyObject *
+    {
+      return wrapped_function<F> ();
+    },
+    METH_NOARGS,
+    doc,
+  };
+}
+
 /* Create a PyMethodDef for a no-argument method.  It takes the
    underlying class C and a pointer-to-method M as template
    parameters, and the name and documentation as arguments.  The
diff --git a/gdb/python/py-wrappers.h b/gdb/python/py-wrappers.h
index 6c2b5e4d41e..d45682d1ddb 100644
--- a/gdb/python/py-wrappers.h
+++ b/gdb/python/py-wrappers.h
@@ -358,4 +358,15 @@ gdbpy_sequence_concat (gdbpy_borrowed_ref<> first, gdbpy_borrowed_ref<> second)
   return result;
 }
 
+/* A wrapper for get_addr_from_python that returns the address or
+   throws an exception.  */
+static inline CORE_ADDR
+gdbpy_get_address (gdbpy_borrowed_ref<> obj)
+{
+  CORE_ADDR result;
+  if (get_addr_from_python (obj, &result) < 0)
+    throw gdb_python_exception ();
+  return result;
+}
+
 #endif /* GDB_PYTHON_PY_WRAPPERS_H */
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 1165f165e29..a91ae4957a1 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -525,11 +525,11 @@ PyObject *objfpy_get_xmethods (PyObject *, void *);
 PyObject *gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw);
 
 gdbpy_ref<> gdbarch_to_arch_object (struct gdbarch *gdbarch);
-PyObject *gdbpy_all_architecture_names (PyObject *self, PyObject *args);
+gdbpy_ref<> gdbpy_all_architecture_names ();
 
-PyObject *gdbpy_new_register_descriptor_iterator (struct gdbarch *gdbarch,
-						  const char *group_name);
-PyObject *gdbpy_new_reggroup_iterator (struct gdbarch *gdbarch);
+gdbpy_ref<> gdbpy_new_register_descriptor_iterator (struct gdbarch *gdbarch,
+						    const char *group_name);
+gdbpy_ref<> gdbpy_new_reggroup_iterator (struct gdbarch *gdbarch);
 
 gdbpy_ref<thread_object> create_thread_object (struct thread_info *tp);
 gdbpy_ref<> thread_to_thread_object (thread_info *thr);;
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 7b5de98b903..563b212fb43 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -3279,9 +3279,9 @@ Set the value of the convenience variable $NAME." },
 Register a TUI window constructor."),
 #endif	/* TUI */
 
-  { "architecture_names", gdbpy_all_architecture_names, METH_NOARGS,
+  noargs_function<gdbpy_all_architecture_names> ("architecture_names",
     "architecture_names () -> List.\n\
-Return a list of all the architecture names GDB understands." },
+Return a list of all the architecture names GDB understands."),
 
   { "connections", gdbpy_connections, METH_NOARGS,
     "connections () -> List.\n\
-- 
2.49.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.