From: Jan Vrany Date: Thu, 21 Nov 2024 13:49:08 +0000 (+0000) Subject: gdb/python: add function () method to gdb.Type object X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f350e1aba5dac9a8e3f48425f502e4b69e9e2455;p=thirdparty%2Fbinutils-gdb.git gdb/python: add function () method to gdb.Type object 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 --- diff --git a/gdb/NEWS b/gdb/NEWS index 765d14a1ae4..3d208744103 100644 --- 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 diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index dac5115a5f8..5eb2813884d 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -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. diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c index 284960a3a87..348889dddd8 100644 --- a/gdb/python/py-type.c +++ b/gdb/python/py-type.c @@ -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 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\ diff --git a/gdb/testsuite/gdb.python/py-type.exp b/gdb/testsuite/gdb.python/py-type.exp index 7e469c93c35..783261e6f4a 100644 --- a/gdb/testsuite/gdb.python/py-type.exp +++ b/gdb/testsuite/gdb.python/py-type.exp @@ -365,6 +365,26 @@ if { [build_inferior "${binfile}" "c"] == 0 } { gdb_test "python print(gdb.lookup_type('int').optimized_out())" \ "" + gdb_test_no_output "python int_t = gdb.lookup_type('int')" + + gdb_test "python print(repr(int_t.function()))" \ + "" + + gdb_test "python print(repr(int_t.function(int_t, int_t, int_t)))" \ + "" + + gdb_test "python print(repr(int_t.function(int_t, None)))" \ + "" + + gdb_test "python print(repr(int_t.function(None)))" \ + "" + + 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