Skip to content

Commit

Permalink
[libclang/python] Retrieve BinaryOperator::getOpcode and BinaryOperat…
Browse files Browse the repository at this point in the history
…or::getOpcodeStr via libclang and its python interface
  • Loading branch information
Thomas Wucher committed Jul 11, 2024
1 parent 8b7263b commit d0e2b83
Show file tree
Hide file tree
Showing 19 changed files with 1,655 additions and 771 deletions.
66 changes: 66 additions & 0 deletions clang/bindings/python/clang/cindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -1892,6 +1892,18 @@ def availability(self):

return AvailabilityKind.from_id(self._availability)

@property
def binary_operator(self):
"""
Retrieves the opcode if this cursor points to a binary operator
:return:
"""

if not hasattr(self, '_binopcode'):
self._binopcode = conf.lib.clang_Cursor_getBinaryOpcode(self)

return BinaryOperator.from_id(self._binopcode)

@property
def access_specifier(self):
"""
Expand Down Expand Up @@ -2181,6 +2193,60 @@ def from_cursor_result(res, fn, args):
res._tu = args[0]._tu
return res

class BinaryOperator(BaseEnumeration):
"""
Describes the BinaryOperator of a declaration
"""

# The unique kind objects, index by id.
_kinds = []
_name_map = None

def __nonzero__(self):
""" Allows checks of the kind ```if cursor.binary_operator:```"""
return self.value != 0

@property
def is_assignment(self):
return BinaryOperator.Assign.value <= self.value < BinaryOperator.Comma.value

def __repr__(self):
return 'BinaryOperator.%s' % (self.name,)

BinaryOperator.Invalid = BinaryOperator(0)
BinaryOperator.PtrMemD = BinaryOperator(1)
BinaryOperator.PtrMemI = BinaryOperator(2)
BinaryOperator.Mul = BinaryOperator(3)
BinaryOperator.Div = BinaryOperator(4)
BinaryOperator.Rem = BinaryOperator(5)
BinaryOperator.Add = BinaryOperator(6)
BinaryOperator.Sub = BinaryOperator(7)
BinaryOperator.Shl = BinaryOperator(8)
BinaryOperator.Shr = BinaryOperator(9)
BinaryOperator.Cmp = BinaryOperator(10)
BinaryOperator.LT = BinaryOperator(11)
BinaryOperator.GT = BinaryOperator(12)
BinaryOperator.LE = BinaryOperator(13)
BinaryOperator.GE = BinaryOperator(14)
BinaryOperator.EQ = BinaryOperator(15)
BinaryOperator.NE = BinaryOperator(16)
BinaryOperator.And = BinaryOperator(17)
BinaryOperator.Xor = BinaryOperator(18)
BinaryOperator.Or = BinaryOperator(19)
BinaryOperator.LAnd = BinaryOperator(20)
BinaryOperator.LOr = BinaryOperator(21)
BinaryOperator.Assign = BinaryOperator(22)
BinaryOperator.MulAssign = BinaryOperator(23)
BinaryOperator.DivAssign = BinaryOperator(24)
BinaryOperator.RemAssign = BinaryOperator(25)
BinaryOperator.AddAssign = BinaryOperator(26)
BinaryOperator.SubAssign = BinaryOperator(27)
BinaryOperator.ShlAssign = BinaryOperator(28)
BinaryOperator.ShrAssign = BinaryOperator(29)
BinaryOperator.AndAssign = BinaryOperator(30)
BinaryOperator.XorAssign = BinaryOperator(31)
BinaryOperator.OrAssign = BinaryOperator(32)
BinaryOperator.Comma = BinaryOperator(33)

class StorageClass:
"""
Expand Down
104 changes: 104 additions & 0 deletions clang/bindings/python/tests/cindex/test_cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from clang.cindex import TemplateArgumentKind
from clang.cindex import TranslationUnit
from clang.cindex import TypeKind
from clang.cindex import BinaryOperator
from .util import get_cursor
from .util import get_cursors
from .util import get_tu
Expand Down Expand Up @@ -54,6 +55,64 @@ class C {
void foo<-7, float, true>();
"""

kBinops = """\
struct C {
int m;
};
void func(void){
int a, b;
int C::* p = &C::
C c;
c.*p;
C* pc;
pc->*p;
a * b;
a / b;
a % b;
a + b;
a - b;
a << b;
a >> b;
a < b;
a > b;
a <= b;
a >= b;
a == b;
a != b;
a & b;
a ^ b;
a | b;
a && b;
a || b;
a = b;
a *= b;
a /= b;
a %= b;
a += b;
a -= b;
a <<= b;
a >>= b;
a &= b;
a ^= b;
a |= b;
a , b;
}
"""


class TestCursor(unittest.TestCase):
def test_get_children(self):
Expand Down Expand Up @@ -695,3 +754,48 @@ def test_mangled_name(self):
self.assertIn(
foo.mangled_name, ("_Z3fooii", "__Z3fooii", "?foo@@YAHHH", "?foo@@YAHHH@Z")
)

def test_binop(self):
tu = get_tu(kBinops, lang="cpp")

operators = {
# not exposed yet
# ".*" : BinaryOperator.PtrMemD,
"->*": BinaryOperator.PtrMemI,
"*": BinaryOperator.Mul,
"/": BinaryOperator.Div,
"%": BinaryOperator.Rem,
"+": BinaryOperator.Add,
"-": BinaryOperator.Sub,
"<<": BinaryOperator.Shl,
">>": BinaryOperator.Shr,
# tests do not run in C++2a mode so this operator is not available
# "<=>" : BinaryOperator.Cmp,
"<": BinaryOperator.LT,
">": BinaryOperator.GT,
"<=": BinaryOperator.LE,
">=": BinaryOperator.GE,
"==": BinaryOperator.EQ,
"!=": BinaryOperator.NE,
"&": BinaryOperator.And,
"^": BinaryOperator.Xor,
"|": BinaryOperator.Or,
"&&": BinaryOperator.LAnd,
"||": BinaryOperator.LOr,
"=": BinaryOperator.Assign,
"*=": BinaryOperator.MulAssign,
"/=": BinaryOperator.DivAssign,
"%=": BinaryOperator.RemAssign,
"+=": BinaryOperator.AddAssign,
"-=": BinaryOperator.SubAssign,
"<<=": BinaryOperator.ShlAssign,
">>=": BinaryOperator.ShrAssign,
"&=": BinaryOperator.AndAssign,
"^=": BinaryOperator.XorAssign,
"|=": BinaryOperator.OrAssign,
",": BinaryOperator.Comma,
}

for op, typ in operators.items():
c = get_cursor(tu, op)
assert c.binary_operator == typ
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1289,6 +1289,8 @@ Python Binding Changes
- Exposed `CXRewriter` API as `class Rewriter`.
- Add some missing kinds from Index.h (CursorKind: 149-156, 272-320, 420-437.
TemplateArgumentKind: 5-9. TypeKind: 161-175 and 178).
- Add support for retrieving binary operator information through
Cursor.binary_operator().

OpenMP Support
--------------
Expand Down
53 changes: 53 additions & 0 deletions clang/include/clang-c/Index.h
Original file line number Diff line number Diff line change
Expand Up @@ -3750,6 +3750,59 @@ enum CX_StorageClass {
CX_SC_Register
};

/**
* Represents a specific kind of binary operator which can appear at a cursor.
*/
enum CX_BinaryOperatorKind {
CX_BO_Invalid = 0,
CX_BO_PtrMemD = 1,
CX_BO_PtrMemI = 2,
CX_BO_Mul = 3,
CX_BO_Div = 4,
CX_BO_Rem = 5,
CX_BO_Add = 6,
CX_BO_Sub = 7,
CX_BO_Shl = 8,
CX_BO_Shr = 9,
CX_BO_Cmp = 10,
CX_BO_LT = 11,
CX_BO_GT = 12,
CX_BO_LE = 13,
CX_BO_GE = 14,
CX_BO_EQ = 15,
CX_BO_NE = 16,
CX_BO_And = 17,
CX_BO_Xor = 18,
CX_BO_Or = 19,
CX_BO_LAnd = 20,
CX_BO_LOr = 21,
CX_BO_Assign = 22,
CX_BO_MulAssign = 23,
CX_BO_DivAssign = 24,
CX_BO_RemAssign = 25,
CX_BO_AddAssign = 26,
CX_BO_SubAssign = 27,
CX_BO_ShlAssign = 28,
CX_BO_ShrAssign = 29,
CX_BO_AndAssign = 30,
CX_BO_XorAssign = 31,
CX_BO_OrAssign = 32,
CX_BO_Comma = 33,
CX_BO_LAST = CX_BO_Comma
};

/**
* \brief Returns the operator code for the binary operator.
*/
CINDEX_LINKAGE enum CX_BinaryOperatorKind
clang_Cursor_getBinaryOpcode(CXCursor C);

/**
* \brief Returns a string containing the spelling of the binary operator.
*/
CINDEX_LINKAGE CXString
clang_Cursor_getBinaryOpcodeStr(enum CX_BinaryOperatorKind Op);

/**
* Returns the storage class for a function or variable declaration.
*
Expand Down
92 changes: 92 additions & 0 deletions clang/test/Index/binop.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// RUN: c-index-test -test-print-binops %s | FileCheck %s

struct C {
int m;
};

void func(void) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-value"
int a, b;
int C::*p = &C::m;

C c;
c.*p;

C *pc;
pc->*p;

a *b;
a / b;
a % b;
a + b;
a - b;

a << b;
a >> b;

a < b;
a > b;

a <= b;
a >= b;
a == b;
a != b;

a &b;
a ^ b;
a | b;

a &&b;
a || b;

a = b;

a *= b;
a /= b;
a %= b;
a += b;
a -= b;

a <<= b;
a >>= b;

a &= b;
a ^= b;
a |= b;
a, b;
#pragma clang diagnostic pop
}

// CHECK: BinaryOperator=.* BinOp=.* 1
// CHECK: BinaryOperator=->* BinOp=->* 2
// CHECK: BinaryOperator=* BinOp=* 3
// CHECK: BinaryOperator=/ BinOp=/ 4
// CHECK: BinaryOperator=% BinOp=% 5
// CHECK: BinaryOperator=+ BinOp=+ 6
// CHECK: BinaryOperator=- BinOp=- 7
// CHECK: BinaryOperator=<< BinOp=<< 8
// CHECK: BinaryOperator=>> BinOp=>> 9
// CHECK: BinaryOperator=< BinOp=< 11
// CHECK: BinaryOperator=> BinOp=> 12
// CHECK: BinaryOperator=<= BinOp=<= 13
// CHECK: BinaryOperator=>= BinOp=>= 14
// CHECK: BinaryOperator=== BinOp=== 15
// CHECK: BinaryOperator=!= BinOp=!= 16
// CHECK: BinaryOperator=& BinOp=& 17
// CHECK: BinaryOperator=^ BinOp=^ 18
// CHECK: BinaryOperator=| BinOp=| 19
// CHECK: BinaryOperator=&& BinOp=&& 20
// CHECK: BinaryOperator=|| BinOp=|| 21
// CHECK: BinaryOperator== BinOp== 22
// CHECK: CompoundAssignOperator=*= BinOp=*= 23
// CHECK: CompoundAssignOperator=/= BinOp=/= 24
// CHECK: CompoundAssignOperator=%= BinOp=%= 25
// CHECK: CompoundAssignOperator=+= BinOp=+= 26
// CHECK: CompoundAssignOperator=-= BinOp=-= 27
// CHECK: CompoundAssignOperator=<<= BinOp=<<= 28
// CHECK: CompoundAssignOperator=>>= BinOp=>>= 29
// CHECK: CompoundAssignOperator=&= BinOp=&= 30
// CHECK: CompoundAssignOperator=^= BinOp=^= 31
// CHECK: CompoundAssignOperator=|= BinOp=|= 32
// CHECK: BinaryOperator=, BinOp=, 33
3 changes: 1 addition & 2 deletions clang/test/Index/blocks.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@ void test() {
// CHECK: blocks.c:9:18: TypeRef=struct foo:4:8 Extent=[9:18 - 9:21]
// CHECK: blocks.c:9:28: CompoundStmt= Extent=[9:28 - 9:58]
// CHECK: blocks.c:9:30: ReturnStmt= Extent=[9:30 - 9:55]
// CHECK: blocks.c:9:37: BinaryOperator= Extent=[9:37 - 9:55]
// CHECK: blocks.c:9:37: BinaryOperator=+ Extent=[9:37 - 9:55]
// CHECK: blocks.c:9:37: CStyleCastExpr= Extent=[9:37 - 9:51]
// CHECK: blocks.c:9:38: TypeRef=int_t:3:13 Extent=[9:38 - 9:43]
// 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:60: DeclRefExpr=_foo:7:21 Extent=[9:60 - 9:64]

2 changes: 1 addition & 1 deletion clang/test/Index/c-index-api-loadTU-test.m
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ @interface TestAttributes()
// CHECK: c-index-api-loadTU-test.m:50:13: VarDecl=d:50:13 (Definition) Extent=[50:2 - 50:14]
// CHECK: c-index-api-loadTU-test.m:50:2: TypeRef=id:0:0 Extent=[50:2 - 50:4]
// CHECK: c-index-api-loadTU-test.m:50:6: ObjCProtocolRef=Proto:25:11 Extent=[50:6 - 50:11]
// CHECK: c-index-api-loadTU-test.m:51:2: BinaryOperator= Extent=[51:2 - 51:7]
// CHECK: c-index-api-loadTU-test.m:51:2: BinaryOperator== Extent=[51:2 - 51:7]
// CHECK: c-index-api-loadTU-test.m:51:2: DeclRefExpr=d:50:13 Extent=[51:2 - 51:3]
// CHECK: c-index-api-loadTU-test.m:51:6: UnexposedExpr=c:49:12 Extent=[51:6 - 51:7]
// CHECK: c-index-api-loadTU-test.m:51:6: UnexposedExpr=c:49:12 Extent=[51:6 - 51:7]
Expand Down
Loading

0 comments on commit d0e2b83

Please sign in to comment.