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?= <[email protected]>
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 {

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to