llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: ykiko (16bit-ykiko) <details> <summary>Changes</summary> Currently, libclang only has the CursorKind: `CXCursor_CallExpr`. Any class inherited from CallExpr is reported as CallExpr. the core code is [here](https://github.com/llvm/llvm-project/blob/main/clang/tools/libclang/CXCursor.cpp#L609) ```cpp case Stmt::CallExprClass: case Stmt::CXXOperatorCallExprClass: case Stmt::CXXMemberCallExprClass: case Stmt::CUDAKernelCallExprClass: case Stmt::CXXConstructExprClass: case Stmt::CXXInheritedCtorInitExprClass: case Stmt::CXXTemporaryObjectExprClass: case Stmt::CXXUnresolvedConstructExprClass: case Stmt::UserDefinedLiteralClass: K = CXCursor_CallExpr; break; ``` As you can see, all of these classes are reported as `CallExpr` and cannot be distinguished from one another. Now, I add `clang_getCursorCallExprKind` to get actual type of `CallExpr`. --- Full diff: https://github.com/llvm/llvm-project/pull/86143.diff 5 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+2) - (modified) clang/include/clang-c/Index.h (+46) - (modified) clang/tools/libclang/CIndex.cpp (+29-1) - (modified) clang/tools/libclang/libclang.map (+5) - (modified) clang/unittests/libclang/LibclangTest.cpp (+24) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 50990140a53ad1..65140e0195b8fc 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -552,6 +552,8 @@ clang-format libclang -------- +- Added ``CXCallExprKind`` and ``clang_getCursorCallExprKind``. + Static Analyzer --------------- diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 60db3cf0966c02..1828b8ec3edaab 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -6663,6 +6663,52 @@ clang_getUnaryOperatorKindSpelling(enum CXUnaryOperatorKind kind); CINDEX_LINKAGE enum CXUnaryOperatorKind clang_getCursorUnaryOperatorKind(CXCursor cursor); +/** + * Describes the kind of CallExpr. + */ +enum CXCallExprKind { + /** Not a CallExpr. */ + CXCallExpr_Invalid = 0, + /** Simple C function call. */ + CXCallExpr_Default, + /** Call to overloaded operator using operator syntax. */ + CXCallExpr_CXXOperatorCallExpr, + /** + * Call to a member function written with member call syntax or + * normal function-call syntax within a member function. + */ + CXCallExpr_CXXMemberCallExpr, + /** Call to a CUDA kernel function. */ + CXCallExpr_CUDAKernelCallExpr, + /** Call to a C++ constructor. */ + CXCallExpr_CXXConstructExpr, + /** + * Call to an inherited base class constructor from an + * inheriting constructor. Implicitly forwards arguments. + */ + CXCallExpr_CXXInheritedCtorInitExpr, + /** + * C++ functional cast expression building a temporary object. + */ + CXCallExpr_CXXTemporaryObjectExpr, + /** + * Explicit type conversion using functional notation, unresolved + * due to type-dependency. + */ + CXCallExpr_CXXUnresolvedConstructExpr, + /** + * Call to a user-defined literal. + */ + CXCallExpr_UserDefinedLiteral, +}; + +/** + * Retrieve the detailed kind of a call expression. + * + * If this cursor is not a CallExpr then returns Invalid. + */ +CINDEX_LINKAGE enum CXCallExprKind clang_getCursorCallExprKind(CXCursor cursor); + /** * @} */ diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 454ee1e42aed1d..20e58b656bdcb7 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2126,7 +2126,7 @@ class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void>, void VisitBlockExpr(const BlockExpr *B); void VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); void VisitCompoundStmt(const CompoundStmt *S); - void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) { /* Do nothing. */ + void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) { /* Do nothing. */ } void VisitMSDependentExistsStmt(const MSDependentExistsStmt *S); void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E); @@ -9731,3 +9731,31 @@ enum CXUnaryOperatorKind clang_getCursorUnaryOperatorKind(CXCursor cursor) { return CXUnaryOperator_Invalid; } + +enum CXCallExprKind clang_getCursorCallExprKind(CXCursor cursor) { + if (clang_isExpression(cursor.kind)) { + const Expr *expr = getCursorExpr(cursor); + + switch (expr->getStmtClass()) { + case Stmt::CallExprClass: + return CXCallExpr_Default; + case Stmt::CXXOperatorCallExprClass: + return CXCallExpr_CXXOperatorCallExpr; + case Stmt::CXXMemberCallExprClass: + return CXCallExpr_CXXMemberCallExpr; + case Stmt::CUDAKernelCallExprClass: + return CXCallExpr_CUDAKernelCallExpr; + case Stmt::CXXConstructExprClass: + return CXCallExpr_CXXConstructExpr; + case Stmt::CXXInheritedCtorInitExprClass: + return CXCallExpr_CXXInheritedCtorInitExpr; + case Stmt::CXXTemporaryObjectExprClass: + return CXCallExpr_CXXTemporaryObjectExpr; + case Stmt::CXXUnresolvedConstructExprClass: + return CXCallExpr_CXXUnresolvedConstructExpr; + case Stmt::UserDefinedLiteralClass: + return CXCallExpr_UserDefinedLiteral; + } + } + return CXCallExpr_Invalid; +} \ No newline at end of file diff --git a/clang/tools/libclang/libclang.map b/clang/tools/libclang/libclang.map index 5676198a286d9b..5499c38a8289f9 100644 --- a/clang/tools/libclang/libclang.map +++ b/clang/tools/libclang/libclang.map @@ -428,6 +428,11 @@ LLVM_17 { clang_getCursorUnaryOperatorKind; }; +LLVM_18 { + global: + clang_getCursorCallExprKind; +} + # 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 { diff --git a/clang/unittests/libclang/LibclangTest.cpp b/clang/unittests/libclang/LibclangTest.cpp index 87075a46d75187..a632cd6e3d2293 100644 --- a/clang/unittests/libclang/LibclangTest.cpp +++ b/clang/unittests/libclang/LibclangTest.cpp @@ -1172,6 +1172,30 @@ TEST_F(LibclangParseTest, UnaryOperator) { }); } +TEST_F(LibclangParseTest, CallExpr){ + std::string Main = "main.cpp"; + const char testSource[] = R"cpp( +struct X{ + int operator+(int) const; +}; + +int x = X() + 1; +)cpp"; + WriteFile(Main, testSource); + ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0, nullptr, + 0, TUFlags); + + Traverse([](CXCursor cursor, CXCursor parent) -> CXChildVisitResult { + if (cursor.kind == CXCursor_CallExpr) { + EXPECT_EQ(clang_getCursorCallExprKind(cursor), + CXCallExpr_CXXOperatorCallExpr); + return CXChildVisit_Break; + } + + return CXChildVisit_Recurse; + }); +} + TEST_F(LibclangParseTest, VisitStaticAssertDecl_noMessage) { const char testSource[] = R"cpp(static_assert(true))cpp"; std::string fileName = "main.cpp"; `````````` </details> https://github.com/llvm/llvm-project/pull/86143 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits