Skip to content

Retrieve BinaryOperator::getOpcode and BinaryOperator::getOpcodeStr via libclang and its python interface #98489

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions clang/bindings/python/clang/cindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -1820,6 +1820,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 @@ -2110,6 +2122,55 @@ def from_cursor_result(res, fn, args):
return res


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

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

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


class StorageClass(BaseEnumeration):
"""
Describes the storage class of a declaration
Expand Down Expand Up @@ -3847,6 +3908,7 @@ def write_main_file_to_stdout(self):
("clang_Cursor_getTemplateArgumentUnsignedValue", [Cursor, c_uint], c_ulonglong),
("clang_Cursor_isAnonymous", [Cursor], bool),
("clang_Cursor_isBitField", [Cursor], bool),
("clang_Cursor_getBinaryOpcode", [Cursor], c_int),
("clang_Cursor_getBriefCommentText", [Cursor], _CXString, _CXString.from_result),
("clang_Cursor_getRawCommentText", [Cursor], _CXString, _CXString.from_result),
("clang_Cursor_getOffsetOfField", [Cursor], c_longlong),
Expand Down Expand Up @@ -4016,6 +4078,7 @@ def function_exists(self, name):

__all__ = [
"AvailabilityKind",
"BinaryOperator",
"Config",
"CodeCompletionResults",
"CompilationDatabase",
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/bindings/python/tests/cindex/test_enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
LinkageKind,
TLSKind,
StorageClass,
BinaryOperator,
)


Expand All @@ -28,6 +29,7 @@ class TestEnums(unittest.TestCase):
LinkageKind,
TLSKind,
StorageClass,
BinaryOperator,
]

def test_from_id(self):
Expand Down
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,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
Loading
Loading