]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb/python: add function () method to gdb.Type object
authorJan Vrany <jan.vrany@labware.com>
Thu, 21 Nov 2024 13:49:08 +0000 (13:49 +0000)
committerJan Vrany <jan.vrany@labware.com>
Thu, 21 Nov 2024 13:49:08 +0000 (13:49 +0000)
This commit adds a new method to Python type objects that returns
possibly new function type returning that type. Parameter types can
be specified too.

This will be useful later to create types for function symbols created
using Python extension code.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
gdb/NEWS
gdb/doc/python.texi
gdb/python/py-type.c
gdb/testsuite/gdb.python/py-type.exp

index 765d14a1ae4a56f5532050b3a8cc6286220f1d11..3d2087441038e847e6f9d5da4f3d41f17549e6b8 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -91,6 +91,9 @@
   ** Added gdb.Architecture.void_type. Returns a gdb.Type representing "void"
      type for that architecture.
 
+  ** Added gdb.Type.function.  Returns a new gdb.Type representing a function
+     returning that type.  Parameter types can be specified too.
+
 * Debugger Adapter Protocol changes
 
   ** The "scopes" request will now return a scope holding global
index dac5115a5f8899bf4073529f9bb491f49818cc5f..5eb2813884db928d162b790952e7566efd575dbb 100644 (file)
@@ -1574,6 +1574,14 @@ Return a new @code{gdb.Type} object which represents a pointer to this
 type.
 @end defun
 
+@defun Type.function (@r{[}param_type@dots{}@r{]})
+Return a new @code{gdb.Type} object which represents a type of function
+returning this type.  @code{param_type@dots{}} arguments specify parameter
+types.  Use @code{None} as last parameter type to create a vararg function
+type.  When invoked with single @code{None} argument or with no arguments at
+all it creates a vararg function taking zero or more parameters.
+@end defun
+
 @defun Type.strip_typedefs ()
 Return a new @code{gdb.Type} that represents the real type,
 after removing all layers of typedefs.
index 284960a3a879b3b91f25fe9e25542fbdb037986f..348889dddd8afcb92c438c35724377d33dcd3c48 100644 (file)
@@ -774,6 +774,57 @@ typy_unqualified (PyObject *self, PyObject *args)
   return type_to_type_object (type);
 }
 
+/* Return a function type. */
+static PyObject *
+typy_function (PyObject *self, PyObject *args)
+{
+  struct type *type = ((type_object *) self)->type;
+
+  gdb_assert (PySequence_Check (args));
+
+  std::vector<struct type *> param_types (PySequence_Length (args));
+
+  for (int i = 0; i < PySequence_Length (args); i++)
+    {
+      PyObject *param_type_obj = PySequence_GetItem (args, i);
+
+      if (param_type_obj == Py_None)
+       {
+         param_types[i] = nullptr;
+         if (i != (PySequence_Length (args) - 1))
+           {
+             PyErr_Format (PyExc_ValueError,
+                           _("Argument at index %d is None but None can "
+                             "only be the last type."), i);
+             return nullptr;
+           }
+       }
+      else
+       {
+         param_types[i] = type_object_to_type (param_type_obj);
+         if (!param_types[i])
+           {
+             PyErr_Format (PyExc_TypeError,
+                           _("Argument at index %d is not a gdb.Type "
+                             "object."), i);
+             return nullptr;
+           }
+       }
+    }
+
+  try
+    {
+      type = lookup_function_type_with_arguments (
+              type, param_types.size (), param_types.data ());
+    }
+  catch (const gdb_exception &except)
+    {
+      return gdbpy_handle_gdb_exception (nullptr, except);
+    }
+
+  return type_to_type_object (type);
+}
+
 /* Return the size of the type represented by SELF, in bytes.  */
 static PyObject *
 typy_get_sizeof (PyObject *self, void *closure)
@@ -1641,6 +1692,9 @@ Return the type of a template argument." },
   { "unqualified", typy_unqualified, METH_NOARGS,
     "unqualified () -> Type\n\
 Return a variant of this type without const or volatile attributes." },
+  { "function", typy_function, METH_VARARGS,
+    "function () -> Type\n\
+Return a function type returning value of this type." },
   { "values", typy_values, METH_NOARGS,
     "values () -> list\n\
 Return a list holding all the fields of this type.\n\
index 7e469c93c356759e51293df13f47257f99f47cbb..783261e6f4ade4ceedb20f0ee94f1c9dcb0dae38 100644 (file)
@@ -365,6 +365,26 @@ if { [build_inferior "${binfile}" "c"] == 0 } {
   gdb_test "python print(gdb.lookup_type('int').optimized_out())" \
       "<optimized out>"
 
+  gdb_test_no_output "python int_t = gdb.lookup_type('int')"
+
+  gdb_test "python print(repr(int_t.function()))" \
+      "<gdb.Type code=TYPE_CODE_FUNC name=int \\(\\)>"
+
+  gdb_test "python print(repr(int_t.function(int_t, int_t, int_t)))" \
+      "<gdb.Type code=TYPE_CODE_FUNC name=int \\(int, int, int\\)>"
+
+  gdb_test "python print(repr(int_t.function(int_t, None)))" \
+      "<gdb.Type code=TYPE_CODE_FUNC name=int \\(int, ...\\)>"
+
+  gdb_test "python print(repr(int_t.function(None)))" \
+      "<gdb.Type code=TYPE_CODE_FUNC name=int \\(\\)>"
+
+  gdb_test "python print(repr(int_t.function(123)))" \
+      "TypeError.*:.*"
+
+   gdb_test "python print(repr(int_t.function(int_t, None, int_t)))" \
+      "ValueError.*:.*"
+
   set sint [get_sizeof int 0]
   gdb_test "python print(gdb.parse_and_eval('aligncheck').type.alignof)" \
       $sint