[clang] Add retrieval of unary operator spelling and python bindings (PR #219983)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 15 03:09:41 PDT 2026
https://github.com/ItsRumo updated https://github.com/llvm/llvm-project/pull/219983
>From 2f1765a4ec1890c933924548b83d5f13861d663b Mon Sep 17 00:00:00 2001
From: Erik Julian Radermacher <erik.radermacher at uni-osnabrueck.de>
Date: Mon, 31 Aug 2026 14:39:48 +0200
Subject: [PATCH 1/3] Add retrieval of unary operator spelling and python
bindings
---
clang/bindings/python/clang/cindex.py | 44 +++++++++++++++++++
.../python/tests/cindex/test_cursor.py | 42 ++++++++++++++++++
.../python/tests/cindex/test_enums.py | 2 +
clang/docs/ReleaseNotes.md | 4 ++
clang/test/Index/annotate-tokens-pp.c | 2 +-
clang/test/Index/annotate-tokens.c | 4 +-
clang/test/Index/blocks.c | 2 +-
clang/test/Index/load-stmts.cpp | 6 +--
clang/test/Index/print-type.c | 2 +-
.../test/Index/recursive-cxx-member-calls.cpp | 8 ++--
clang/test/Index/unaryop.cpp | 38 ++++++++++++++++
clang/tools/libclang/CIndex.cpp | 5 +++
12 files changed, 147 insertions(+), 12 deletions(-)
create mode 100644 clang/test/Index/unaryop.cpp
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index bc00dd770ce3b5..9e01b0d88951dd 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -2036,6 +2036,19 @@ def binary_operator(self) -> BinaryOperator:
return BinaryOperator.from_id(self._binopcode)
+ @property
+ @cursor_null_guard
+ def unary_operator(self) -> UnaryOperator:
+ """
+ Retrieves the opcode if this cursor points to a unary operator
+ :return:
+ """
+
+ if not hasattr(self, "_binopcode"):
+ self._binopcode = conf.lib.clang_getCursorUnaryOperatorKind(self)
+
+ return UnaryOperator.from_id(self._binopcode)
+
@property
@cursor_null_guard
def access_specifier(self) -> AccessSpecifier:
@@ -2474,6 +2487,35 @@ def is_assignment(self):
Comma = 33
+class UnaryOperator(BaseEnumeration):
+ """
+ Describes the UnaryOperator of a declaration
+ """
+
+ def __nonzero__(self):
+ """Allows checks of the kind ```if cursor.unary_operator:```"""
+ return self.value != 0
+
+ def is_postfix(self):
+ return self == UnaryOperator.PostDec or self == UnaryOperator.PostInc
+
+ Invalid = 0
+ PostInc = 1
+ PostDec = 2
+ PreInc = 3
+ PreDec = 4
+ AddrOf = 5
+ Deref = 6
+ Plus = 7
+ Minus = 8
+ Not = 9
+ LNot = 10
+ Real = 11
+ Imag = 12
+ Extension = 13
+ CoAwait = 14
+
+
class StorageClass(BaseEnumeration):
"""
Describes the storage class of a declaration
@@ -4345,6 +4387,7 @@ def set_property(self, property, value):
("clang_Cursor_getTemplateArgumentValue", [Cursor, c_uint], c_longlong),
("clang_Cursor_getTemplateArgumentUnsignedValue", [Cursor, c_uint], c_ulonglong),
("clang_getCursorBinaryOperatorKind", [Cursor], c_int),
+ ("clang_getCursorUnaryOperatorKind", [Cursor], c_int),
("clang_Cursor_getBriefCommentText", [Cursor], _CXString),
("clang_Cursor_getRawCommentText", [Cursor], _CXString),
("clang_Cursor_getOffsetOfField", [Cursor], c_longlong),
@@ -4550,4 +4593,5 @@ def get_clang_version(self) -> str:
"TranslationUnit",
"TypeKind",
"Type",
+ "UnaryOperator",
]
diff --git a/clang/bindings/python/tests/cindex/test_cursor.py b/clang/bindings/python/tests/cindex/test_cursor.py
index 76680e576b3076..e8a77371f88e27 100644
--- a/clang/bindings/python/tests/cindex/test_cursor.py
+++ b/clang/bindings/python/tests/cindex/test_cursor.py
@@ -9,6 +9,7 @@
TemplateArgumentKind,
TranslationUnit,
TypeKind,
+ UnaryOperator,
conf,
)
@@ -986,6 +987,47 @@ def test_binop(self):
c = get_cursor(tu, op)
assert c.binary_operator == typ
+ def test_unaryop(self):
+ tu = get_tu("""
+ void func(void) {
+ int a = 0;
+ a++;
+ ++a;
+ a--;
+ --a;
+ *(&a);
+ +a;
+ -a;
+ !a;
+ ~a;
+ float _Complex b;
+ __real b;
+ __imag b;
+ __extension__ a;
+ }
+ """, lang="cpp")
+
+ operators = {
+ "&": UnaryOperator.AddrOf,
+ "*": UnaryOperator.Deref,
+ "+": UnaryOperator.Plus,
+ "-": UnaryOperator.Minus,
+ "~": UnaryOperator.Not,
+ "!": UnaryOperator.LNot,
+ "__real": UnaryOperator.Real,
+ "__imag": UnaryOperator.Imag,
+ "__extension__": UnaryOperator.Extension,
+ }
+
+ for op, typ in operators.items():
+ c = get_cursor(tu, op)
+ assert c.unary_operator == typ
+
+ for should_be, has in zip(
+ (UnaryOperator.PostInc, UnaryOperator.PreInc, UnaryOperator.PostDec, UnaryOperator.PreDec),
+ list(next(tu.cursor.get_children()).get_children())[1:]):
+ assert should_be == has
+
def test_from_result_null(self):
tu = get_tu("int a = 1+2;", lang="cpp")
op = next(next(tu.cursor.get_children()).get_children())
diff --git a/clang/bindings/python/tests/cindex/test_enums.py b/clang/bindings/python/tests/cindex/test_enums.py
index 09f346ee6e11f9..f926e75309b35f 100644
--- a/clang/bindings/python/tests/cindex/test_enums.py
+++ b/clang/bindings/python/tests/cindex/test_enums.py
@@ -20,6 +20,7 @@
TypeKind,
PrintingPolicyProperty,
BaseEnumeration,
+ UnaryOperator,
)
@@ -56,6 +57,7 @@ def test_all_variants(self):
"CXTLSKind": TLSKind,
"CXTokenKind": TokenKind,
"CXTypeKind": TypeKind,
+ "CXUnaryOperatorKind": UnaryOperator,
}
indexheader = (
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index dd3dfdc5ad8d7b..d23eacffd9f9f9 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -705,6 +705,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.
+- add unary operator handling to clang_getCursorSpelling()
### Code Completion
@@ -740,6 +741,9 @@ The `alpha.cplusplus.UseAfterLifetimeEnd` checker was renamed to `alpha.core.Use
### Python Binding Changes
+- Add support for retrieving unary operator information through
+ Cursor.unary_operator().
+
### OpenMP Support
- Added parsing and semantic support for `dims` modifier in `num_teams`,
diff --git a/clang/test/Index/annotate-tokens-pp.c b/clang/test/Index/annotate-tokens-pp.c
index 7da2d6f5823aaa..16248bb403b35e 100644
--- a/clang/test/Index/annotate-tokens-pp.c
+++ b/clang/test/Index/annotate-tokens-pp.c
@@ -197,7 +197,7 @@ struct A
// CHECK: Punctuation: "=" [25:36 - 25:37] VarDecl=z:25:34 (Definition)
// CHECK: Identifier: "x" [25:38 - 25:39] DeclRefExpr=x:24:7
// CHECK: Punctuation: ";" [25:39 - 25:40] DeclStmt=
-// CHECK: Punctuation: "++" [25:41 - 25:43] UnaryOperator=
+// CHECK: Punctuation: "++" [25:41 - 25:43] UnaryOperator=++
// CHECK: Identifier: "z" [25:43 - 25:44] DeclRefExpr=z:25:3
// CHECK: Punctuation: ";" [25:44 - 25:45] CompoundStmt=
// CHECK: Punctuation: "}" [25:46 - 25:47] CompoundStmt=
diff --git a/clang/test/Index/annotate-tokens.c b/clang/test/Index/annotate-tokens.c
index 08e7a9a02f8f24..34f50da8775756 100644
--- a/clang/test/Index/annotate-tokens.c
+++ b/clang/test/Index/annotate-tokens.c
@@ -106,7 +106,7 @@ void test() {
// CHECK: Identifier: "ptr" [8:14 - 8:17] DeclRefExpr=ptr:3:14
// CHECK: Punctuation: "?" [8:18 - 8:19] UnexposedExpr=
// CHECK: Punctuation: ":" [8:20 - 8:21] UnexposedExpr=
-// CHECK: Punctuation: "&" [8:22 - 8:23] UnaryOperator=
+// CHECK: Punctuation: "&" [8:22 - 8:23] UnaryOperator=&
// CHECK: Identifier: "x" [8:23 - 8:24] DeclRefExpr=x:7:12
// CHECK: Punctuation: ";" [8:24 - 8:25] DeclStmt=
// CHECK: Keyword: "const" [9:3 - 9:8] VarDecl=hello:9:16 (Definition)
@@ -130,7 +130,7 @@ void test() {
// CHECK: Identifier: "x" [20:5 - 20:6] DeclRefExpr=x:18:12
// CHECK: Punctuation: "." [20:6 - 20:7] MemberRefExpr=a:2:16
// CHECK: Identifier: "a" [20:7 - 20:8] MemberRefExpr=a:2:16
-// CHECK: Punctuation: "++" [20:8 - 20:10] UnaryOperator=
+// CHECK: Punctuation: "++" [20:8 - 20:10] UnaryOperator=++
// CHECK: Punctuation: ";" [20:10 - 20:11] CompoundStmt=
// CHECK: Punctuation: "}" [21:3 - 21:4] CompoundStmt=
// CHECK: Keyword: "while" [21:5 - 21:10] DoStmt=
diff --git a/clang/test/Index/blocks.c b/clang/test/Index/blocks.c
index 304c7800cb700c..882ca40459acca 100644
--- a/clang/test/Index/blocks.c
+++ b/clang/test/Index/blocks.c
@@ -29,5 +29,5 @@ void test() {
// CHECK: blocks.c:9:50: MemberRefExpr=x:4:19 SingleRefName=[9:50 - 9:51] RefName=[9:50 - 9:51] Extent=[9:45 - 9:51]
// CHECK: blocks.c:9:45: DeclRefExpr=foo:9:23 Extent=[9:45 - 9:48]
// CHECK: blocks.c:9:54: DeclRefExpr=i:8:11 Extent=[9:54 - 9:55]
-// CHECK: blocks.c:9:59: UnaryOperator= Extent=[9:59 - 9:64]
+// CHECK: blocks.c:9:59: UnaryOperator=& Extent=[9:59 - 9:64]
// CHECK: blocks.c:9:60: DeclRefExpr=_foo:7:21 Extent=[9:60 - 9:64]
diff --git a/clang/test/Index/load-stmts.cpp b/clang/test/Index/load-stmts.cpp
index 0bfaf51daa259b..c65c2295ca3d91 100644
--- a/clang/test/Index/load-stmts.cpp
+++ b/clang/test/Index/load-stmts.cpp
@@ -132,17 +132,17 @@ void casts(int *ip) {
// CHECK: load-stmts.cpp:4:23: DeclRefExpr=x:3:12 Extent=[4:23 - 4:24]
// CHECK: load-stmts.cpp:4:19: UnexposedExpr=z:4:19 Extent=[4:19 - 4:20]
// CHECK: load-stmts.cpp:4:19: DeclRefExpr=z:4:19 Extent=[4:19 - 4:20]
-// CHECK: load-stmts.cpp:4:26: UnaryOperator= Extent=[4:26 - 4:29]
+// CHECK: load-stmts.cpp:4:26: UnaryOperator=++ Extent=[4:26 - 4:29]
// CHECK: load-stmts.cpp:4:28: DeclRefExpr=x:3:12 Extent=[4:28 - 4:29]
// CHECK: load-stmts.cpp:6:10: VarDecl=z2:6:10 (Definition) Extent=[6:7 - 6:17]
// CHECK: load-stmts.cpp:6:7: TypeRef=T:1:13 Extent=[6:7 - 6:8]
-// CHECK: load-stmts.cpp:6:15: UnaryOperator= Extent=[6:15 - 6:17]
+// CHECK: load-stmts.cpp:6:15: UnaryOperator=& Extent=[6:15 - 6:17]
// CHECK: load-stmts.cpp:6:16: DeclRefExpr=x:3:12 Extent=[6:16 - 6:17]
// CHECK: load-stmts.cpp:6:10: UnexposedExpr=z2:6:10 Extent=[6:10 - 6:12]
// CHECK: load-stmts.cpp:6:10: DeclRefExpr=z2:6:10 Extent=[6:10 - 6:12]
// CHECK: load-stmts.cpp:7:13: VarDecl=z3:7:13 (Definition) Extent=[7:10 - 7:20]
// CHECK: load-stmts.cpp:7:10: TypeRef=T:1:13 Extent=[7:10 - 7:11]
-// CHECK: load-stmts.cpp:7:18: UnaryOperator= Extent=[7:18 - 7:20]
+// CHECK: load-stmts.cpp:7:18: UnaryOperator=& Extent=[7:18 - 7:20]
// CHECK: load-stmts.cpp:7:19: DeclRefExpr=x:3:12 Extent=[7:19 - 7:20]
// CHECK: load-stmts.cpp:7:13: UnexposedExpr=z3:7:13 Extent=[7:13 - 7:15]
// CHECK: load-stmts.cpp:7:13: DeclRefExpr=z3:7:13 Extent=[7:13 - 7:15]
diff --git a/clang/test/Index/print-type.c b/clang/test/Index/print-type.c
index 3ceecbd90b2501..aa74b24d6c9a4c 100644
--- a/clang/test/Index/print-type.c
+++ b/clang/test/Index/print-type.c
@@ -44,7 +44,7 @@ _Atomic(unsigned long) aul;
// CHECK: CompoundStmt= [type=] [typekind=Invalid] [isPOD=0]
// CHECK: CallExpr=fn:3:55 [type=void] [typekind=Void] [args= [int] [Int]] [isPOD=0]
// CHECK: DeclRefExpr=fn:3:55 [type=void (*)(int)] [typekind=Pointer] [canonicaltype=void (*)(int)] [canonicaltypekind=Pointer] [isPOD=1] [pointeetype=void (int)] [pointeekind=FunctionProto]
-// CHECK: UnaryOperator= [type=int] [typekind=Int] [isPOD=1]
+// CHECK: UnaryOperator=* [type=int] [typekind=Int] [isPOD=1]
// CHECK: DeclRefExpr=p:3:13 [type=int *] [typekind=Pointer] [isPOD=1] [pointeetype=int] [pointeekind=Int]
// CHECK: DeclStmt= [type=] [typekind=Invalid] [isPOD=0]
// CHECK: VarDecl=w:5:17 (Definition) [type=const FooType] [typekind=Typedef] const [canonicaltype=const int] [canonicaltypekind=Int] [isPOD=1]
diff --git a/clang/test/Index/recursive-cxx-member-calls.cpp b/clang/test/Index/recursive-cxx-member-calls.cpp
index c7f0053500c60a..184ae07a19616d 100644
--- a/clang/test/Index/recursive-cxx-member-calls.cpp
+++ b/clang/test/Index/recursive-cxx-member-calls.cpp
@@ -438,7 +438,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo * Name) {
// CHECK-tokens: Identifier: "size_t" [41:16 - 41:22] TypeRef=size_t:2:25
// CHECK-tokens: Identifier: "npos" [41:23 - 41:27] VarDecl=npos:41:23
// CHECK-tokens: Punctuation: "=" [41:28 - 41:29] VarDecl=npos:41:23
-// CHECK-tokens: Punctuation: "~" [41:30 - 41:31] UnaryOperator=
+// CHECK-tokens: Punctuation: "~" [41:30 - 41:31] UnaryOperator=~
// CHECK-tokens: Identifier: "size_t" [41:31 - 41:37] TypeRef=size_t:2:25
// CHECK-tokens: Punctuation: "(" [41:37 - 41:38] CXXFunctionalCastExpr=
// CHECK-tokens: Literal: "0" [41:38 - 41:39] IntegerLiteral=
@@ -867,7 +867,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo * Name) {
// CHECK-tokens: Punctuation: ")" [89:62 - 89:63] FunctionTemplate=Case:88:42 (Definition)
// CHECK-tokens: Punctuation: "{" [89:64 - 89:65] CompoundStmt=
// CHECK-tokens: Keyword: "return" [90:5 - 90:11] ReturnStmt=
-// CHECK-tokens: Punctuation: "*" [90:12 - 90:13] UnaryOperator=
+// CHECK-tokens: Punctuation: "*" [90:12 - 90:13] UnaryOperator=*
// CHECK-tokens: Keyword: "this" [90:13 - 90:17] CXXThisExpr=
// CHECK-tokens: Punctuation: ";" [90:17 - 90:18] CompoundStmt=
// CHECK-tokens: Punctuation: "}" [91:3 - 91:4] CompoundStmt=
@@ -1629,7 +1629,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo * Name) {
// CHECK: 40:23: TypedefDecl=iterator:40:23 (Definition) Extent=[40:3 - 40:31]
// CHECK: 41:23: VarDecl=npos:41:23 Extent=[41:3 - 41:40]
// CHECK: 41:16: TypeRef=size_t:2:25 Extent=[41:16 - 41:22]
-// CHECK: 41:30: UnaryOperator= Extent=[41:30 - 41:40]
+// CHECK: 41:30: UnaryOperator=~ Extent=[41:30 - 41:40]
// CHECK: 41:31: CXXFunctionalCastExpr= Extent=[41:31 - 41:40]
// CHECK: 41:31: TypeRef=size_t:2:25 Extent=[41:31 - 41:37]
// CHECK: 41:38: UnexposedExpr= Extent=[41:38 - 41:39]
@@ -1856,7 +1856,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo * Name) {
// CHECK: 89:57: ParmDecl=Value:89:57 (Definition) Extent=[89:47 - 89:62]
// CHECK: 89:64: CompoundStmt= Extent=[89:64 - 91:4]
// CHECK: 90:5: ReturnStmt= Extent=[90:5 - 90:17]
-// CHECK: 90:12: UnaryOperator= Extent=[90:12 - 90:17]
+// CHECK: 90:12: UnaryOperator=* Extent=[90:12 - 90:17]
// CHECK: 90:13: CXXThisExpr= Extent=[90:13 - 90:17]
// CHECK: 92:5: CXXMethod=Default:92:5 (Definition) (const) Extent=[92:3 - 94:4] [access=public]
// CHECK: 92:23: ParmDecl=Value:92:23 (Definition) Extent=[92:13 - 92:28]
diff --git a/clang/test/Index/unaryop.cpp b/clang/test/Index/unaryop.cpp
new file mode 100644
index 00000000000000..db0a617b294f1c
--- /dev/null
+++ b/clang/test/Index/unaryop.cpp
@@ -0,0 +1,38 @@
+// RUN: c-index-test -test-load-source all %s | FileCheck %s
+
+void func(void) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-value"
+ int a = 0;
+ int *b = &a;
+ *b;
+ a++;
+ a--;
+ ++a;
+ --a;
+ +a;
+ -a;
+ !a;
+ ~a;
+
+ float _Complex c = 0;
+ __real c;
+ __imag c;
+
+ __extension__ a;
+#pragma clang diagnostic pop
+}
+
+// CHECK: unaryop.cpp:7:14: UnaryOperator=& Extent=[7:14 - 7:16]
+// CHECK: unaryop.cpp:8:5: UnaryOperator=* Extent=[8:5 - 8:7]
+// CHECK: unaryop.cpp:9:5: UnaryOperator=++ Extent=[9:5 - 9:8]
+// CHECK: unaryop.cpp:10:5: UnaryOperator=-- Extent=[10:5 - 10:8]
+// CHECK: unaryop.cpp:11:5: UnaryOperator=++ Extent=[11:5 - 11:8]
+// CHECK: unaryop.cpp:12:5: UnaryOperator=-- Extent=[12:5 - 12:8]
+// CHECK: unaryop.cpp:13:5: UnaryOperator=+ Extent=[13:5 - 13:7]
+// CHECK: unaryop.cpp:14:5: UnaryOperator=- Extent=[14:5 - 14:7]
+// CHECK: unaryop.cpp:15:5: UnaryOperator=! Extent=[15:5 - 15:7]
+// CHECK: unaryop.cpp:16:5: UnaryOperator=~ Extent=[16:5 - 16:7]
+// CHECK: unaryop.cpp:19:5: UnaryOperator=__real Extent=[19:5 - 19:13]
+// CHECK: unaryop.cpp:20:5: UnaryOperator=__imag Extent=[20:5 - 20:13]
+// CHECK: unaryop.cpp:22:5: UnaryOperator=__extension__ Extent=[22:5 - 22:20]
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 39e9e89b1ff00d..fa3cce6a36708d 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -5483,6 +5483,11 @@ CXString clang_getCursorSpelling(CXCursor C) {
clang_getCursorBinaryOperatorKind(C));
}
+ if (C.kind == CXCursor_UnaryOperator) {
+ return clang_getUnaryOperatorKindSpelling(
+ clang_getCursorUnaryOperatorKind(C));
+ }
+
const Decl *D = getDeclFromExpr(getCursorExpr(C));
if (D)
return getDeclSpelling(D);
>From 27192c5839682bbfb9fb27d4ef54029225fe88c7 Mon Sep 17 00:00:00 2001
From: Erik Julian Radermacher <erik.radermacher at uni-osnabrueck.de>
Date: Mon, 31 Aug 2026 18:23:05 +0200
Subject: [PATCH 2/3] fixup! Add retrieval of unary operator spelling and
python bindings
---
.../python/tests/cindex/test_cursor.py | 21 ++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/clang/bindings/python/tests/cindex/test_cursor.py b/clang/bindings/python/tests/cindex/test_cursor.py
index e8a77371f88e27..c18bc9c420e3c9 100644
--- a/clang/bindings/python/tests/cindex/test_cursor.py
+++ b/clang/bindings/python/tests/cindex/test_cursor.py
@@ -988,8 +988,9 @@ def test_binop(self):
assert c.binary_operator == typ
def test_unaryop(self):
- tu = get_tu("""
- void func(void) {
+ tu = get_tu(
+ """
+ void func(void) {
int a = 0;
a++;
++a;
@@ -1004,8 +1005,9 @@ def test_unaryop(self):
__real b;
__imag b;
__extension__ a;
- }
- """, lang="cpp")
+ }""",
+ lang="cpp",
+ )
operators = {
"&": UnaryOperator.AddrOf,
@@ -1023,9 +1025,14 @@ def test_unaryop(self):
c = get_cursor(tu, op)
assert c.unary_operator == typ
- for should_be, has in zip(
- (UnaryOperator.PostInc, UnaryOperator.PreInc, UnaryOperator.PostDec, UnaryOperator.PreDec),
- list(next(tu.cursor.get_children()).get_children())[1:]):
+ shoulds = (
+ UnaryOperator.PostInc,
+ UnaryOperator.PreInc,
+ UnaryOperator.PostDec,
+ UnaryOperator.PreDec,
+ )
+ haves = list(next(tu.cursor.get_children()).get_children())[1:]
+ for should_be, has in zip(shoulds, haves):
assert should_be == has
def test_from_result_null(self):
>From 67fac6dcd259087e718b8f3d7ed3847e27b902c9 Mon Sep 17 00:00:00 2001
From: Erik Julian Radermacher <erik.radermacher at uni-osnabrueck.de>
Date: Tue, 15 Sep 2026 12:04:27 +0200
Subject: [PATCH 3/3] fixup! Add retrieval of unary operator spelling and
python bindings
---
clang/bindings/python/clang/cindex.py | 6 +--
.../python/tests/cindex/test_cursor.py | 53 ++++++++++---------
2 files changed, 31 insertions(+), 28 deletions(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 9e01b0d88951dd..6564e8eed47bd6 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -2044,10 +2044,10 @@ def unary_operator(self) -> UnaryOperator:
:return:
"""
- if not hasattr(self, "_binopcode"):
+ if not hasattr(self, "_unopcode"):
self._binopcode = conf.lib.clang_getCursorUnaryOperatorKind(self)
- return UnaryOperator.from_id(self._binopcode)
+ return UnaryOperator.from_id(self._unopcode)
@property
@cursor_null_guard
@@ -2513,7 +2513,7 @@ def is_postfix(self):
Real = 11
Imag = 12
Extension = 13
- CoAwait = 14
+ Coawait = 14
class StorageClass(BaseEnumeration):
diff --git a/clang/bindings/python/tests/cindex/test_cursor.py b/clang/bindings/python/tests/cindex/test_cursor.py
index c18bc9c420e3c9..ec6b261d3f0bf8 100644
--- a/clang/bindings/python/tests/cindex/test_cursor.py
+++ b/clang/bindings/python/tests/cindex/test_cursor.py
@@ -990,11 +990,9 @@ def test_binop(self):
def test_unaryop(self):
tu = get_tu(
"""
- void func(void) {
+ void prefix_func(void) {
int a = 0;
- a++;
++a;
- a--;
--a;
*(&a);
+a;
@@ -1005,35 +1003,40 @@ def test_unaryop(self):
__real b;
__imag b;
__extension__ a;
+ }
+ void postfix_func(void) {
+ int a = 0;
+ a++;
+ a--;
}""",
lang="cpp",
)
operators = {
- "&": UnaryOperator.AddrOf,
- "*": UnaryOperator.Deref,
- "+": UnaryOperator.Plus,
- "-": UnaryOperator.Minus,
- "~": UnaryOperator.Not,
- "!": UnaryOperator.LNot,
- "__real": UnaryOperator.Real,
- "__imag": UnaryOperator.Imag,
- "__extension__": UnaryOperator.Extension,
+ "prefix": {
+ "&": UnaryOperator.AddrOf,
+ "*": UnaryOperator.Deref,
+ "+": UnaryOperator.Plus,
+ "-": UnaryOperator.Minus,
+ "~": UnaryOperator.Not,
+ "!": UnaryOperator.LNot,
+ "++": UnaryOperator.PreInc,
+ "--": UnaryOperator.PreDec,
+ "__real": UnaryOperator.Real,
+ "__imag": UnaryOperator.Imag,
+ "__extension__": UnaryOperator.Extension,
+ },
+ "postfix": {
+ "++": UnaryOperator.PostInc,
+ "--": UnaryOperator.PostDec,
+ }
}
- for op, typ in operators.items():
- c = get_cursor(tu, op)
- assert c.unary_operator == typ
-
- shoulds = (
- UnaryOperator.PostInc,
- UnaryOperator.PreInc,
- UnaryOperator.PostDec,
- UnaryOperator.PreDec,
- )
- haves = list(next(tu.cursor.get_children()).get_children())[1:]
- for should_be, has in zip(shoulds, haves):
- assert should_be == has
+ for operator_type, ops in operators.items():
+ root = get_cursor(tu, f"{operator_type}_func")
+ for spelling, operator in ops.items():
+ c = get_cursor(root, spelling)
+ assert c is not None and c.unary_operator == operator
def test_from_result_null(self):
tu = get_tu("int a = 1+2;", lang="cpp")
More information about the cfe-commits
mailing list