Skip to content

Commit

Permalink
[cindex] Add API to query the class methods of a type (llvm#123539)
Browse files Browse the repository at this point in the history
Inspired by llvm#120300, add a new
API `clang_visitCXXMethods` to libclang (and the Python bindings) which
allows iterating over the class methods of a type.

---------

Co-authored-by: Vlad Serebrennikov <[email protected]>
Co-authored-by: Aaron Ballman <[email protected]>
  • Loading branch information
3 people authored Mar 1, 2025
1 parent fe18796 commit 304c053
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 0 deletions.
16 changes: 16 additions & 0 deletions clang/bindings/python/clang/cindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -2713,6 +2713,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
Expand Down Expand Up @@ -4020,6 +4035,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),
Expand Down
18 changes: 18 additions & 0 deletions clang/bindings/python/tests/cindex/test_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
4 changes: 4 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,8 @@ clang-format

libclang
--------
- Added ``clang_visitCXXMethods``, which allows visiting the methods
of a class.

- Fixed a buffer overflow in ``CXString`` implementation. The fix may result in
increased memory allocation.
Expand Down Expand Up @@ -388,6 +390,8 @@ Sanitizers

Python Binding Changes
----------------------
- Added ``Type.get_methods``, a binding for ``clang_visitCXXMethods``, which
allows visiting the methods of a class.

OpenMP Support
--------------
Expand Down
22 changes: 22 additions & 0 deletions clang/include/clang-c/Index.h
Original file line number Diff line number Diff line change
Expand Up @@ -6628,6 +6628,28 @@ 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.
*/
Expand Down
26 changes: 26 additions & 0 deletions clang/tools/libclang/CIndexCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,32 @@ 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 auto *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 (const 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;

Expand Down
1 change: 1 addition & 0 deletions clang/tools/libclang/libclang.map
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,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
Expand Down

0 comments on commit 304c053

Please sign in to comment.