[clang] Add `clang_getCursorCallExprKind` to get the underlying type of CallExpr (PR #86143)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 21 09:06:39 PDT 2024
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
More information about the cfe-commits
mailing list