https://github.com/Nerixyz updated 
https://github.com/llvm/llvm-project/pull/213463

>From 8501030fbc22a629261a91d91eeba33810bf1c1b Mon Sep 17 00:00:00 2001
From: Nerixyz <[email protected]>
Date: Sat, 1 Aug 2026 17:49:14 +0200
Subject: [PATCH 1/2] [lldb][Python] Enable type annotations for most types

---
 lldb/bindings/python/python-typemaps.swig | 41 +++++++++++++++
 lldb/bindings/python/python.swig          | 62 +++++++++++++++++++++++
 2 files changed, 103 insertions(+)

diff --git a/lldb/bindings/python/python-typemaps.swig 
b/lldb/bindings/python/python-typemaps.swig
index 072e688c4bde1..37f44c619883c 100644
--- a/lldb/bindings/python/python-typemaps.swig
+++ b/lldb/bindings/python/python-typemaps.swig
@@ -53,6 +53,8 @@ AND call SWIG_fail at the same time, because it will result 
in a double free.
   free((char *) $1);
 }
 
+%typemap(pytyping, out="typing.List[str]") char** 
"typing.Optional[typing.List[str]]"
+
 %typecheck(SWIG_TYPECHECK_POINTER) lldb::ScriptObjectPtr {
   PythonObject obj(PyRefType::Borrowed, $input);
   if (!obj.IsValid()) {
@@ -122,6 +124,8 @@ AND call SWIG_fail at the same time, because it will result 
in a double free.
   Py_INCREF($result);
 }
 
+%typemap(pytyping) lldb::ScriptObjectPtr "typing.Any"
+
 %typemap(out) lldb::SBScriptObject {
   $result = nullptr;
   if (const void* impl = $1.GetPointer())
@@ -134,6 +138,8 @@ AND call SWIG_fail at the same time, because it will result 
in a double free.
   }
 }
 
+%typemap(pytyping) lldb::SBScriptObject "typing.Any"
+
 %typemap(out) char** {
   int len;
   int i;
@@ -272,6 +278,10 @@ AND call SWIG_fail at the same time, because it will 
result in a double free.
     SWIG_fail;
   }
 }
+
+%typemap(pytyping) (const char *cstr, uint32_t cstr_len),
+                   (const char *src, size_t src_len) "typing.Union[str, bytes, 
bytearray]"
+
 // For SBProcess::WriteMemory, SBTarget::GetInstructions and 
SBDebugger::DispatchInput.
 %typemap(in) (const void *buf, size_t size),
              (const void *data, size_t data_len),
@@ -294,6 +304,10 @@ AND call SWIG_fail at the same time, because it will 
result in a double free.
   }
 }
 
