[clang] libclang: Query operator kind on declaration and expression cursors (PR #216553)
Serafean wrote: ping? https://github.com/llvm/llvm-project/pull/216553 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] libclang: Query operator kind on declaration and expression cursors (PR #216553)
https://github.com/Serafean updated
https://github.com/llvm/llvm-project/pull/216553
From 3360ccc8b37ffd068b554bb917aff211bed86d20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Bedn=C3=A1r?=
Date: Sun, 16 Aug 2026 00:00:07 +0200
Subject: [PATCH 1/5] Report operator kind for Declarations and Exprs
---
clang/docs/ReleaseNotes.md | 1 +
clang/tools/libclang/CIndex.cpp | 54 +
2 files changed, 55 insertions(+)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index c348ddaf23017f..b312bde887615c 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -476,6 +476,7 @@ features cannot lower the translation-unit ABI level;
### libclang
- visit identifier initializers in lambda capture as VarDecl instead of
VariableRef. Warning: this changes behaviour.
+- Allow querying Unary and Binary operator types on declaration cursors.
### Code Completion
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 7c9da867909f55..83b9842fb0db2c 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -10224,6 +10224,16 @@ CXString clang_getBinaryOperatorKindSpelling(enum
CXBinaryOperatorKind kind) {
}
enum CXBinaryOperatorKind clang_getCursorBinaryOperatorKind(CXCursor cursor) {
+
+ auto retOp = [](OverloadedOperatorKind Kind, int numArgs) {
+if (!(Kind == OO_None || Kind == OO_PlusPlus || Kind == OO_MinusMinus ||
+ numArgs != 2)) {
+ auto opcode = BinaryOperator::getOverloadedOpcode(Kind);
+ return static_cast(opcode + 1);
+}
+return CXBinaryOperator_Invalid;
+ };
+
if (clang_isExpression(cursor.kind)) {
const Expr *expr = getCursorExpr(cursor);
@@ -10232,6 +10242,22 @@ enum CXBinaryOperatorKind
clang_getCursorBinaryOperatorKind(CXCursor cursor) {
if (const auto *op = dyn_cast(expr))
return static_cast(op->getOpcode() + 1);
+
+if (const auto *OCE = dyn_cast(expr)) {
+ return retOp(OCE->getOperator(), OCE->getNumArgs());
+}
+ }
+
+ if (clang_isDeclaration(cursor.kind)) {
+const auto *decl = getCursorDecl(cursor);
+
+const auto *funcDecl = dyn_cast(decl);
+if (!funcDecl)
+ return CXBinaryOperator_Invalid;
+
+return retOp(funcDecl->getOverloadedOperator(),
+ (funcDecl->isCXXClassMember()) ? funcDecl->getNumParams() + 1
+: funcDecl->getNumParams());
}
return CXBinaryOperator_Invalid;
@@ -10246,11 +10272,39 @@ CXString clang_getUnaryOperatorKindSpelling(enum
CXUnaryOperatorKind kind) {
}
enum CXUnaryOperatorKind clang_getCursorUnaryOperatorKind(CXCursor cursor) {
+
+ auto retOp = [](OverloadedOperatorKind op, int argNum) {
+const bool postfix =
+argNum == 2 && (op == OO_PlusPlus || op == OO_MinusMinus);
+
+if (op == OO_None || (!postfix && argNum != 1))
+ return CXUnaryOperator_Invalid;
+
+const auto uop = UnaryOperator::getOverloadedOpcode(op, postfix);
+return static_cast(uop + 1);
+ };
+
if (clang_isExpression(cursor.kind)) {
const Expr *expr = getCursorExpr(cursor);
if (const auto *op = dyn_cast(expr))
return static_cast(op->getOpcode() + 1);
+
+if (const auto *OCE = dyn_cast(expr)) {
+ return retOp(OCE->getOperator(), OCE->getNumArgs());
+}
+ }
+
+ if (clang_isDeclaration(cursor.kind)) {
+const auto *decl = getCursorDecl(cursor);
+
+const auto *funcDecl = dyn_cast(decl);
+if (!funcDecl)
+ return CXUnaryOperator_Invalid;
+
+return retOp(funcDecl->getOverloadedOperator(),
+ (funcDecl->isCXXClassMember()) ? funcDecl->getNumParams() + 1
+: funcDecl->getNumParams());
}
return CXUnaryOperator_Invalid;
From 6300718233206b5d4798a079d12545d71745fedd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Bedn=C3=A1r?=
Date: Sun, 16 Aug 2026 00:01:02 +0200
Subject: [PATCH 2/5] tests
---
clang/test/Index/binop.cpp | 437 +++-
clang/test/Index/unop.cpp | 175 ++
clang/tools/c-index-test/c-index-test.c | 22 +-
3 files changed, 632 insertions(+), 2 deletions(-)
create mode 100644 clang/test/Index/unop.cpp
diff --git a/clang/test/Index/binop.cpp b/clang/test/Index/binop.cpp
index 576fd73cc2abfe..743a0279a896ff 100644
--- a/clang/test/Index/binop.cpp
+++ b/clang/test/Index/binop.cpp
@@ -1,4 +1,4 @@
-// RUN: c-index-test -test-print-binops %s | FileCheck %s
+// RUN: c-index-test -test-print-binops -std=c++20 %s | FileCheck %s
struct C {
int m;
@@ -90,3 +90,438 @@ void func(void) {
// CHECK: CompoundAssignOperator=^= BinOp=^= 31
// CHECK: CompoundAssignOperator=|= BinOp=|= 32
// CHECK: BinaryOperator=, BinOp=, 33
+
+struct D {
+ D() = default;
+ D& operator+(){return *this;}
+ D& operator-(){return *this;}
+ int& operator->*(int D::*i){return this->i;}
+ D& operator*(const D&){return *this;}
[clang] libclang: Query operator kind on declaration and expression cursors (PR #216553)
https://github.com/Serafean updated
https://github.com/llvm/llvm-project/pull/216553
From 3360ccc8b37ffd068b554bb917aff211bed86d20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Bedn=C3=A1r?=
Date: Sun, 16 Aug 2026 00:00:07 +0200
Subject: [PATCH 1/4] Report operator kind for Declarations and Exprs
---
clang/docs/ReleaseNotes.md | 1 +
clang/tools/libclang/CIndex.cpp | 54 +
2 files changed, 55 insertions(+)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index c348ddaf23017..b312bde887615 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -476,6 +476,7 @@ features cannot lower the translation-unit ABI level;
### libclang
- visit identifier initializers in lambda capture as VarDecl instead of
VariableRef. Warning: this changes behaviour.
+- Allow querying Unary and Binary operator types on declaration cursors.
### Code Completion
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 7c9da867909f5..83b9842fb0db2 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -10224,6 +10224,16 @@ CXString clang_getBinaryOperatorKindSpelling(enum
CXBinaryOperatorKind kind) {
}
enum CXBinaryOperatorKind clang_getCursorBinaryOperatorKind(CXCursor cursor) {
+
+ auto retOp = [](OverloadedOperatorKind Kind, int numArgs) {
+if (!(Kind == OO_None || Kind == OO_PlusPlus || Kind == OO_MinusMinus ||
+ numArgs != 2)) {
+ auto opcode = BinaryOperator::getOverloadedOpcode(Kind);
+ return static_cast(opcode + 1);
+}
+return CXBinaryOperator_Invalid;
+ };
+
if (clang_isExpression(cursor.kind)) {
const Expr *expr = getCursorExpr(cursor);
@@ -10232,6 +10242,22 @@ enum CXBinaryOperatorKind
clang_getCursorBinaryOperatorKind(CXCursor cursor) {
if (const auto *op = dyn_cast(expr))
return static_cast(op->getOpcode() + 1);
+
+if (const auto *OCE = dyn_cast(expr)) {
+ return retOp(OCE->getOperator(), OCE->getNumArgs());
+}
+ }
+
+ if (clang_isDeclaration(cursor.kind)) {
+const auto *decl = getCursorDecl(cursor);
+
+const auto *funcDecl = dyn_cast(decl);
+if (!funcDecl)
+ return CXBinaryOperator_Invalid;
+
+return retOp(funcDecl->getOverloadedOperator(),
+ (funcDecl->isCXXClassMember()) ? funcDecl->getNumParams() + 1
+: funcDecl->getNumParams());
}
return CXBinaryOperator_Invalid;
@@ -10246,11 +10272,39 @@ CXString clang_getUnaryOperatorKindSpelling(enum
CXUnaryOperatorKind kind) {
}
enum CXUnaryOperatorKind clang_getCursorUnaryOperatorKind(CXCursor cursor) {
+
+ auto retOp = [](OverloadedOperatorKind op, int argNum) {
+const bool postfix =
+argNum == 2 && (op == OO_PlusPlus || op == OO_MinusMinus);
+
+if (op == OO_None || (!postfix && argNum != 1))
+ return CXUnaryOperator_Invalid;
+
+const auto uop = UnaryOperator::getOverloadedOpcode(op, postfix);
+return static_cast(uop + 1);
+ };
+
if (clang_isExpression(cursor.kind)) {
const Expr *expr = getCursorExpr(cursor);
if (const auto *op = dyn_cast(expr))
return static_cast(op->getOpcode() + 1);
+
+if (const auto *OCE = dyn_cast(expr)) {
+ return retOp(OCE->getOperator(), OCE->getNumArgs());
+}
+ }
+
+ if (clang_isDeclaration(cursor.kind)) {
+const auto *decl = getCursorDecl(cursor);
+
+const auto *funcDecl = dyn_cast(decl);
+if (!funcDecl)
+ return CXUnaryOperator_Invalid;
+
+return retOp(funcDecl->getOverloadedOperator(),
+ (funcDecl->isCXXClassMember()) ? funcDecl->getNumParams() + 1
+: funcDecl->getNumParams());
}
return CXUnaryOperator_Invalid;
From 6300718233206b5d4798a079d12545d71745fedd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Bedn=C3=A1r?=
Date: Sun, 16 Aug 2026 00:01:02 +0200
Subject: [PATCH 2/4] tests
---
clang/test/Index/binop.cpp | 437 +++-
clang/test/Index/unop.cpp | 175 ++
clang/tools/c-index-test/c-index-test.c | 22 +-
3 files changed, 632 insertions(+), 2 deletions(-)
create mode 100644 clang/test/Index/unop.cpp
diff --git a/clang/test/Index/binop.cpp b/clang/test/Index/binop.cpp
index 576fd73cc2abf..743a0279a896f 100644
--- a/clang/test/Index/binop.cpp
+++ b/clang/test/Index/binop.cpp
@@ -1,4 +1,4 @@
-// RUN: c-index-test -test-print-binops %s | FileCheck %s
+// RUN: c-index-test -test-print-binops -std=c++20 %s | FileCheck %s
struct C {
int m;
@@ -90,3 +90,438 @@ void func(void) {
// CHECK: CompoundAssignOperator=^= BinOp=^= 31
// CHECK: CompoundAssignOperator=|= BinOp=|= 32
// CHECK: BinaryOperator=, BinOp=, 33
+
+struct D {
+ D() = default;
+ D& operator+(){return *this;}
+ D& operator-(){return *this;}
+ int& operator->*(int D::*i){return this->i;}
+ D& operator*(const D&){return *this;}
+ D&
[clang] libclang: Query operator kind on declaration and expression cursors (PR #216553)
https://github.com/Serafean updated
https://github.com/llvm/llvm-project/pull/216553
From 3360ccc8b37ffd068b554bb917aff211bed86d20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Bedn=C3=A1r?=
Date: Sun, 16 Aug 2026 00:00:07 +0200
Subject: [PATCH 1/4] Report operator kind for Declarations and Exprs
---
clang/docs/ReleaseNotes.md | 1 +
clang/tools/libclang/CIndex.cpp | 54 +
2 files changed, 55 insertions(+)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index c348ddaf23017..b312bde887615 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -476,6 +476,7 @@ features cannot lower the translation-unit ABI level;
### libclang
- visit identifier initializers in lambda capture as VarDecl instead of
VariableRef. Warning: this changes behaviour.
+- Allow querying Unary and Binary operator types on declaration cursors.
### Code Completion
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 7c9da867909f5..83b9842fb0db2 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -10224,6 +10224,16 @@ CXString clang_getBinaryOperatorKindSpelling(enum
CXBinaryOperatorKind kind) {
}
enum CXBinaryOperatorKind clang_getCursorBinaryOperatorKind(CXCursor cursor) {
+
+ auto retOp = [](OverloadedOperatorKind Kind, int numArgs) {
+if (!(Kind == OO_None || Kind == OO_PlusPlus || Kind == OO_MinusMinus ||
+ numArgs != 2)) {
+ auto opcode = BinaryOperator::getOverloadedOpcode(Kind);
+ return static_cast(opcode + 1);
+}
+return CXBinaryOperator_Invalid;
+ };
+
if (clang_isExpression(cursor.kind)) {
const Expr *expr = getCursorExpr(cursor);
@@ -10232,6 +10242,22 @@ enum CXBinaryOperatorKind
clang_getCursorBinaryOperatorKind(CXCursor cursor) {
if (const auto *op = dyn_cast(expr))
return static_cast(op->getOpcode() + 1);
+
+if (const auto *OCE = dyn_cast(expr)) {
+ return retOp(OCE->getOperator(), OCE->getNumArgs());
+}
+ }
+
+ if (clang_isDeclaration(cursor.kind)) {
+const auto *decl = getCursorDecl(cursor);
+
+const auto *funcDecl = dyn_cast(decl);
+if (!funcDecl)
+ return CXBinaryOperator_Invalid;
+
+return retOp(funcDecl->getOverloadedOperator(),
+ (funcDecl->isCXXClassMember()) ? funcDecl->getNumParams() + 1
+: funcDecl->getNumParams());
}
return CXBinaryOperator_Invalid;
@@ -10246,11 +10272,39 @@ CXString clang_getUnaryOperatorKindSpelling(enum
CXUnaryOperatorKind kind) {
}
enum CXUnaryOperatorKind clang_getCursorUnaryOperatorKind(CXCursor cursor) {
+
+ auto retOp = [](OverloadedOperatorKind op, int argNum) {
+const bool postfix =
+argNum == 2 && (op == OO_PlusPlus || op == OO_MinusMinus);
+
+if (op == OO_None || (!postfix && argNum != 1))
+ return CXUnaryOperator_Invalid;
+
+const auto uop = UnaryOperator::getOverloadedOpcode(op, postfix);
+return static_cast(uop + 1);
+ };
+
if (clang_isExpression(cursor.kind)) {
const Expr *expr = getCursorExpr(cursor);
if (const auto *op = dyn_cast(expr))
return static_cast(op->getOpcode() + 1);
+
+if (const auto *OCE = dyn_cast(expr)) {
+ return retOp(OCE->getOperator(), OCE->getNumArgs());
+}
+ }
+
+ if (clang_isDeclaration(cursor.kind)) {
+const auto *decl = getCursorDecl(cursor);
+
+const auto *funcDecl = dyn_cast(decl);
+if (!funcDecl)
+ return CXUnaryOperator_Invalid;
+
+return retOp(funcDecl->getOverloadedOperator(),
+ (funcDecl->isCXXClassMember()) ? funcDecl->getNumParams() + 1
+: funcDecl->getNumParams());
}
return CXUnaryOperator_Invalid;
From 6300718233206b5d4798a079d12545d71745fedd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Bedn=C3=A1r?=
Date: Sun, 16 Aug 2026 00:01:02 +0200
Subject: [PATCH 2/4] tests
---
clang/test/Index/binop.cpp | 437 +++-
clang/test/Index/unop.cpp | 175 ++
clang/tools/c-index-test/c-index-test.c | 22 +-
3 files changed, 632 insertions(+), 2 deletions(-)
create mode 100644 clang/test/Index/unop.cpp
diff --git a/clang/test/Index/binop.cpp b/clang/test/Index/binop.cpp
index 576fd73cc2abf..743a0279a896f 100644
--- a/clang/test/Index/binop.cpp
+++ b/clang/test/Index/binop.cpp
@@ -1,4 +1,4 @@
-// RUN: c-index-test -test-print-binops %s | FileCheck %s
+// RUN: c-index-test -test-print-binops -std=c++20 %s | FileCheck %s
struct C {
int m;
@@ -90,3 +90,438 @@ void func(void) {
// CHECK: CompoundAssignOperator=^= BinOp=^= 31
// CHECK: CompoundAssignOperator=|= BinOp=|= 32
// CHECK: BinaryOperator=, BinOp=, 33
+
+struct D {
+ D() = default;
+ D& operator+(){return *this;}
+ D& operator-(){return *this;}
+ int& operator->*(int D::*i){return this->i;}
+ D& operator*(const D&){return *this;}
+ D&
[clang] libclang: Query operator kind on declaration and expression cursors (PR #216553)
Serafean wrote:
Handling `CXXOperatorCallExpr` is desirable indeed.
Adding `clang_Function_getBinaryOperatorKind` makes sense for discovery and API
symmetry. Could `clang_getCursorBinaryOperatorKind` also handle the
declaration case, and `clang_Function_getBinaryOperatorKind` only delegate to
that? Would that be OK? My argument for this is to keep the unary/binary op
distinction logic in one place. Essentially:
`
clang_Function_getBinaryOperatorKind(CXCursor decl) {
return clang_getCursorBinaryOperatorKind(decl);
}
`
https://github.com/llvm/llvm-project/pull/216553
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] libclang: Query operator kind on declaration and expression cursors (PR #216553)
Martin =?utf-8?q?Bednár?= Message-ID: In-Reply-To: AaronBallman wrote: > Thanks for taking a look. > > > we'd want something more along the lines of > > clang_CXXMethod_isBinaryOperator() > > non-member operators need to be supported too. `clang_Function_isOperator()` ? Ah good call, though we probably don't want it to be `is` because this would return the kind rather than a bool, so probably more along the lines of `clang_Function_getBinaryOperatorKind()`. > > That said, I'd like to understand the need a bit more before adding a new > > interface. > > I have two needs : > > * know whether a CallExpr calls an operator (unary/binary doesn't > matter). This could be done by querying the referenced cursor > (`CXXMethod`/`FunctionDecl`) and asking whether it's an operator, or from the > Expr itself. I'd prefer knowing whether the referenced declaration cursor is > an operator. I think both are important because you can also call operators directly but they have a different AST form: https://godbolt.org/z/qKo3GqKEo -- the use of `+` as an operator forms a `CXXOperatorCallExpr` while the call to `operator+` forms a `CXXMemberCallExpr`. So I think it makes sense for `clang_getCursorBinaryOperatorKind()` to handle a `CXXOperatorCallExpr` because you can use this to catch times the user is actually using an operator, but without having to know about the oddity of calling the operator directly. But if you have a function declaration, it's still useful to know "is this for an operator and if so, which one?". > * Know when the called operator is `co_await`. Makes sense. > I actually don't like too much querying the `CallExpr` directly, but added it > for ease of use/consistency. I very much prefer querying the Declaration. Thanks for the explanation! I'm okay with adding new declaration-based interfaces and I'm also okay with extending the expression-based interface to handle a `CXXOperatorCallExpr`; your call on whether you want to do both, or only add the declaration interfaces. https://github.com/llvm/llvm-project/pull/216553 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] libclang: Query operator kind on declaration and expression cursors (PR #216553)
Serafean wrote: Looking at it, I'm not sure adding support for querying `CallExpr` is necessary/worthwhile, as `clang_getCursorReferenced` on callExpr would be enough to get the declaration and then query the operator kind there... Thoughts? https://github.com/llvm/llvm-project/pull/216553 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] libclang: Query operator kind on declaration and expression cursors (PR #216553)
https://github.com/Serafean updated
https://github.com/llvm/llvm-project/pull/216553
From 3360ccc8b37ffd068b554bb917aff211bed86d20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Bedn=C3=A1r?=
Date: Sun, 16 Aug 2026 00:00:07 +0200
Subject: [PATCH 1/2] Report operator kind for Declarations and Exprs
---
clang/docs/ReleaseNotes.md | 1 +
clang/tools/libclang/CIndex.cpp | 54 +
2 files changed, 55 insertions(+)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index c348ddaf23017..b312bde887615 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -476,6 +476,7 @@ features cannot lower the translation-unit ABI level;
### libclang
- visit identifier initializers in lambda capture as VarDecl instead of
VariableRef. Warning: this changes behaviour.
+- Allow querying Unary and Binary operator types on declaration cursors.
### Code Completion
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 7c9da867909f5..83b9842fb0db2 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -10224,6 +10224,16 @@ CXString clang_getBinaryOperatorKindSpelling(enum
CXBinaryOperatorKind kind) {
}
enum CXBinaryOperatorKind clang_getCursorBinaryOperatorKind(CXCursor cursor) {
+
+ auto retOp = [](OverloadedOperatorKind Kind, int numArgs) {
+if (!(Kind == OO_None || Kind == OO_PlusPlus || Kind == OO_MinusMinus ||
+ numArgs != 2)) {
+ auto opcode = BinaryOperator::getOverloadedOpcode(Kind);
+ return static_cast(opcode + 1);
+}
+return CXBinaryOperator_Invalid;
+ };
+
if (clang_isExpression(cursor.kind)) {
const Expr *expr = getCursorExpr(cursor);
@@ -10232,6 +10242,22 @@ enum CXBinaryOperatorKind
clang_getCursorBinaryOperatorKind(CXCursor cursor) {
if (const auto *op = dyn_cast(expr))
return static_cast(op->getOpcode() + 1);
+
+if (const auto *OCE = dyn_cast(expr)) {
+ return retOp(OCE->getOperator(), OCE->getNumArgs());
+}
+ }
+
+ if (clang_isDeclaration(cursor.kind)) {
+const auto *decl = getCursorDecl(cursor);
+
+const auto *funcDecl = dyn_cast(decl);
+if (!funcDecl)
+ return CXBinaryOperator_Invalid;
+
+return retOp(funcDecl->getOverloadedOperator(),
+ (funcDecl->isCXXClassMember()) ? funcDecl->getNumParams() + 1
+: funcDecl->getNumParams());
}
return CXBinaryOperator_Invalid;
@@ -10246,11 +10272,39 @@ CXString clang_getUnaryOperatorKindSpelling(enum
CXUnaryOperatorKind kind) {
}
enum CXUnaryOperatorKind clang_getCursorUnaryOperatorKind(CXCursor cursor) {
+
+ auto retOp = [](OverloadedOperatorKind op, int argNum) {
+const bool postfix =
+argNum == 2 && (op == OO_PlusPlus || op == OO_MinusMinus);
+
+if (op == OO_None || (!postfix && argNum != 1))
+ return CXUnaryOperator_Invalid;
+
+const auto uop = UnaryOperator::getOverloadedOpcode(op, postfix);
+return static_cast(uop + 1);
+ };
+
if (clang_isExpression(cursor.kind)) {
const Expr *expr = getCursorExpr(cursor);
if (const auto *op = dyn_cast(expr))
return static_cast(op->getOpcode() + 1);
+
+if (const auto *OCE = dyn_cast(expr)) {
+ return retOp(OCE->getOperator(), OCE->getNumArgs());
+}
+ }
+
+ if (clang_isDeclaration(cursor.kind)) {
+const auto *decl = getCursorDecl(cursor);
+
+const auto *funcDecl = dyn_cast(decl);
+if (!funcDecl)
+ return CXUnaryOperator_Invalid;
+
+return retOp(funcDecl->getOverloadedOperator(),
+ (funcDecl->isCXXClassMember()) ? funcDecl->getNumParams() + 1
+: funcDecl->getNumParams());
}
return CXUnaryOperator_Invalid;
From 6300718233206b5d4798a079d12545d71745fedd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Bedn=C3=A1r?=
Date: Sun, 16 Aug 2026 00:01:02 +0200
Subject: [PATCH 2/2] tests
---
clang/test/Index/binop.cpp | 437 +++-
clang/test/Index/unop.cpp | 175 ++
clang/tools/c-index-test/c-index-test.c | 22 +-
3 files changed, 632 insertions(+), 2 deletions(-)
create mode 100644 clang/test/Index/unop.cpp
diff --git a/clang/test/Index/binop.cpp b/clang/test/Index/binop.cpp
index 576fd73cc2abf..743a0279a896f 100644
--- a/clang/test/Index/binop.cpp
+++ b/clang/test/Index/binop.cpp
@@ -1,4 +1,4 @@
-// RUN: c-index-test -test-print-binops %s | FileCheck %s
+// RUN: c-index-test -test-print-binops -std=c++20 %s | FileCheck %s
struct C {
int m;
@@ -90,3 +90,438 @@ void func(void) {
// CHECK: CompoundAssignOperator=^= BinOp=^= 31
// CHECK: CompoundAssignOperator=|= BinOp=|= 32
// CHECK: BinaryOperator=, BinOp=, 33
+
+struct D {
+ D() = default;
+ D& operator+(){return *this;}
+ D& operator-(){return *this;}
+ int& operator->*(int D::*i){return this->i;}
+ D& operator*(const D&){return *this;}
+ D&
[clang] libclang: Query operator kind on declaration and expression cursors (PR #216553)
Martin =?utf-8?q?Bednár?=
Message-ID:
In-Reply-To:
github-actions[bot] wrote:
# :penguin: Linux x64 Test Results
* 90873 tests passed
* 1798 tests skipped
* 1 test failed
## Failed Tests
(click on a test name to see its output)
### Clang
Clang.Index/binop.cpp
```
Exit Code: 1
Command Output (stdout):
--
# RUN: at line 1
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/c-index-test
-test-print-binops
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp
| /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp
# executed command:
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/c-index-test
-test-print-binops
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp
# .---command stderr
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:464:15:
warning: '<=>' is a single token in C++20; add a space to avoid a change in
behavior [-Wc++20-compat]
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:464:7:
error: 'operator<=' cannot be the name of a variable or data member
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:464:17:
error: expected ';' at end of declaration list
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:472:6:
warning: '<=>' is a single token in C++20; add a space to avoid a change in
behavior [-Wc++20-compat]
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:472:8:
error: expected expression
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:473:6:
error: invalid operands to binary expression ('space1' and 'space1')
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:293:6:
note: candidate function not viable: no known conversion from 'space1' to
'const E' for 1st argument
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:474:6:
error: invalid operands to binary expression ('space1' and 'space1')
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:294:6:
note: candidate function not viable: no known conversion from 'space1' to
'const E' for 1st argument
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:475:6:
error: invalid operands to binary expression ('space1' and 'space1')
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:295:6:
note: candidate function not viable: no known conversion from 'space1' to
'const E' for 1st argument
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:476:6:
error: invalid operands to binary expression ('space1' and 'space1')
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:296:6:
note: candidate function not viable: no known conversion from 'space1' to
'const E' for 1st argument
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:478:6:
error: invalid operands to binary expression ('space1' and 'space1')
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:298:6:
note: candidate function not viable: no known conversion from 'space1' to
'const E' for 1st argument
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:498:13:
warning: '<=>' is a single token in C++20; add a space to avoid a change in
behavior [-Wc++20-compat]
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:498:5:
error: 'operator<=' cannot be the name of a variable or data member
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:498:15:
error: expected ';' after top level declarator
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:504:6:
warning: '<=>' is a single token in C++20; add a space to avoid a change in
behavior [-Wc++20-compat]
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:504:8:
error: expected expression
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:505:6:
error: invalid operands to binary expression ('space2' and 'space2')
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:293:6:
note: candidate function not viable: no known conversion from 'space2' to
'const E' for 1st argument
# |
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/Index/binop.cpp:506:6:
error: invalid operands to binary expression ('space2' and 'space2')
# |
[clang] libclang: Query operator kind on declaration and expression cursors (PR #216553)
Serafean wrote: Updated to also include https://github.com/llvm/llvm-project/pull/182303 , with added test for operator <=>. https://github.com/llvm/llvm-project/pull/216553 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] libclang: Query operator kind on declaration and expression cursors (PR #216553)
https://github.com/Serafean edited https://github.com/llvm/llvm-project/pull/216553 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] libclang: Query operator kind on declaration and expression cursors (PR #216553)
https://github.com/Serafean edited https://github.com/llvm/llvm-project/pull/216553 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] libclang: Query operator kind on declaration and expression cursors (PR #216553)
https://github.com/Serafean edited https://github.com/llvm/llvm-project/pull/216553 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
