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
