[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