[clang] [libclang]Introduce clang_CXXIsCoroutine() (PR #182685)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Feb 21 08:02:54 PST 2026
https://github.com/Serafean created https://github.com/llvm/llvm-project/pull/182685
Knowing whether a function is a coroutine or not is useful, this adds the clang_CXXIsCoroutine() function to get that information using the C API.
>From f4d7d275aef16069591bdbbcb6f27ee37d5b9f52 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Bedn=C3=A1r?= <martin at serafean.cz>
Date: Fri, 20 Feb 2026 12:04:37 +0100
Subject: [PATCH] [libclang]Introduce clang_CXXIsCoroutine()
---
clang/docs/ReleaseNotes.rst | 1 +
clang/include/clang-c/Index.h | 8 +++++-
clang/test/Index/coroutines.cpp | 36 ++++++++++++++++++++++---
clang/tools/c-index-test/c-index-test.c | 2 ++
clang/tools/libclang/CIndex.cpp | 23 ++++++++++++++++
clang/tools/libclang/libclang.map | 5 ++++
6 files changed, 70 insertions(+), 5 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b1d7c77e65958..b950c38089fbb 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -409,6 +409,7 @@ clang-format
libclang
--------
- Fix crash in clang_getBinaryOperatorKindSpelling and clang_getUnaryOperatorKindSpelling
+- Add clang_CXXIsCoroutine()
Code Completion
---------------
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 203634c80d82a..907a01ff75e3d 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -34,7 +34,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 64
+#define CINDEX_VERSION_MINOR 65
#define CINDEX_VERSION_ENCODE(major, minor) (((major) * 10000) + ((minor) * 1))
@@ -4883,6 +4883,12 @@ CINDEX_LINKAGE unsigned clang_EnumDecl_isScoped(CXCursor C);
*/
CINDEX_LINKAGE unsigned clang_CXXMethod_isConst(CXCursor C);
+/**
+ * Determine if a function, member function, or lambda is a coroutine.
+ *
+ */
+CINDEX_LINKAGE int clang_CXXIsCoroutine(CXCursor cursor);
+
/**
* 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/coroutines.cpp b/clang/test/Index/coroutines.cpp
index eafca475419b7..d5358b5ae9ab6 100644
--- a/clang/test/Index/coroutines.cpp
+++ b/clang/test/Index/coroutines.cpp
@@ -18,7 +18,35 @@ struct std::coroutine_traits<void> { using promise_type = promise_void; };
void CoroutineTestRet() {
co_return;
}
-// CHECK: [[@LINE-3]]:25: UnexposedStmt=
-// CHECK-SAME: [[@LINE-4]]:25 - [[@LINE-2]]:2]
-// CHECK: [[@LINE-4]]:3: UnexposedStmt=
-// CHECK-SAME: [[@LINE-5]]:3 - [[@LINE-5]]:12]
+// CHECK: [[@LINE-3]]:6: FunctionDecl=CoroutineTestRet:18:6 (Definition) (coroutine) Extent=[18:1 - 20:2]
+// CHECK: [[@LINE-4]]:25: UnexposedStmt=
+// CHECK-SAME: [[@LINE-5]]:25 - [[@LINE-3]]:2]
+// CHECK: [[@LINE-5]]:3: UnexposedStmt=
+// CHECK-SAME: [[@LINE-6]]:3 - [[@LINE-6]]:12]
+
+class Coro {
+public:
+ struct promise_type {
+ Coro get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend() noexcept;
+ void return_void();
+ void unhandled_exception();
+ };
+ Coro(std::coroutine_handle<promise_void>);
+};
+
+class W{
+public:
+ Coro CoroutineMemberTest() {
+ co_return;
+ }
+};
+
+// CHECK: CXXMethod=CoroutineMemberTest:41:8 (Definition) (coroutine) Extent=[41:3 - 43:4] [access=public]
+
+auto lambda = []() -> Coro {
+ co_return;
+};
+
+// CHECK: LambdaExpr= (coroutine) Extent=[48:15 - 50:2]
diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c
index cb3245756a394..d60a4f3dc4a8b 100644
--- a/clang/tools/c-index-test/c-index-test.c
+++ b/clang/tools/c-index-test/c-index-test.c
@@ -964,6 +964,8 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
printf(" (explicit)");
if (clang_CXXRecord_isAbstract(Cursor))
printf(" (abstract)");
+ if (clang_CXXIsCoroutine(Cursor))
+ printf(" (coroutine)");
if (clang_EnumDecl_isScoped(Cursor))
printf(" (scoped)");
if (clang_Cursor_isVariadic(Cursor))
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 06b86b51ee36d..2ca2730efd771 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -10220,3 +10220,26 @@ enum CXUnaryOperatorKind clang_getCursorUnaryOperatorKind(CXCursor cursor) {
return CXUnaryOperator_Invalid;
}
+
+int clang_CXXIsCoroutine(CXCursor cursor) {
+ if (cursor.kind == CXCursor_FunctionDecl ||
+ cursor.kind == CXCursor_CXXMethod) {
+ if (const Decl *D = getCursorDecl(cursor)) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const Stmt *Body = FD->getBody())
+ return isa<CoroutineBodyStmt>(Body);
+ }
+ }
+ }
+
+ if (cursor.kind == CXCursor_LambdaExpr) {
+ if (const Expr *E = getCursorExpr(cursor)) {
+ if (const LambdaExpr *L = dyn_cast<LambdaExpr>(E)) {
+ if (const Stmt *Body = L->getBody())
+ return isa<CoroutineBodyStmt>(Body);
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/clang/tools/libclang/libclang.map b/clang/tools/libclang/libclang.map
index 3d9d2e268a611..7f9aaee3dd339 100644
--- a/clang/tools/libclang/libclang.map
+++ b/clang/tools/libclang/libclang.map
@@ -457,6 +457,11 @@ LLVM_21 {
clang_Cursor_isGCCAssemblyVolatile;
};
+LLVM_23 {
+ global:
+ clang_CXXIsCoroutine;
+};
+
# 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 {
More information about the cfe-commits
mailing list