https://github.com/trelau updated https://github.com/llvm/llvm-project/pull/123539
>From bb0542e8f2ad50892ee9d2c1f76ec1def85c3e56 Mon Sep 17 00:00:00 2001 From: Trevor Laughlin <trevor.w.laugh...@gmail.com> Date: Sun, 19 Jan 2025 19:21:10 -0500 Subject: [PATCH 1/3] [cindex] Add API to query the class methods of a type --- clang/bindings/python/clang/cindex.py | 16 +++++++++++ .../bindings/python/tests/cindex/test_type.py | 18 +++++++++++++ clang/docs/ReleaseNotes.rst | 4 +++ clang/include/clang-c/Index.h | 23 ++++++++++++++++ clang/tools/libclang/CIndexCXX.cpp | 27 +++++++++++++++++++ clang/tools/libclang/libclang.map | 1 + 6 files changed, 89 insertions(+) diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py index 806e1b40f3c9e..9e65ea2942d16 100644 --- a/clang/bindings/python/clang/cindex.py +++ b/clang/bindings/python/clang/cindex.py @@ -2710,6 +2710,21 @@ def visitor(base, children): conf.lib.clang_visitCXXBaseClasses(self, fields_visit_callback(visitor), bases) return iter(bases) + def get_methods(self): + """Return an iterator for accessing the methods of this type.""" + + def visitor(method, children): + assert method != conf.lib.clang_getNullCursor() + + # Create reference to TU so it isn't GC'd before Cursor. + method._tu = self._tu + methods.append(method) + return 1 # continue + + methods: list[Cursor] = [] + conf.lib.clang_visitCXXMethods(self, fields_visit_callback(visitor), methods) + return iter(methods) + def get_exception_specification_kind(self): """ Return the kind of the exception specification; a value from @@ -4017,6 +4032,7 @@ def set_property(self, property, value): ), ("clang_visitChildren", [Cursor, cursor_visit_callback, py_object], c_uint), ("clang_visitCXXBaseClasses", [Type, fields_visit_callback, py_object], c_uint), + ("clang_visitCXXMethods", [Type, fields_visit_callback, py_object], c_uint), ("clang_Cursor_getNumArguments", [Cursor], c_int), ("clang_Cursor_getArgument", [Cursor, c_uint], Cursor), ("clang_Cursor_getNumTemplateArguments", [Cursor], c_int), diff --git a/clang/bindings/python/tests/cindex/test_type.py b/clang/bindings/python/tests/cindex/test_type.py index 9bac33f3041f4..bc893d509524e 100644 --- a/clang/bindings/python/tests/cindex/test_type.py +++ b/clang/bindings/python/tests/cindex/test_type.py @@ -559,3 +559,21 @@ class Template : public A, public B, virtual C { self.assertEqual(bases[1].get_base_offsetof(cursor_type_decl), 96) self.assertTrue(bases[2].is_virtual_base()) self.assertEqual(bases[2].get_base_offsetof(cursor_type_decl), 128) + + def test_class_methods(self): + source = """ + template <typename T> + class Template { void Foo(); }; + typedef Template<int> instance; + instance bar; + """ + tu = get_tu(source, lang="cpp", flags=["--target=x86_64-linux-gnu"]) + cursor = get_cursor(tu, "instance") + cursor_type = cursor.underlying_typedef_type + self.assertEqual(cursor.kind, CursorKind.TYPEDEF_DECL) + methods = list(cursor_type.get_methods()) + self.assertEqual(len(methods), 4) + self.assertEqual(methods[0].kind, CursorKind.CXX_METHOD) + self.assertEqual(methods[1].kind, CursorKind.CONSTRUCTOR) + self.assertEqual(methods[2].kind, CursorKind.CONSTRUCTOR) + self.assertEqual(methods[3].kind, CursorKind.CONSTRUCTOR) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b02ac467cd3a2..dd9f722a6a08c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -1241,6 +1241,8 @@ libclang of a class. - Added ``clang_getOffsetOfBase``, which allows computing the offset of a base class in a class's layout. +- Added ``clang_visitCXXMethods``, which allows visiting the methods + of a class. Static Analyzer --------------- @@ -1394,6 +1396,8 @@ Python Binding Changes allows visiting the base classes of a class. - Added ``Cursor.get_base_offsetof``, a binding for ``clang_getOffsetOfBase``, which allows computing the offset of a base class in a class's layout. +- Added ``Type.get_methods``, a binding for ``clang_visitCXXMethods``, which + allows visiting the methods of a class. OpenMP Support -------------- diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index aac5d1fa8aa2e..5d961ca0cdd7f 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -6680,6 +6680,29 @@ CINDEX_LINKAGE unsigned clang_visitCXXBaseClasses(CXType T, CXFieldVisitor visitor, CXClientData client_data); +/** + * Visit the class methods of a type. + * + * This function visits all the methods of the given cursor, + * invoking the given \p visitor function with the cursors of each + * visited method. The traversal may be ended prematurely, if + * the visitor returns \c CXFieldVisit_Break. + * + * \param T the record type whose field may be visited. + * + * \param visitor the visitor function that will be invoked for each + * field of \p T. + * + * \param client_data pointer data supplied by the client, which will + * be passed to the visitor each time it is invoked. + * + * \returns a non-zero value if the traversal was terminated + * prematurely by the visitor returning \c CXFieldVisit_Break. + */ +CINDEX_LINKAGE unsigned clang_visitCXXMethods(CXType T, + CXFieldVisitor visitor, + CXClientData client_data); + /** * Describes the kind of binary operators. */ diff --git a/clang/tools/libclang/CIndexCXX.cpp b/clang/tools/libclang/CIndexCXX.cpp index 8b84fdc22ecff..4d8ff696950b3 100644 --- a/clang/tools/libclang/CIndexCXX.cpp +++ b/clang/tools/libclang/CIndexCXX.cpp @@ -54,6 +54,33 @@ unsigned clang_visitCXXBaseClasses(CXType PT, CXFieldVisitor visitor, return true; } +unsigned clang_visitCXXMethods(CXType PT, CXFieldVisitor visitor, + CXClientData client_data) { + CXCursor PC = clang_getTypeDeclaration(PT); + if (clang_isInvalid(PC.kind)) + return false; + const CXXRecordDecl *RD = + dyn_cast_if_present<CXXRecordDecl>(cxcursor::getCursorDecl(PC)); + if (!RD || RD->isInvalidDecl()) + return false; + RD = RD->getDefinition(); + if (!RD || RD->isInvalidDecl()) + return false; + + for (auto Method : RD->methods()) { + // Callback to the client. + switch ( + visitor(cxcursor::MakeCXCursor(Method, getCursorTU(PC)), + client_data)) { + case CXVisit_Break: + return true; + case CXVisit_Continue: + break; + } + } + return true; +} + enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) { AccessSpecifier spec = AS_none; diff --git a/clang/tools/libclang/libclang.map b/clang/tools/libclang/libclang.map index 8ca8a58b76d9e..a86c5a95303f8 100644 --- a/clang/tools/libclang/libclang.map +++ b/clang/tools/libclang/libclang.map @@ -440,6 +440,7 @@ LLVM_20 { clang_getTypePrettyPrinted; clang_isBeforeInTranslationUnit; clang_visitCXXBaseClasses; + clang_visitCXXMethods; }; # Example of how to add a new symbol version entry. If you do add a new symbol >From 76a3b8f891216994cc586956524caef0b57de6cf Mon Sep 17 00:00:00 2001 From: Trevor Laughlin <trevor.w.laugh...@gmail.com> Date: Sat, 15 Feb 2025 19:52:48 -0500 Subject: [PATCH 2/3] Update to const auto *Method Co-authored-by: Vlad Serebrennikov <serebrennikov.vladis...@gmail.com> --- clang/tools/libclang/CIndexCXX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/tools/libclang/CIndexCXX.cpp b/clang/tools/libclang/CIndexCXX.cpp index 4d8ff696950b3..cb4442da2e8d1 100644 --- a/clang/tools/libclang/CIndexCXX.cpp +++ b/clang/tools/libclang/CIndexCXX.cpp @@ -67,7 +67,7 @@ unsigned clang_visitCXXMethods(CXType PT, CXFieldVisitor visitor, if (!RD || RD->isInvalidDecl()) return false; - for (auto Method : RD->methods()) { + for (const auto *Method : RD->methods()) { // Callback to the client. switch ( visitor(cxcursor::MakeCXCursor(Method, getCursorTU(PC)), >From 197eb868f253bf31b2d61efe7e654beaa7da2a16 Mon Sep 17 00:00:00 2001 From: Trevor Laughlin <trevor.w.laugh...@gmail.com> Date: Fri, 21 Feb 2025 21:10:36 -0800 Subject: [PATCH 3/3] Fix capitalization Co-authored-by: Aaron Ballman <aa...@aaronballman.com> --- clang/include/clang-c/Index.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 622435b03bc1a..50cf464aa442f 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -6636,15 +6636,15 @@ CINDEX_LINKAGE unsigned clang_visitCXXBaseClasses(CXType T, * visited method. The traversal may be ended prematurely, if * the visitor returns \c CXFieldVisit_Break. * - * \param T the record type whose field may be visited. + * \param T The record type whose field may be visited. * - * \param visitor the visitor function that will be invoked for each + * \param visitor The visitor function that will be invoked for each * field of \p T. * - * \param client_data pointer data supplied by the client, which will + * \param client_data Pointer data supplied by the client, which will * be passed to the visitor each time it is invoked. * - * \returns a non-zero value if the traversal was terminated + * \returns A non-zero value if the traversal was terminated * prematurely by the visitor returning \c CXFieldVisit_Break. */ CINDEX_LINKAGE unsigned clang_visitCXXMethods(CXType T, _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits