https://github.com/fscheidl updated https://github.com/llvm/llvm-project/pull/183305
>From 457cd587131d837561baf89c77e65aeb97849d0c Mon Sep 17 00:00:00 2001 From: Fabian Scheidl <[email protected]> Date: Wed, 25 Feb 2026 15:58:42 +0100 Subject: [PATCH] [libclang] Add clang_CXXMethod_isVolatile and clang_Cursor_isConstexpr --- clang/bindings/python/clang/cindex.py | 14 ++++++++ .../python/tests/cindex/test_cursor.py | 32 +++++++++++++++++++ clang/docs/ReleaseNotes.rst | 5 +++ clang/include/clang-c/Index.h | 11 +++++++ clang/test/Index/cursor-properties.cpp | 18 +++++++++++ clang/tools/c-index-test/c-index-test.c | 4 +++ clang/tools/libclang/CIndex.cpp | 26 +++++++++++++++ clang/tools/libclang/libclang.map | 6 ++++ 8 files changed, 116 insertions(+) create mode 100644 clang/test/Index/cursor-properties.cpp diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py index 1896a0a9c1c34..b589771ce72c5 100644 --- a/clang/bindings/python/clang/cindex.py +++ b/clang/bindings/python/clang/cindex.py @@ -1680,6 +1680,13 @@ def is_const_method(self) -> bool: """ return bool(conf.lib.clang_CXXMethod_isConst(self)) + @cursor_null_guard + def is_volatile_method(self) -> bool: + """Returns True if the cursor refers to a C++ member function or member + function template that is declared 'volatile'. + """ + return bool(conf.lib.clang_CXXMethod_isVolatile(self)) + @cursor_null_guard def is_converting_constructor(self) -> bool: """Returns True if the cursor refers to a C++ converting constructor.""" @@ -1852,6 +1859,11 @@ def is_scoped_enum(self) -> bool: """Returns True if the cursor refers to a scoped enum declaration.""" return bool(conf.lib.clang_EnumDecl_isScoped(self)) + @cursor_null_guard + def is_constexpr(self) -> bool: + """Returns True if the cursor refers to a constexpr declaration.""" + return bool(conf.lib.clang_Cursor_isConstexpr(self)) + @cursor_null_guard def get_definition(self) -> Cursor | None: """ @@ -4251,6 +4263,7 @@ def set_property(self, property, value): ("clang_CXXConstructor_isMoveConstructor", [Cursor], c_uint), ("clang_CXXField_isMutable", [Cursor], c_uint), ("clang_CXXMethod_isConst", [Cursor], c_uint), + ("clang_CXXMethod_isVolatile", [Cursor], c_uint), ("clang_CXXMethod_isDefaulted", [Cursor], c_uint), ("clang_CXXMethod_isDeleted", [Cursor], c_uint), ("clang_CXXMethod_isCopyAssignmentOperator", [Cursor], c_uint), @@ -4436,6 +4449,7 @@ def set_property(self, property, value): ("clang_Cursor_isAnonymousRecordDecl", [Cursor], c_uint), ("clang_Cursor_isBitField", [Cursor], c_uint), ("clang_Cursor_isFunctionInlined", [Cursor], c_uint), + ("clang_Cursor_isConstexpr", [Cursor], c_uint), ("clang_Location_isInSystemHeader", [SourceLocation], c_int), ("clang_PrintingPolicy_dispose", [PrintingPolicy]), ("clang_PrintingPolicy_getProperty", [PrintingPolicy, c_int], c_uint), diff --git a/clang/bindings/python/tests/cindex/test_cursor.py b/clang/bindings/python/tests/cindex/test_cursor.py index 76680e576b307..9ed26624cc907 100644 --- a/clang/bindings/python/tests/cindex/test_cursor.py +++ b/clang/bindings/python/tests/cindex/test_cursor.py @@ -197,6 +197,19 @@ def test_is_const_method(self): self.assertTrue(foo.is_const_method()) self.assertFalse(bar.is_const_method()) + def test_is_volatile_method(self): + """Ensure Cursor.is_volatile_method works.""" + source = "class X { void foo() volatile; void bar(); };" + tu = get_tu(source, lang="cpp") + + foo = get_cursor(tu, "foo") + bar = get_cursor(tu, "bar") + self.assertIsNotNone(foo) + self.assertIsNotNone(bar) + + self.assertTrue(foo.is_volatile_method()) + self.assertFalse(bar.is_volatile_method()) + def test_is_converting_constructor(self): """Ensure Cursor.is_converting_constructor works.""" source = "class X { explicit X(int); X(double); X(); };" @@ -565,6 +578,25 @@ def test_is_scoped_enum(self): self.assertFalse(regular_enum.is_scoped_enum()) self.assertTrue(scoped_enum.is_scoped_enum()) + def test_is_constexpr(self): + """Ensure Cursor.is_constexpr works.""" + source = "constexpr int x = 42; int y = 1; struct S { constexpr int foo() { return 1; } int bar() { return 2; } };" + tu = get_tu(source, lang="cpp", flags=["--std=c++14"]) + + x = get_cursor(tu, "x") + y = get_cursor(tu, "y") + foo = get_cursor(tu, "foo") + bar = get_cursor(tu, "bar") + self.assertIsNotNone(x) + self.assertIsNotNone(y) + self.assertIsNotNone(foo) + self.assertIsNotNone(bar) + + self.assertTrue(x.is_constexpr()) + self.assertFalse(y.is_constexpr()) + self.assertTrue(foo.is_constexpr()) + self.assertFalse(bar.is_constexpr()) + def test_get_definition(self): """Ensure Cursor.get_definition works.""" tu = get_tu( diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index cb1010aee1edd..2aed5c929dcda 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -431,6 +431,9 @@ libclang - Visit switch initializer statements (https://bugs.kde.org/show_bug.cgi?id=415537#c2) - Fix crash in clang_getBinaryOperatorKindSpelling and clang_getUnaryOperatorKindSpelling +- Added ``clang_CXXMethod_isVolatile`` to determine if a C++ method is declared volatile. +- Added ``clang_Cursor_isConstexpr`` to determine if a cursor refers to a constexpr declaration. + Code Completion --------------- @@ -468,6 +471,8 @@ Python Binding Changes ``CodeCompletionResults.results`` should be changed to directly use ``CodeCompletionResults``: it nows supports ``__len__`` and ``__getitem__``, so it can be used the same as ``CodeCompletionResults.results``. +- Added ``Cursor.is_volatile_method``, a binding for ``clang_CXXMethod_isVolatile``. +- Added ``Cursor.is_constexpr``, a binding for ``clang_Cursor_isConstexpr``. OpenMP Support -------------- diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 203634c80d82a..bf24285ba20d6 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -3351,6 +3351,11 @@ CINDEX_LINKAGE unsigned clang_Cursor_isMacroBuiltin(CXCursor C); */ CINDEX_LINKAGE unsigned clang_Cursor_isFunctionInlined(CXCursor C); +/** + * Determine whether a cursor refers to a constexpr declaration. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isConstexpr(CXCursor C); + /** * Determine whether a CXType has the "volatile" qualifier set, * without looking through typedefs that may have added "volatile" at @@ -4883,6 +4888,12 @@ CINDEX_LINKAGE unsigned clang_EnumDecl_isScoped(CXCursor C); */ CINDEX_LINKAGE unsigned clang_CXXMethod_isConst(CXCursor C); +/** + * Determine if a C++ member function or member function template is + * declared 'volatile'. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isVolatile(CXCursor C); + /** * Given a cursor that represents a template, determine * the cursor kind of the specializations would be generated by instantiating diff --git a/clang/test/Index/cursor-properties.cpp b/clang/test/Index/cursor-properties.cpp new file mode 100644 index 0000000000000..efa4c9a6f7286 --- /dev/null +++ b/clang/test/Index/cursor-properties.cpp @@ -0,0 +1,18 @@ +struct Foo { + void normal(); + void bar() const; + void bar() volatile; + void bar() const volatile; + constexpr int baz() { return 1; } +}; +constexpr int x = 42; +int y = 1; + +// RUN: c-index-test -test-print-type --std=c++14 %s | FileCheck %s +// CHECK: CXXMethod=normal:2:8 [type=void ()] [typekind=FunctionProto] [resulttype=void] [resulttypekind=Void] [isPOD=0] +// CHECK: CXXMethod=bar:3:8 (const) [type=void () const] [typekind=FunctionProto] [resulttype=void] [resulttypekind=Void] [isPOD=0] +// CHECK: CXXMethod=bar:4:8 (volatile) [type=void () volatile] [typekind=FunctionProto] [resulttype=void] [resulttypekind=Void] [isPOD=0] +// CHECK: CXXMethod=bar:5:8 (const) (volatile) [type=void () const volatile] [typekind=FunctionProto] [resulttype=void] [resulttypekind=Void] [isPOD=0] +// CHECK: CXXMethod=baz:6:17 (Definition) (constexpr) [type=int ()] [typekind=FunctionProto] [resulttype=int] [resulttypekind=Int] [isPOD=0] +// CHECK: VarDecl=x:8:15 (Definition) (constexpr) [type=const int] [typekind=Int] const [isPOD=1] +// CHECK: VarDecl=y:9:5 (Definition) [type=int] [typekind=Int] [isPOD=1] diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c index cb3245756a394..89970855ca537 100644 --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -954,6 +954,8 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) { printf(" (virtual)"); if (clang_CXXMethod_isConst(Cursor)) printf(" (const)"); + if (clang_CXXMethod_isVolatile(Cursor)) + printf(" (volatile)"); if (clang_CXXMethod_isPureVirtual(Cursor)) printf(" (pure)"); if (clang_CXXMethod_isCopyAssignmentOperator(Cursor)) @@ -966,6 +968,8 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) { printf(" (abstract)"); if (clang_EnumDecl_isScoped(Cursor)) printf(" (scoped)"); + if (clang_Cursor_isConstexpr(Cursor)) + printf(" (constexpr)"); if (clang_Cursor_isVariadic(Cursor)) printf(" (variadic)"); if (clang_Cursor_isObjCOptional(Cursor)) diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 31b6a3222d916..a2c145d1fa2e3 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -9538,6 +9538,16 @@ unsigned clang_CXXMethod_isConst(CXCursor C) { return (Method && Method->getMethodQualifiers().hasConst()) ? 1 : 0; } +unsigned clang_CXXMethod_isVolatile(CXCursor C) { + if (!clang_isDeclaration(C.kind)) + return 0; + + const Decl *D = cxcursor::getCursorDecl(C); + const CXXMethodDecl *Method = + D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : nullptr; + return (Method && Method->getMethodQualifiers().hasVolatile()) ? 1 : 0; +} + unsigned clang_CXXMethod_isDefaulted(CXCursor C) { if (!clang_isDeclaration(C.kind)) return 0; @@ -9619,6 +9629,22 @@ unsigned clang_CXXMethod_isExplicit(CXCursor C) { return 0; } +unsigned clang_Cursor_isConstexpr(CXCursor C) { + if (!clang_isDeclaration(C.kind)) + return 0; + + const Decl *D = cxcursor::getCursorDecl(C); + if (!D) + return 0; + + if (const auto *VD = dyn_cast<VarDecl>(D)) + return VD->isConstexpr(); + if (const auto *FD = dyn_cast<FunctionDecl>(D)) + return FD->isConstexpr(); + + return 0; +} + unsigned clang_CXXRecord_isAbstract(CXCursor C) { if (!clang_isDeclaration(C.kind)) return 0; diff --git a/clang/tools/libclang/libclang.map b/clang/tools/libclang/libclang.map index 3d9d2e268a611..a4018bb6c12bf 100644 --- a/clang/tools/libclang/libclang.map +++ b/clang/tools/libclang/libclang.map @@ -457,6 +457,12 @@ LLVM_21 { clang_Cursor_isGCCAssemblyVolatile; }; +LLVM_23 { + global: + clang_Cursor_isConstexpr; + clang_CXXMethod_isVolatile; +}; + # Example of how to add a new symbol version entry. If you do add a new symbol # version, please update the example to depend on the version you added. # LLVM_X { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
