Re: [PATCH v2 4/9] gdb: add new helpers for retrieving a type's fully qualified name

Matthieu Longo
2026-03-06T17:50:56Z

On 03/03/2026 18:59, Tom Tromey wrote:
>>>>>> Matthieu Longo <matthieu.longo@arm.com> writes:
>
>> +/* Return the type's fully qualified name from a PyTypeObject. */
>> +const char *
>> +gdb_py_tp_name (PyTypeObject *py_type) noexcept
>> +{
>> +#if PY_VERSION_HEX >= 0x030d0000
> ...
>> +#elif ! defined (Py_LIMITED_API)
> ...
>> +#else
>> + #error "The version of Python you are using does not expose " \
>> + "PyType_GetFullyQualifiedName() as a part of the limited C API."
>> +#endif
>
> I think this case can't actually be hit... can it?
>

It currently can when you build GDB with python 3.11 for instance with --enable-py-limited-api=yes.
Unfortunately, I haven't added the logic to error when someone requests to build GDB against the limited API, but does not have a suitable version of Python.
This #error were a workaround to provide a meaningful message to the developer in this case.

> My reasoning is that the very first case is taken if either the limited
> API is in use (which requires 0x030e0000 as of this patch) or if Python
> is new enough.
>
> So, all other cases fall into the non-limited case.
>
> It would be better IMO to remove it if it cannot ever happen.
>

I agree with you, all other cases should fall into the non-limited case.
To do so, it requires me to fix the configure script to detect the issue before the build (see below).

>> +#else
>> + #error "The version of Python you are using does not expose Py_TYPE() "\
>> + "as a part of the limited C API."
>
> I'd prefer that #error not be indented here.
>

Removed in the patch below.

>> +++ b/gdb/python/py-obj-type.h
>> @@ -0,0 +1,31 @@
>> +/* Helpers related to Python object type
>> +
>> +/* Return the type's fully qualified name from a PyTypeObject. */
>> +extern const char *
>> +gdb_py_tp_name (PyTypeObject *py_type) noexcept;
>> +
>> +/* Return the type's fully qualified name from a PyObject. */
>> +extern const char *
>> +gdbpy_py_obj_tp_name (PyObject *self) noexcept;
>
> Declarations in gdb don't have a newline after the return type.
>

Fixed in the next revision.

> thanks,
> Tom

Here is the fix to remove #error macros, and detect the issue at configure time.
I will split the configure fix from the removal of the #error macros in the next revision.

Matthieu

diff --git a/gdb/configure.ac b/gdb/configure.ac
index a3343dec118..b7ae2f3bb3c 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -933,6 +933,7 @@ else
# do except assume that the compiler will be able to find those files.
python_includes=
python_libs=
+ python_prefix=
have_python_config=no
fi

@@ -1062,6 +1063,13 @@ AC_SUBST(PYTHON_CPPFLAGS)
AC_SUBST(PYTHON_LIBS)
AM_CONDITIONAL(HAVE_PYTHON, test "${have_libpython}" != no)

+dnl Use --enable-py-limited-api to enable the build of GDB against the Python
+dnl limited API.
+dnl
+dnl no - Disable the Python limited API.
+dnl yes - Use the Python limited API to build GDB, error if the selected
+dnl version of Python is not compatible with the Python limited API.
+
# Check whether to build GDB against Python limited C API.
AC_ARG_ENABLE([py-limited-api],
[AS_HELP_STRING([--enable-py-limited-api],
@@ -1072,10 +1080,14 @@ AC_ARG_ENABLE([py-limited-api],
if test "$enable_py_limited_api" = yes; then
# The minimal Python limited API version is currently set to 3.14 for the
# support of Py_TYPE().
- # The choice of the minimal version for the Python limited API won't be frozen
- # until the end of the migration.
- AC_DEFINE(Py_LIMITED_API, 0x030e0000,
- [Define if GDB should be built against the Python limited C API.])
+ # The choice of the minimal version for the Python limited API won't be
+ # frozen until the end of the migration.
+ AM_PYTHON_CHECK_VERSION([$python_prog], [3.14], [
+ AC_DEFINE(Py_LIMITED_API, 0x030e0000,
+ [Define if GDB should be built against the Python limited C API.])
+ ],[
+ AC_MSG_ERROR([Python limited API support requires at least Python version 3.14])
+ ])
fi

# -------------------- #
diff --git a/gdb/python/py-obj-type.c b/gdb/python/py-obj-type.c
index 034ebd26b8d..ea0b59a8447 100644
--- a/gdb/python/py-obj-type.c
+++ b/gdb/python/py-obj-type.c
@@ -33,7 +33,7 @@ gdb_py_tp_name (PyTypeObject *py_type) noexcept

return PyUnicode_AsUTF8AndSize (fully_qualified_name, nullptr);

-#elif ! defined (Py_LIMITED_API)
+#else /* PY_VERSION_HEX < 0x030d0000 && ! defined (Py_LIMITED_API) */
/* For non-heap types, the fully qualified name corresponds to tp_name. */
if (! (PyType_GetFlags (py_type) & Py_TPFLAGS_HEAPTYPE))
return py_type->tp_name;
@@ -62,10 +62,6 @@ gdb_py_tp_name (PyTypeObject *py_type) noexcept

return PyUnicode_AsUTF8AndSize (ht->ht_qualname, nullptr);
# endif
-
-#else
- #error "The version of Python you are using does not expose " \
- "PyType_GetFullyQualifiedName() as a part of the limited C API."
#endif
}

@@ -74,11 +70,5 @@ const char *
gdbpy_py_obj_tp_name (PyObject *self) noexcept
{
/* Note: Py_TYPE () is part of the stable ABI since version 3.14. */
-#if ! defined (Py_LIMITED_API) \
- || Py_LIMITED_API >= 0x030e0000
return gdb_py_tp_name (Py_TYPE (self));
-#else
- #error "The version of Python you are using does not expose Py_TYPE() "\
- "as a part of the limited C API."
-#endif
}