[libclang] Add CXBinaryOperatorKind and CXUnaryOperatorKind

Adds 2 new functions to the C libclang api for retrieving operator
kinds for binary and unary operators from cursors. Also adds 2
functions for retrieving the spelling of the new enums.

Fixes https://github.com/llvm/llvm-project/issues/29138
Differential Revision: https://reviews.llvm.org/D150910
This commit is contained in:
MineGame159 2023-06-09 10:01:43 -04:00 committed by Aaron Ballman
parent 621507ce20
commit 7fbc9de455
6 changed files with 221 additions and 4 deletions

View File

@ -728,6 +728,9 @@ libclang
has an evaluable bit width. Fixes undefined behavior when called on a
bit-field whose width depends on a template parameter.
- Added ``CXBinaryOperatorKind`` and ``CXUnaryOperatorKind``.
(`#29138 <https://github.com/llvm/llvm-project/issues/29138>`_)
Static Analyzer
---------------
- Fix incorrect alignment attribute on the this parameter of certain

View File

@ -6510,6 +6510,144 @@ typedef enum CXVisitorResult (*CXFieldVisitor)(CXCursor C,
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);
/**
* @}
*/

View File

@ -362,8 +362,8 @@ CAST_OPERATION(IntToOCLSampler)
//===- 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 @@ BINARY_OPERATION(Comma, ",")
//===- 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, "++")

View File

@ -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,38 @@ cxindex::Logger::~Logger() {
OS << "--------------------------------------------------\n";
}
}
CXString clang_getBinaryOperatorKindSpelling(enum CXBinaryOperatorKind kind) {
return cxstring::createRef(
BinaryOperator::getOpcodeStr(static_cast<BinaryOperatorKind>(kind - 1)));
}
enum CXBinaryOperatorKind clang_getCursorBinaryOperatorKind(CXCursor cursor) {
if (clang_isExpression(cursor.kind)) {
const Expr *expr = getCursorExpr(cursor);
if (const auto *op = dyn_cast<BinaryOperator>(expr))
return static_cast<CXBinaryOperatorKind>(op->getOpcode() + 1);
if (const auto *op = dyn_cast<CXXRewrittenBinaryOperator>(expr))
return static_cast<CXBinaryOperatorKind>(op->getOpcode() + 1);
}
return CXBinaryOperator_Invalid;
}
CXString clang_getUnaryOperatorKindSpelling(enum CXUnaryOperatorKind kind) {
return cxstring::createRef(
UnaryOperator::getOpcodeStr(static_cast<UnaryOperatorKind>(kind - 1)));
}
enum CXUnaryOperatorKind clang_getCursorUnaryOperatorKind(CXCursor cursor) {
if (clang_isExpression(cursor.kind)) {
const Expr *expr = getCursorExpr(cursor);
if (const auto *op = dyn_cast<UnaryOperator>(expr))
return static_cast<CXUnaryOperatorKind>(op->getOpcode() + 1);
}
return CXUnaryOperator_Invalid;
}

View File

@ -422,6 +422,10 @@ LLVM_17 {
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

View File

@ -1138,6 +1138,40 @@ void Class1::fun() {}
"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;