Index: bindings/python/clang/cindex.py =================================================================== --- bindings/python/clang/cindex.py +++ bindings/python/clang/cindex.py @@ -1258,6 +1258,18 @@ return StorageClass.from_id(self._storage_class) @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): """ Retrieves the access specifier (if any) of the entity pointed at by the @@ -1533,6 +1545,84 @@ res._tu = args[0]._tu return res +class BinaryOperator(object): + """ + Describes the BinaryOperator of a declaration + """ + + # The unique kind objects, index by id. + _kinds = [] + _name_map = None + + def __init__(self, value): + if value >= len(BinaryOperator._kinds): + BinaryOperator._kinds += [None] * (value - len(BinaryOperator._kinds) + 1) + if BinaryOperator._kinds[value] is not None: + raise ValueError, 'BinaryOperator already loaded' + self.value = value + BinaryOperator._kinds[value] = self + BinaryOperator._name_map = None + + def from_param(self): + return self.value + + @property + def name(self): + """Get the enumeration name of this storage class.""" + if self._name_map is None: + self._name_map = {} + for key, value in BinaryOperator.__dict__.items(): + if isinstance(value, BinaryOperator): + self._name_map[value] = key + return self._name_map[self] + + @property + def is_assignment(self): + return BinaryOperator.Assign.value <= self.value < BinaryOperator.Comma.value + + @staticmethod + def from_id(id): + if id >= len(BinaryOperator._kinds) or not BinaryOperator._kinds[id]: + raise ValueError,'Unknown storage class %d' % id + return BinaryOperator._kinds[id] + + 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.LT = BinaryOperator(10) +BinaryOperator.GT = BinaryOperator(11) +BinaryOperator.LE = BinaryOperator(12) +BinaryOperator.GE = BinaryOperator(13) +BinaryOperator.EQ = BinaryOperator(14) +BinaryOperator.NE = BinaryOperator(15) +BinaryOperator.And = BinaryOperator(16) +BinaryOperator.Xor = BinaryOperator(17) +BinaryOperator.Or = BinaryOperator(18) +BinaryOperator.LAnd = BinaryOperator(19) +BinaryOperator.LOr = BinaryOperator(20) +BinaryOperator.Assign = BinaryOperator(21) +BinaryOperator.MulAssign = BinaryOperator(22) +BinaryOperator.DivAssign = BinaryOperator(23) +BinaryOperator.RemAssign = BinaryOperator(24) +BinaryOperator.AddAssign = BinaryOperator(25) +BinaryOperator.SubAssign = BinaryOperator(26) +BinaryOperator.ShlAssign = BinaryOperator(27) +BinaryOperator.ShrAssign = BinaryOperator(28) +BinaryOperator.AndAssign = BinaryOperator(29) +BinaryOperator.XorAssign = BinaryOperator(30) +BinaryOperator.OrAssign = BinaryOperator(31) +BinaryOperator.Comma = BinaryOperator(32) + class StorageClass(object): """ Describes the storage class of a declaration Index: include/clang-c/Index.h =================================================================== --- include/clang-c/Index.h +++ include/clang-c/Index.h @@ -3812,6 +3812,51 @@ */ CINDEX_LINKAGE unsigned clang_Cursor_isVariadic(CXCursor C); +enum CX_BinaryOperatorKind { + CX_BO_Invalid, + CX_BO_PtrMemD, + CX_BO_PtrMemI, + CX_BO_Mul, + CX_BO_Div, + CX_BO_Rem, + CX_BO_Add, + CX_BO_Sub, + CX_BO_Shl, + CX_BO_Shr, + CX_BO_LT, + CX_BO_GT, + CX_BO_LE, + CX_BO_GE, + CX_BO_EQ, + CX_BO_NE, + CX_BO_And, + CX_BO_Xor, + CX_BO_Or, + CX_BO_LAnd, + CX_BO_LOr, + CX_BO_Assign, + CX_BO_MulAssign, + CX_BO_DivAssign, + CX_BO_RemAssign, + CX_BO_AddAssign, + CX_BO_SubAssign, + CX_BO_ShlAssign, + CX_BO_ShrAssign, + CX_BO_AndAssign, + CX_BO_XorAssign, + CX_BO_OrAssign, + 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(CXCursor C); /** * \brief Given a cursor that represents a declaration, return the associated * comment's source range. The range may include multiple consecutive comments Index: include/clang/AST/OperationKinds.h =================================================================== --- include/clang/AST/OperationKinds.h +++ include/clang/AST/OperationKinds.h @@ -305,7 +305,8 @@ enum BinaryOperatorKind { // Operators listed in order of precedence. - // Note that additions to this should also update the StmtVisitor class. + // Note that additions to this should also update the StmtVisitor class + // and the C bindings in libclang. BO_PtrMemD, BO_PtrMemI, // [C++ 5.5] Pointer-to-member operators. BO_Mul, BO_Div, BO_Rem, // [C99 6.5.5] Multiplicative operators. BO_Add, BO_Sub, // [C99 6.5.6] Additive operators. Index: tools/libclang/CIndex.cpp =================================================================== --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -3670,6 +3670,11 @@ return cxstring::createDup(OS.str()); } + if (C.kind == CXCursor_BinaryOperator || + C.kind == CXCursor_CompoundAssignOperator) { + return clang_Cursor_getBinaryOpCodeStr(C); + } + const Decl *D = getDeclFromExpr(getCursorExpr(C)); if (D) return getDeclSpelling(D); @@ -3683,18 +3688,18 @@ return cxstring::createEmpty(); } - + if (C.kind == CXCursor_MacroExpansion) return cxstring::createRef(getCursorMacroExpansion(C).getName() - ->getNameStart()); + ->getNameStart()); if (C.kind == CXCursor_MacroDefinition) return cxstring::createRef(getCursorMacroDefinition(C)->getName() - ->getNameStart()); + ->getNameStart()); if (C.kind == CXCursor_InclusionDirective) return cxstring::createDup(getCursorInclusionDirective(C)->getFileName()); - + if (clang_isDeclaration(C.kind)) return getDeclSpelling(getCursorDecl(C)); @@ -6667,6 +6672,34 @@ return 0; } +enum CX_BinaryOperatorKind clang_Cursor_getBinaryOpCode(CXCursor C) { + if (C.kind != CXCursor_BinaryOperator && + C.kind != CXCursor_CompoundAssignOperator) { + return CX_BO_Invalid; + } + + const Expr *D = getCursorExpr(C); + if (const BinaryOperator *BinOp = dyn_cast(D)) { + return static_cast(BinOp->getOpcode() + 1); + } + + return CX_BO_Invalid; +} + +CXString clang_Cursor_getBinaryOpCodeStr(CXCursor C) { + if (C.kind != CXCursor_BinaryOperator && + C.kind != CXCursor_CompoundAssignOperator) { + return cxstring::createEmpty(); + } + + const Expr *D = getCursorExpr(C); + if (const BinaryOperator *BinOp = dyn_cast(D)) { + return cxstring::createDup(BinOp->getOpcodeStr()); + } + + return cxstring::createEmpty(); +} + CXSourceRange clang_Cursor_getCommentRange(CXCursor C) { if (!clang_isDeclaration(C.kind)) return clang_getNullRange();