[RFC,v2,05/21] gdb/python: add function () method to gdb.Type object
Checks
Commit Message
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 | 3 ++
gdb/doc/python.texi | 8 +++++
gdb/python/py-type.c | 54 ++++++++++++++++++++++++++++
gdb/testsuite/gdb.python/py-type.exp | 20 +++++++++++
4 files changed, 85 insertions(+)
Comments
> From: Jan Vrany <jan.vrany@labware.com>
> CC: Jan Vrany <jan.vrany@labware.com>,
> Eli Zaretskii <eliz@gnu.org>
> Date: Thu, 21 Nov 2024 12:46:58 +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 | 3 ++
> gdb/doc/python.texi | 8 +++++
> gdb/python/py-type.c | 54 ++++++++++++++++++++++++++++
> gdb/testsuite/gdb.python/py-type.exp | 20 +++++++++++
> 4 files changed, 85 insertions(+)
The documentation parts are okay, but...
> +@defun Type.function (@r{[}param_type...@r{]})
> +Return a new @code{gdb.Type} object which represents a type of function
> +returning this type. @code{param_type...} arguments specify parameter
...please use @dots{} instead of literal "..." in both cases here,
when you push.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
On Thu, 2024-11-21 at 15:34 +0200, Eli Zaretskii wrote:
> > From: Jan Vrany <jan.vrany@labware.com>
> > CC: Jan Vrany <jan.vrany@labware.com>,
> > Eli Zaretskii <eliz@gnu.org>
> > Date: Thu, 21 Nov 2024 12:46:58 +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 | 3 ++
> > gdb/doc/python.texi | 8 +++++
> > gdb/python/py-type.c | 54
> > ++++++++++++++++++++++++++++
> > gdb/testsuite/gdb.python/py-type.exp | 20 +++++++++++
> > 4 files changed, 85 insertions(+)
>
> The documentation parts are okay, but...
>
> > +@defun Type.function (@r{[}param_type...@r{]})
> > +Return a new @code{gdb.Type} object which represents a type of
> > function
> > +returning this type. @code{param_type...} arguments specify
> > parameter
>
> ...please use @dots{} instead of literal "..." in both cases here,
> when you push.
>
Thanks! I have fixed this in my local working version
and it will part of next version. Same for the extra "to"
in the other commit (
https://sourceware.org/pipermail/gdb-patches/2024-November/213479.html
)
Jan
> Reviewed-By: Eli Zaretskii <eliz@gnu.org>
>
@@ -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
@@ -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...@r{]})
+Return a new @code{gdb.Type} object which represents a type of function
+returning this type. @code{param_type...} 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.
@@ -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\
@@ -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