+%typemap(pytyping) (const void *buf, size_t size),
+                   (const void *data, size_t data_len),
+                   (const void *buf, uint64_t size) "typing.Union[str, bytes, 
bytearray]"
+
 // typemap for an incoming buffer
 // See also SBProcess::ReadMemory.
 %typemap(in) (void *buf, size_t size) {
@@ -410,6 +424,12 @@ template <> bool SetNumberFromPyObject<double>(double 
&number, PyObject *obj) {
   free($1);
 }
 
+%typemap(pytyping) (uint64_t* array, size_t array_len),
+                   (uint32_t* array, size_t array_len),
+                   (int64_t* array, size_t array_len),
+                   (int32_t* array, size_t array_len) 
"typing.Optional[typing.List[int]]"
+%typemap(pytyping) (double* array, size_t array_len) 
"typing.Optional[typing.List[float]]"
+
 // these typemaps wrap SBModule::GetVersion() from requiring a memory buffer
 // to the more Pythonic style where a list is returned and no previous 
allocation
 // is necessary - this will break if more than 50 versions are ever returned
@@ -469,6 +489,8 @@ template <> bool SetNumberFromPyObject<double>(double 
&number, PyObject *obj) {
   $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
 }
 
+%typemap(pytyping) (lldb::LogOutputCallback log_callback, void *baton) 
"typing.Optional[typing.Callable[[str], None]]"
+
 // For lldb::SBDebuggerDestroyCallback
 %typemap(in) (lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) {
   if (!($input == Py_None ||
@@ -493,6 +515,8 @@ template <> bool SetNumberFromPyObject<double>(double 
&number, PyObject *obj) {
   $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
 }
 
+%typemap(pytyping) (lldb::SBDebuggerDestroyCallback destroy_callback, void 
*baton) "typing.Optional[typing.Callable[[int], None]]"
+
 // For lldb::SBCommandPrintCallback
 %typemap(in) (lldb::SBCommandPrintCallback callback, void *baton) {
   if (!($input == Py_None ||
@@ -512,6 +536,8 @@ template <> bool SetNumberFromPyObject<double>(double 
&number, PyObject *obj) {
   $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
 }
 
+%typemap(pytyping) (lldb::SBCommandPrintCallback callback, void *baton) 
"typing.Optional[typing.Callable[[SBCommandReturnObject], int]]"
+
 %typemap(in) (lldb::CommandOverrideCallback callback, void *baton) {
   if (!($input == Py_None ||
         PyCallable_Check(reinterpret_cast<PyObject *>($input)))) {
@@ -529,6 +555,8 @@ template <> bool SetNumberFromPyObject<double>(double 
&number, PyObject *obj) {
   $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
 }
 
+%typemap(pytyping) (lldb::CommandOverrideCallback callback, void *baton) 
"typing.Optional[typing.Callable[[typing.List[str]], bool]]"
+
 %typemap(in) lldb::FileSP {
   PythonFile py_file(PyRefType::Borrowed, $input);
   if (!py_file) {
@@ -604,6 +632,8 @@ template <> bool SetNumberFromPyObject<double>(double 
&number, PyObject *obj) {
   }
 }
 
+%typemap(pytyping) lldb::FileSP "typing.IO"
+
 %typemap(in) (const char* string, int len) {
   if ($input == Py_None) {
     $1 = NULL;
@@ -628,6 +658,7 @@ template <> bool SetNumberFromPyObject<double>(double 
&number, PyObject *obj) {
   }
 }
 
+%typemap(pytyping) (const char* string, int len) 
"typing.Optional[typing.List[str]]"
 
 // Typemap for SBFile::Write.
 %typemap(in) (const uint8_t *buf, size_t num_bytes) {
@@ -645,6 +676,8 @@ template <> bool SetNumberFromPyObject<double>(double 
&number, PyObject *obj) {
   }
 }
 
+%typemap(pytyping) (const uint8_t *buf, size_t num_bytes) "typing.Union[bytes, 
bytearray]"
+
 // Typemap for SBFile::Read.
 %typemap(in) (uint8_t *buf, size_t num_bytes) {
   if (PythonByteArray::Check($input)) {
@@ -657,6 +690,8 @@ template <> bool SetNumberFromPyObject<double>(double 
&number, PyObject *obj) {
   }
 }
 
+%typemap(pytyping) (uint8_t *buf, size_t num_bytes) "bytearray"
+
 %typemap(in) (const char **symbol_name, uint32_t num_names) {
   using namespace lldb_private;
   /* Check if is a list  */
@@ -684,6 +719,8 @@ template <> bool SetNumberFromPyObject<double>(double 
&number, PyObject *obj) {
   }
 }
 
+%typemap(pytyping) (const char **symbol_name, uint32_t num_names) 
"typing.Optional[typing.List[str]]"
+
 // For lldb::SBPlatformLocateModuleCallback
 %typemap(in) (lldb::SBPlatformLocateModuleCallback callback,
               void *callback_baton) {
@@ -734,3 +771,7 @@ template <> bool SetNumberFromPyObject<double>(double 
&number, PyObject *obj) {
   $1 = $input == Py_None;
   $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input));
 }
+
+%typemap(pytyping)
+  (lldb::SBPlatformLocateModuleCallback callback, void *callback_baton)
+  "typing.Optional[typing.Callable[[SBModuleSpec, SBFileSpec, SBFileSpec], 
SBError]]"
diff --git a/lldb/bindings/python/python.swig b/lldb/bindings/python/python.swig
index 1c9e7a24e5287..6dd4ad388c606 100644
--- a/lldb/bindings/python/python.swig
+++ b/lldb/bindings/python/python.swig
@@ -64,6 +64,68 @@ except ImportError:
 // Parameter types will be used in the autodoc string.
 %feature("autodoc", "1");
 
+#if SWIG_VERSION >= 0x040500
+// Swig 4.5.0 added typing annotations. Use them.
+%feature("python:annotations", "typing");
+
+// The default pytyping entry maps to `typing.Any`. Use the proxy names here.
+// They might generate incorrect annotations (`SWIGTYPE_*`) in more complex 
scenarios.
+%typemap(pytyping) SWIGTYPE      "$&pytypename";
+%typemap(pytyping) SWIGTYPE []   "typing.Optional[$pytypename]";
+%typemap(pytyping) SWIGTYPE *    "typing.Optional[$pytypename]";
+%typemap(pytyping) SWIGTYPE &    "$pytypename";
+%typemap(pytyping) SWIGTYPE &&   "$pytypename";
+%typemap(pytyping) enum SWIGTYPE "int";
+
+// But disable the annotations for the following functions.
+// When the support matures, we can annotate these.
+
+// Exclude operator==/!=. They generate `__eq__(self, rhs: T) -> bool`.
+// However, `rhs` should be `object`.
+%feature("python:annotations", "0") operator==;
+%feature("python:annotations", "0") operator!=;
+
+// Uses (char *dst, size_t dst_len) argout typemap.
+// Should return `str`, but annotated as `int`.
+%feature("python:annotations", "0") lldb::SBProcess::GetSTDOUT;
+%feature("python:annotations", "0") lldb::SBProcess::GetSTDERR;
+%feature("python:annotations", "0") lldb::SBProcess::GetAsyncProfileData;
+%feature("python:annotations", "0") lldb::SBStructuredData::GetStringValue;
+
+// Uses (char *dst_or_null, size_t dst_len) argout typemap.
+// Should return `str`, but annotated as `int`.
+%feature("python:annotations", "0") lldb::SBThread::GetStopDescription;
+
+// Uses (char *dst_path, size_t dst_len) argout typemap.
+// Should return `str`, but annotated as `int`.
+%feature("python:annotations", "0") lldb::SBFileSpec::GetPath;
+%feature("python:annotations", "0") lldb::SBFileSpec::ResolvePath;
+
+// Uses (void *buf, size_t size) argout typemap.
+// Should return `typing.Optional[bytes]`, but annotated as `int`.
+%feature("python:annotations", "0") lldb::SBProcess::ReadMemory;
+%feature("python:annotations", "0") lldb::SBTarget::ReadMemory;
+
+// Uses (void *char_buf, size_t size) argout typemap.
+// Should return `str`, but annotated as `int`.
+%feature("python:annotations", "0") lldb::SBProcess::ReadCStringFromMemory;
+
+// Uses (uint32_t *versions, uint32_t num_versions) argout typemap.
+// Should return `typing.List[int]`, but annotated as `int`.
+%feature("python:annotations", "0") lldb::SBModule::GetVersion;
+
+// Uses INPUT/OUTPUT/INOUT. Not supported by the typing annotations right now.
+%feature("python:annotations", "0") lldb::SBDebugger::RunCommandInterpreter;
+%feature("python:annotations", "0") lldb::SBDebugger::GetProgressFromEvent;
+%feature("python:annotations", "0") lldb::SBFile::Read;
+%feature("python:annotations", "0") lldb::SBFile::Write;
+#else
+// Make sure `typing` is imported in all cases (Swig < 4.5.0).
+%pythoncode %{
+import typing
+%}
+#endif // SWIG_VERSION >= 0x040500
+
 // Include lldb-python first as it sets Py_LIMITED_API.
 %begin %{
 #include "../source/Plugins/ScriptInterpreter/Python/lldb-python.h"

>From 46f31f103ddfe9b05b8dc639bee6c586e14a3fe1 Mon Sep 17 00:00:00 2001
From: Nerixyz <[email protected]>
Date: Thu, 6 Aug 2026 18:57:05 +0200
Subject: [PATCH 2/2] fix: review comments

---
 lldb/bindings/python/python-typemaps.swig | 29 ++++++++++++++++++
 lldb/bindings/python/python.swig          | 37 ++---------------------
 2 files changed, 31 insertions(+), 35 deletions(-)

diff --git a/lldb/bindings/python/python-typemaps.swig 
b/lldb/bindings/python/python-typemaps.swig
index 37f44c619883c..d148bc27ad413 100644
--- a/lldb/bindings/python/python-typemaps.swig
+++ b/lldb/bindings/python/python-typemaps.swig
@@ -210,6 +210,16 @@ AND call SWIG_fail at the same time, because it will 
result in a double free.
 // as char data instead of byte data.
 %typemap(argout) (void *char_buf, size_t size) = (char *dst, size_t dst_len);
 
+// Uses (char *dst, size_t dst_len) argout typemap.
+// Should return `str`, but annotated as `typing.List[typing.Union[int, 
typing.Optional[str]]]`.
+%feature("python:annotations", "0") lldb::SBProcess::GetSTDOUT;
+%feature("python:annotations", "0") lldb::SBProcess::GetSTDERR;
+%feature("python:annotations", "0") lldb::SBProcess::GetAsyncProfileData;
+%feature("python:annotations", "0") lldb::SBStructuredData::GetStringValue;
+
+// Uses (void *char_buf, size_t size) argout typemap.
+// Should return `str`, but annotated as `typing.List[typing.Union[int, 
typing.Optional[SWIGTYPE_p_void]]]`.
+%feature("python:annotations", "0") lldb::SBProcess::ReadCStringFromMemory;
 
 // typemap for handling an snprintf-like API like SBThread::GetStopDescription.
 %typemap(in) (char *dst_or_null, size_t dst_len) {
@@ -250,11 +260,20 @@ AND call SWIG_fail at the same time, because it will 
result in a double free.
   free($1);
 }
 
+// Uses (char *dst_or_null, size_t dst_len) argout typemap.
+// Should return `str`, but annotated as `typing.List[typing.Union[int, 
typing.Optional[str]]]`.
+%feature("python:annotations", "0") lldb::SBThread::GetStopDescription;
+
 
 // For lldb::SBFileSpec::GetPath
 %typemap(in) (char *dst_path, size_t dst_len) = (char *dst_or_null, size_t 
dst_len);
 %typemap(argout) (char *dst_path, size_t dst_len) = (char *dst_or_null, size_t 
dst_len);
 
+// Uses (char *dst_path, size_t dst_len) argout typemap.
+// Should return `str`, but annotated as `typing.List[typing.Union[int, 
typing.Optional[str]]]`.
+%feature("python:annotations", "0") lldb::SBFileSpec::GetPath;
+%feature("python:annotations", "0") lldb::SBFileSpec::ResolvePath;
+
 
 // typemap for an outgoing buffer
 // See also SBEvent::SBEvent(uint32_t event, const char *cstr, uint32_t 
cstr_len).
@@ -338,6 +357,12 @@ AND call SWIG_fail at the same time, because it will 
result in a double free.
   free($1);
 }
 
+// Uses (void *buf, size_t size) argout typemap.
+// Should return `typing.Optional[bytes]`, but annotated as 
`typing.List[typing.Union[int, typing.Optional[SWIGTYPE_p_void]]]`.
+%feature("python:annotations", "0") lldb::SBProcess::ReadMemory;
+%feature("python:annotations", "0") lldb::SBTarget::ReadMemory;
+%feature("python:annotations", "0") lldb::SBData::ReadRawData;
+
 %{
 namespace {
 template <class T>
@@ -465,6 +490,10 @@ template <> bool SetNumberFromPyObject<double>(double 
&number, PyObject *obj) {
   free($1);
 }
 
+// Uses (uint32_t *versions, uint32_t num_versions) argout typemap.
+// Should return `typing.List[int]`, but annotated as 
`typing.List[typing.Union[int, typing.Optional[SWIGTYPE_p_unsigned_int]]]`.
+%feature("python:annotations", "0") lldb::SBModule::GetVersion;
+
 // For Log::LogOutputCallback
 %typemap(in) (lldb::LogOutputCallback log_callback, void *baton) {
   if (!($input == Py_None ||
diff --git a/lldb/bindings/python/python.swig b/lldb/bindings/python/python.swig
index 6dd4ad388c606..a44f5746e5a54 100644
--- a/lldb/bindings/python/python.swig
+++ b/lldb/bindings/python/python.swig
@@ -65,7 +65,6 @@ except ImportError:
 %feature("autodoc", "1");
 
 #if SWIG_VERSION >= 0x040500
-// Swig 4.5.0 added typing annotations. Use them.
 %feature("python:annotations", "typing");
 
 // The default pytyping entry maps to `typing.Any`. Use the proxy names here.
@@ -77,46 +76,14 @@ except ImportError:
 %typemap(pytyping) SWIGTYPE &&   "$pytypename";
 %typemap(pytyping) enum SWIGTYPE "int";
 
-// But disable the annotations for the following functions.
-// When the support matures, we can annotate these.
-
 // Exclude operator==/!=. They generate `__eq__(self, rhs: T) -> bool`.
 // However, `rhs` should be `object`.
 %feature("python:annotations", "0") operator==;
 %feature("python:annotations", "0") operator!=;
 
-// Uses (char *dst, size_t dst_len) argout typemap.
-// Should return `str`, but annotated as `int`.
-%feature("python:annotations", "0") lldb::SBProcess::GetSTDOUT;
-%feature("python:annotations", "0") lldb::SBProcess::GetSTDERR;
-%feature("python:annotations", "0") lldb::SBProcess::GetAsyncProfileData;
-%feature("python:annotations", "0") lldb::SBStructuredData::GetStringValue;
-
-// Uses (char *dst_or_null, size_t dst_len) argout typemap.
-// Should return `str`, but annotated as `int`.
-%feature("python:annotations", "0") lldb::SBThread::GetStopDescription;
-
-// Uses (char *dst_path, size_t dst_len) argout typemap.
-// Should return `str`, but annotated as `int`.
-%feature("python:annotations", "0") lldb::SBFileSpec::GetPath;
-%feature("python:annotations", "0") lldb::SBFileSpec::ResolvePath;
-
-// Uses (void *buf, size_t size) argout typemap.
-// Should return `typing.Optional[bytes]`, but annotated as `int`.
-%feature("python:annotations", "0") lldb::SBProcess::ReadMemory;
-%feature("python:annotations", "0") lldb::SBTarget::ReadMemory;
-
-// Uses (void *char_buf, size_t size) argout typemap.
-// Should return `str`, but annotated as `int`.
-%feature("python:annotations", "0") lldb::SBProcess::ReadCStringFromMemory;
-
-// Uses (uint32_t *versions, uint32_t num_versions) argout typemap.
-// Should return `typing.List[int]`, but annotated as `int`.
-%feature("python:annotations", "0") lldb::SBModule::GetVersion;
-
-// Uses INPUT/OUTPUT/INOUT. Not supported by the typing annotations right now.
-%feature("python:annotations", "0") lldb::SBDebugger::RunCommandInterpreter;
+// OUTPUT/INOUT is not supported by the typing annotations right now.
 %feature("python:annotations", "0") lldb::SBDebugger::GetProgressFromEvent;
+%feature("python:annotations", "0") lldb::SBDebugger::RunCommandInterpreter;
 %feature("python:annotations", "0") lldb::SBFile::Read;
 %feature("python:annotations", "0") lldb::SBFile::Write;
 #else

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to