[clang] [libclang/python] Ensure all used library functions are registered (PR #140015)
Jannick Kremer via cfe-commits
cfe-commits at lists.llvm.org
Thu May 15 23:31:06 PDT 2025
https://github.com/DeinAlptraum updated https://github.com/llvm/llvm-project/pull/140015
>From c3c0adfe4a7dce3568a81594588be53d761b5980 Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Thu, 15 May 2025 15:58:00 +0900
Subject: [PATCH 1/5] [libclang/python] Ensure all library functions are
registered
---
clang/bindings/python/tests/cindex/test_lib.py | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 clang/bindings/python/tests/cindex/test_lib.py
diff --git a/clang/bindings/python/tests/cindex/test_lib.py b/clang/bindings/python/tests/cindex/test_lib.py
new file mode 100644
index 0000000000000..f8f892731500b
--- /dev/null
+++ b/clang/bindings/python/tests/cindex/test_lib.py
@@ -0,0 +1,17 @@
+import os
+
+from clang.cindex import Config, conf, FUNCTION_LIST
+
+if "CLANG_LIBRARY_PATH" in os.environ:
+ Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])
+
+import unittest
+
+
+class TestIndex(unittest.TestCase):
+ def test_functions_registered(self):
+ IGNORED = set(["_FuncPtr", "_name", "_handle"])
+ lib_functions = set(vars(conf.lib).keys())
+ registered_functions = set([item[0] for item in FUNCTION_LIST])
+ unregistered_functions = lib_functions - registered_functions - IGNORED
+ self.assertEqual(unregistered_functions, set())
>From 2962bfb7c190d11119739201eca56852d26d2895 Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Thu, 15 May 2025 17:20:55 +0900
Subject: [PATCH 2/5] Add missing entries to FUNCTION_LIST
---
clang/bindings/python/clang/cindex.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 4ff7f318416b7..a638bc88e98d6 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -3970,6 +3970,7 @@ def set_property(self, property, value):
("clang_getCursorAvailability", [Cursor], c_int),
("clang_getCursorDefinition", [Cursor], Cursor),
("clang_getCursorDisplayName", [Cursor], _CXString),
+ ("clang_getCursorExceptionSpecificationType", [Cursor], c_int),
("clang_getCursorExtent", [Cursor], SourceRange),
("clang_getCursorLexicalParent", [Cursor], Cursor),
("clang_getCursorLocation", [Cursor], SourceLocation),
@@ -3980,6 +3981,7 @@ def set_property(self, property, value):
("clang_getCursorResultType", [Cursor], Type),
("clang_getCursorSemanticParent", [Cursor], Cursor),
("clang_getCursorSpelling", [Cursor], _CXString),
+ ("clang_getCursorTLSKind", [Cursor], c_int),
("clang_getCursorType", [Cursor], Type),
("clang_getCursorUSR", [Cursor], _CXString),
("clang_Cursor_getMangling", [Cursor], _CXString),
@@ -4005,6 +4007,7 @@ def set_property(self, property, value):
("clang_getEnumConstantDeclUnsignedValue", [Cursor], c_ulonglong),
("clang_getEnumConstantDeclValue", [Cursor], c_longlong),
("clang_getEnumDeclIntegerType", [Cursor], Type),
+ ("clang_getExceptionSpecificationType", [Type], c_int),
("clang_getFile", [TranslationUnit, c_interop_string], c_object_p),
("clang_getFileName", [File], _CXString),
("clang_getFileTime", [File], c_uint),
@@ -4101,6 +4104,7 @@ def set_property(self, property, value):
("clang_Cursor_getBriefCommentText", [Cursor], _CXString),
("clang_Cursor_getRawCommentText", [Cursor], _CXString),
("clang_Cursor_getOffsetOfField", [Cursor], c_longlong),
+ ("clang_Cursor_getStorageClass", [Cursor], c_int),
("clang_Cursor_isAnonymous", [Cursor], bool),
("clang_Cursor_isAnonymousRecordDecl", [Cursor], bool),
("clang_Cursor_isBitField", [Cursor], bool),
>From f0dc3c5a80416eb5670911f3fa2a0583909831f4 Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Fri, 16 May 2025 12:26:34 +0900
Subject: [PATCH 3/5] Gather used library functions via AST analysis
---
.../bindings/python/tests/cindex/test_lib.py | 30 ++++++++++++++-----
1 file changed, 22 insertions(+), 8 deletions(-)
diff --git a/clang/bindings/python/tests/cindex/test_lib.py b/clang/bindings/python/tests/cindex/test_lib.py
index f8f892731500b..c5369838a2c84 100644
--- a/clang/bindings/python/tests/cindex/test_lib.py
+++ b/clang/bindings/python/tests/cindex/test_lib.py
@@ -1,17 +1,31 @@
import os
-from clang.cindex import Config, conf, FUNCTION_LIST
+import clang.cindex
if "CLANG_LIBRARY_PATH" in os.environ:
- Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])
+ clang.cindex.Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])
import unittest
+import ast
-class TestIndex(unittest.TestCase):
+class TestLib(unittest.TestCase):
def test_functions_registered(self):
- IGNORED = set(["_FuncPtr", "_name", "_handle"])
- lib_functions = set(vars(conf.lib).keys())
- registered_functions = set([item[0] for item in FUNCTION_LIST])
- unregistered_functions = lib_functions - registered_functions - IGNORED
- self.assertEqual(unregistered_functions, set())
+
+ def get_function_spelling(node):
+ # The call expressions we are interested in have their spelling in .attr, not .id
+ if hasattr(node, "attr"):
+ return node.attr
+ return ""
+
+ filename = clang.cindex.__file__
+ with open(filename) as file:
+ root = ast.parse(file.read())
+ functions = [
+ get_function_spelling(node.func)
+ for node in ast.walk(root)
+ if isinstance(node, ast.Call)
+ ]
+ used_functions = set([func for func in functions if func.startswith("clang_")])
+ registered_functions = set([item[0] for item in clang.cindex.FUNCTION_LIST])
+ self.assertEqual(used_functions - registered_functions, set())
>From acd9965dba83bd7488d819c34ca477f52fd1f1bf Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Fri, 16 May 2025 12:42:09 +0900
Subject: [PATCH 4/5] Add missing library functions
---
clang/bindings/python/clang/cindex.py | 2 ++
clang/bindings/python/tests/cindex/test_lib.py | 1 -
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index a638bc88e98d6..f06eff1e0c1b0 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -3952,6 +3952,7 @@ def set_property(self, property, value):
("clang_equalRanges", [SourceRange, SourceRange], bool),
("clang_equalTypes", [Type, Type], bool),
("clang_formatDiagnostic", [Diagnostic, c_uint], _CXString),
+ ("clang_getAddressSpace", [Type], c_uint),
("clang_getArgType", [Type, c_uint], Type),
("clang_getArrayElementType", [Type], Type),
("clang_getArraySize", [Type], c_longlong),
@@ -3973,6 +3974,7 @@ def set_property(self, property, value):
("clang_getCursorExceptionSpecificationType", [Cursor], c_int),
("clang_getCursorExtent", [Cursor], SourceRange),
("clang_getCursorLexicalParent", [Cursor], Cursor),
+ ("clang_getCursorLinkage", [Cursor], c_int),
("clang_getCursorLocation", [Cursor], SourceLocation),
("clang_getCursorPrettyPrinted", [Cursor, PrintingPolicy], _CXString),
("clang_getCursorPrintingPolicy", [Cursor], c_object_p),
diff --git a/clang/bindings/python/tests/cindex/test_lib.py b/clang/bindings/python/tests/cindex/test_lib.py
index c5369838a2c84..ee125fbcf2b7a 100644
--- a/clang/bindings/python/tests/cindex/test_lib.py
+++ b/clang/bindings/python/tests/cindex/test_lib.py
@@ -11,7 +11,6 @@
class TestLib(unittest.TestCase):
def test_functions_registered(self):
-
def get_function_spelling(node):
# The call expressions we are interested in have their spelling in .attr, not .id
if hasattr(node, "attr"):
>From ca2f496b82eec584dcad20eceed3f7a891daf1f0 Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Fri, 16 May 2025 15:30:32 +0900
Subject: [PATCH 5/5] Fix formatting
---
clang/bindings/python/tests/cindex/test_lib.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/bindings/python/tests/cindex/test_lib.py b/clang/bindings/python/tests/cindex/test_lib.py
index ee125fbcf2b7a..5e88ebf9d8448 100644
--- a/clang/bindings/python/tests/cindex/test_lib.py
+++ b/clang/bindings/python/tests/cindex/test_lib.py
@@ -12,7 +12,8 @@
class TestLib(unittest.TestCase):
def test_functions_registered(self):
def get_function_spelling(node):
- # The call expressions we are interested in have their spelling in .attr, not .id
+ # The call expressions we are interested in have
+ # their spelling in .attr, not .id
if hasattr(node, "attr"):
return node.attr
return ""
More information about the cfe-commits
mailing list