llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Rumo (ItsRumo)

<details>
<summary>Changes</summary>

Adds handling for unary operators in clang_getCursorSpelling() and provides 
representations in Python for unary operator kinds as well as a property to 
retrieve the UnaryOperator of a cursor.

The changeset is modeled after a972a394afcb276abb3029d0f2753d4403e379c2, which 
introduced similar features for binary operators.

---
Full diff: https://github.com/llvm/llvm-project/pull/219983.diff


12 Files Affected:

- (modified) clang/bindings/python/clang/cindex.py (+44) 
- (modified) clang/bindings/python/tests/cindex/test_cursor.py (+42) 
- (modified) clang/bindings/python/tests/cindex/test_enums.py (+2) 
- (modified) clang/docs/ReleaseNotes.md (+4) 
- (modified) clang/test/Index/annotate-tokens-pp.c (+1-1) 
- (modified) clang/test/Index/annotate-tokens.c (+2-2) 
- (modified) clang/test/Index/blocks.c (+1-1) 
- (modified) clang/test/Index/load-stmts.cpp (+3-3) 
- (modified) clang/test/Index/print-type.c (+1-1) 
- (modified) clang/test/Index/recursive-cxx-member-calls.cpp (+4-4) 
- (added) clang/test/Index/unaryop.cpp (+38) 
- (modified) clang/tools/libclang/CIndex.cpp (+5) 


``````````diff
diff --git a/clang/bindings/python/clang/cindex.py 
b/clang/bindings/python/clang/cindex.py
index bc00dd770ce3b..9e01b0d88951d 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 76680e576b307..e8a77371f88e2 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 09f346ee6e11f..f926e75309b35 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 dd3dfdc5ad8d7..d23eacffd9f9f 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 7da2d6f5823aa..16248bb403b35 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 08e7a9a02f8f2..34f50da877575 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 304c7800cb700..882ca40459acc 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 0bfaf51daa259..c65c2295ca3d9 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 3ceecbd90b250..aa74b24d6c9a4 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 c7f0053500c60..184ae07a19616 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 0000000000000..db0a617b294f1
--- /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 39e9e89b1ff00..fa3cce6a36708 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);

``````````

</details>


https://github.com/llvm/llvm-project/pull/219983
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to