[clang] [libclang] Add support for constexpr in Python bindings and C API (PR #188965)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 27 04:05:53 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Jonathan B. Coe (jbcoe)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/188965.diff
5 Files Affected:
- (modified) clang/bindings/python/clang/cindex.py (+9)
- (added) clang/bindings/python/tests/cindex/test_constexpr.py (+54)
- (modified) clang/include/clang-c/Index.h (+6)
- (modified) clang/tools/libclang/CIndex.cpp (+9)
- (modified) clang/tools/libclang/libclang.map (+1)
``````````diff
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index b71f9ed2275e0..d86f7d07296dd 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -2375,6 +2375,14 @@ def is_function_inlined(self) -> bool:
"""
return bool(conf.lib.clang_Cursor_isFunctionInlined(self))
+ @property
+ @cursor_null_guard
+ def is_constexpr(self) -> bool:
+ """
+ Determine if the cursor is a constexpr declaration.
+ """
+ return bool(conf.lib.clang_Cursor_isConstexpr(self))
+
@cursor_null_guard
def has_attrs(self) -> bool:
"""
@@ -4492,6 +4500,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_constexpr.py b/clang/bindings/python/tests/cindex/test_constexpr.py
new file mode 100644
index 0000000000000..cb3db25929f1c
--- /dev/null
+++ b/clang/bindings/python/tests/cindex/test_constexpr.py
@@ -0,0 +1,54 @@
+import unittest
+from .util import get_cursor, get_tu
+
+class TestConstexpr(unittest.TestCase):
+ def test_is_constexpr(self):
+ source = """
+ constexpr int f1() {
+ constexpr int local_v1 = 1;
+ int local_v2 = 2;
+ return local_v1 + local_v2;
+ }
+ int f2() { return 2; }
+
+ constexpr int v1 = 3;
+ int v2 = 4;
+
+ struct S {
+ static constexpr int m1 = 5;
+ int m2;
+ constexpr int m3() const { return 6; }
+ int m4() const { return 7; }
+ };
+ """
+ tu = get_tu(source, lang="cpp")
+
+ f1 = get_cursor(tu, "f1")
+ f2 = get_cursor(tu, "f2")
+ self.assertIsNotNone(f1)
+ self.assertTrue(f1.is_constexpr)
+ self.assertFalse(f2.is_constexpr)
+
+ v1 = get_cursor(tu, "v1")
+ v2 = get_cursor(tu, "v2")
+ self.assertIsNotNone(v1)
+ self.assertTrue(v1.is_constexpr)
+ self.assertFalse(v2.is_constexpr)
+
+ local_v1 = get_cursor(f1, "local_v1")
+ local_v2 = get_cursor(f1, "local_v2")
+ self.assertIsNotNone(local_v1)
+ self.assertTrue(local_v1.is_constexpr)
+ self.assertFalse(local_v2.is_constexpr)
+
+ S = get_cursor(tu, "S")
+ m1 = get_cursor(S, "m1")
+ m2 = get_cursor(S, "m2")
+ m3 = get_cursor(S, "m3")
+ m4 = get_cursor(S, "m4")
+
+ self.assertIsNotNone(m1)
+ self.assertTrue(m1.is_constexpr)
+ self.assertFalse(m2.is_constexpr)
+ self.assertTrue(m3.is_constexpr)
+ self.assertFalse(m4.is_constexpr)
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index dcf1f4f1b4258..b657fdb7979e2 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -3351,6 +3351,12 @@ CINDEX_LINKAGE unsigned clang_Cursor_isMacroBuiltin(CXCursor C);
*/
CINDEX_LINKAGE unsigned clang_Cursor_isFunctionInlined(CXCursor C);
+/**
+ * Determine whether a CXCursor that is a function or variable declaration is
+ * 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
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 3ee37ed2dfc27..ba01a119d26a4 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -4559,6 +4559,15 @@ unsigned clang_Cursor_isFunctionInlined(CXCursor C) {
return FD->isInlined();
}
+unsigned clang_Cursor_isConstexpr(CXCursor C) {
+ const Decl *D = getCursorDecl(C);
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
+ return FD->isConstexpr();
+ if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(D))
+ return VD->isConstexpr();
+ return false;
+}
+
static StringLiteral *getCFSTR_value(CallExpr *callExpr) {
if (callExpr->getNumArgs() != 1) {
return nullptr;
diff --git a/clang/tools/libclang/libclang.map b/clang/tools/libclang/libclang.map
index 3d9d2e268a611..de22123e1f2a8 100644
--- a/clang/tools/libclang/libclang.map
+++ b/clang/tools/libclang/libclang.map
@@ -87,6 +87,7 @@ LLVM_13 {
clang_Cursor_isDynamicCall;
clang_Cursor_isExternalSymbol;
clang_Cursor_isFunctionInlined;
+ clang_Cursor_isConstexpr;
clang_Cursor_isInlineNamespace;
clang_Cursor_isMacroBuiltin;
clang_Cursor_isMacroFunctionLike;
``````````
</details>
https://github.com/llvm/llvm-project/pull/188965
More information about the cfe-commits
mailing list