Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -717,6 +717,9 @@ has an evaluable bit width. Fixes undefined behavior when called on a bit-field whose width depends on a template parameter. +- Add ``CXBinaryOperatorKind`` and ``CXUnaryOperatorKind``. + (`#29138 `_) + Static Analyzer --------------- - Fix incorrect alignment attribute on the this parameter of certain Index: clang/include/clang-c/Index.h =================================================================== --- clang/include/clang-c/Index.h +++ clang/include/clang-c/Index.h @@ -6510,6 +6510,144 @@ CINDEX_LINKAGE unsigned clang_Type_visitFields(CXType T, CXFieldVisitor visitor, CXClientData client_data); +/** + * Describes the kind of binary operators. + */ +enum CXBinaryOperatorKind { + /** This value describes cursors which are not binary operators. */ + CXBinaryOperator_Invalid, + /** C++ Pointer - to - member operator. */ + CXBinaryOperator_PtrMemD, + /** C++ Pointer - to - member operator. */ + CXBinaryOperator_PtrMemI, + /** Multiplication operator. */ + CXBinaryOperator_Mul, + /** Division operator. */ + CXBinaryOperator_Div, + /** Remainder operator. */ + CXBinaryOperator_Rem, + /** Addition operator. */ + CXBinaryOperator_Add, + /** Subtraction operator. */ + CXBinaryOperator_Sub, + /** Bitwise shift left operator. */ + CXBinaryOperator_Shl, + /** Bitwise shift right operator. */ + CXBinaryOperator_Shr, + /** C++ three-way comparison (spaceship) operator. */ + CXBinaryOperator_Cmp, + /** Less than operator. */ + CXBinaryOperator_LT, + /** Greater than operator. */ + CXBinaryOperator_GT, + /** Less or equal operator. */ + CXBinaryOperator_LE, + /** Greater or equal operator. */ + CXBinaryOperator_GE, + /** Equal operator. */ + CXBinaryOperator_EQ, + /** Not equal operator. */ + CXBinaryOperator_NE, + /** Bitwise AND operator. */ + CXBinaryOperator_And, + /** Bitwise XOR operator. */ + CXBinaryOperator_Xor, + /** Bitwise OR operator. */ + CXBinaryOperator_Or, + /** Logical AND operator. */ + CXBinaryOperator_LAnd, + /** Logical OR operator. */ + CXBinaryOperator_LOr, + /** Assignment operator. */ + CXBinaryOperator_Assign, + /** Multiplication assignment operator. */ + CXBinaryOperator_MulAssign, + /** Division assignment operator. */ + CXBinaryOperator_DivAssign, + /** Remainder assignment operator. */ + CXBinaryOperator_RemAssign, + /** Addition assignment operator. */ + CXBinaryOperator_AddAssign, + /** Subtraction assignment operator. */ + CXBinaryOperator_SubAssign, + /** Bitwise shift left assignment operator. */ + CXBinaryOperator_ShlAssign, + /** Bitwise shift right assignment operator. */ + CXBinaryOperator_ShrAssign, + /** Bitwise AND assignment operator. */ + CXBinaryOperator_AndAssign, + /** Bitwise XOR assignment operator. */ + CXBinaryOperator_XorAssign, + /** Bitwise OR assignment operator. */ + CXBinaryOperator_OrAssign, + /** Comma operator. */ + CXBinaryOperator_Comma +}; + +/** + * Retrieve the spelling of a given CXBinaryOperatorKind. + */ +CINDEX_LINKAGE CXString +clang_getBinaryOperatorKindSpelling(enum CXBinaryOperatorKind kind); + +/** + * Retrieve the binary operator kind of this cursor. + * + * If this cursor is not a binary operator then returns Invalid. + */ +CINDEX_LINKAGE enum CXBinaryOperatorKind + clang_getCursorBinaryOperatorKind(CXCursor cursor); + +/** + * Describes the kind of unary operators. + */ +enum CXUnaryOperatorKind { + /** This value describes cursors which are not unary operators. */ + CXUnaryOperator_Invalid, + /** Postfix increment operator. */ + CXUnaryOperator_PostInc, + /** Postfix decrement operator. */ + CXUnaryOperator_PostDec, + /** Prefix increment operator. */ + CXUnaryOperator_PreInc, + /** Prefix decrement operator. */ + CXUnaryOperator_PreDec, + /** Address of operator. */ + CXUnaryOperator_AddrOf, + /** Dereference operator. */ + CXUnaryOperator_Deref, + /** Plus operator. */ + CXUnaryOperator_Plus, + /** Minus operator. */ + CXUnaryOperator_Minus, + /** Not operator. */ + CXUnaryOperator_Not, + /** LNot operator. */ + CXUnaryOperator_LNot, + /** "__real expr" operator. */ + CXUnaryOperator_Real, + /** "__imag expr" operator. */ + CXUnaryOperator_Imag, + /** __extension__ marker operator. */ + CXUnaryOperator_Extension, + /** C++ co_await operator. */ + CXUnaryOperator_Coawait +}; + +/** + * Retrieve the spelling of a given CXUnaryOperatorKind. + */ +CINDEX_LINKAGE CXString +clang_getUnaryOperatorKindSpelling(enum CXUnaryOperatorKind kind); + +/** + * Retrieve the unary operator kind of this cursor. + * + * If this cursor is not a unary operator then returns Invalid. + */ +CINDEX_LINKAGE enum CXUnaryOperatorKind + clang_getCursorUnaryOperatorKind(CXCursor cursor); + /** * @} */ Index: clang/include/clang/AST/OperationKinds.def =================================================================== --- clang/include/clang/AST/OperationKinds.def +++ clang/include/clang/AST/OperationKinds.def @@ -362,8 +362,8 @@ //===- Binary Operations -------------------------------------------------===// // Operators listed in order of precedence. -// Note that additions to this should also update the StmtVisitor class and -// BinaryOperator::getOverloadedOperator. +// Note that additions to this should also update the StmtVisitor class, +// BinaryOperator::getOverloadedOperator and CXBinaryOperatorKind enum. // [C++ 5.5] Pointer-to-member operators. BINARY_OPERATION(PtrMemD, ".*") @@ -415,8 +415,8 @@ //===- Unary Operations ---------------------------------------------------===// -// Note that additions to this should also update the StmtVisitor class and -// UnaryOperator::getOverloadedOperator. +// Note that additions to this should also update the StmtVisitor class, +// UnaryOperator::getOverloadedOperator and CXUnaryOperatorKind enum. // [C99 6.5.2.4] Postfix increment and decrement UNARY_OPERATION(PostInc, "++") Index: clang/tools/libclang/CIndex.cpp =================================================================== --- clang/tools/libclang/CIndex.cpp +++ clang/tools/libclang/CIndex.cpp @@ -23,8 +23,11 @@ #include "clang-c/FatalErrorHandler.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclObjCCommon.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/Mangle.h" #include "clang/AST/OpenMPClause.h" +#include "clang/AST/OperationKinds.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticCategories.h" @@ -9604,3 +9607,39 @@ OS << "--------------------------------------------------\n"; } } + +CXString clang_getBinaryOperatorKindSpelling(enum CXBinaryOperatorKind kind) { + return cxstring::createRef( + BinaryOperator::getOpcodeStr(static_cast(kind - 1))); +} + +enum CXBinaryOperatorKind clang_getCursorBinaryOperatorKind(CXCursor cursor) { + if (clang_isExpression(cursor.kind)) { + const Expr *expr = getCursorExpr(cursor); + + if (const BinaryOperator *op = dyn_cast(expr)) + return static_cast(op->getOpcode() + 1); + + if (const CXXRewrittenBinaryOperator *op = + dyn_cast(expr)) + return static_cast(op->getOpcode() + 1); + } + + return CXBinaryOperator_Invalid; +} + +CXString clang_getUnaryOperatorKindSpelling(enum CXUnaryOperatorKind kind) { + return cxstring::createRef( + UnaryOperator::getOpcodeStr(static_cast(kind - 1))); +} + +enum CXUnaryOperatorKind clang_getCursorUnaryOperatorKind(CXCursor cursor) { + if (clang_isExpression(cursor.kind)) { + const Expr *expr = getCursorExpr(cursor); + + if (const UnaryOperator *op = dyn_cast(expr)) + return static_cast(op->getOpcode() + 1); + } + + return CXUnaryOperator_Invalid; +} Index: clang/tools/libclang/libclang.map =================================================================== --- clang/tools/libclang/libclang.map +++ clang/tools/libclang/libclang.map @@ -422,6 +422,10 @@ global: clang_CXXMethod_isExplicit; clang_createIndexWithOptions; + clang_getBinaryOperatorKindSpelling; + clang_getCursorBinaryOperatorKind; + clang_getUnaryOperatorKindSpelling; + clang_getCursorUnaryOperatorKind; }; # Example of how to add a new symbol version entry. If you do add a new symbol Index: clang/unittests/libclang/LibclangTest.cpp =================================================================== --- clang/unittests/libclang/LibclangTest.cpp +++ clang/unittests/libclang/LibclangTest.cpp @@ -1138,6 +1138,40 @@ "class ns1::Class1"); } +TEST_F(LibclangParseTest, BinaryOperator) { + std::string Main = "main.cpp"; + WriteFile(Main, "int foo() { return 5 + 9; };"); + ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0, nullptr, + 0, TUFlags); + + Traverse([](CXCursor cursor, CXCursor parent) -> CXChildVisitResult { + if (cursor.kind == CXCursor_BinaryOperator) { + EXPECT_EQ(clang_getCursorBinaryOperatorKind(cursor), + CXBinaryOperator_Add); + return CXChildVisit_Break; + } + + return CXChildVisit_Recurse; + }); +} + +TEST_F(LibclangParseTest, UnaryOperator) { + std::string Main = "main.cpp"; + WriteFile(Main, "int foo() { int a = 5; return a++; };"); + ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0, nullptr, + 0, TUFlags); + + Traverse([](CXCursor cursor, CXCursor parent) -> CXChildVisitResult { + if (cursor.kind == CXCursor_UnaryOperator) { + EXPECT_EQ(clang_getCursorUnaryOperatorKind(cursor), + CXUnaryOperator_PostInc); + return CXChildVisit_Break; + } + + return CXChildVisit_Recurse; + }); +} + class LibclangRewriteTest : public LibclangParseTest { public: CXRewriter Rew = nullptr;