// // Created by erki on 16.02.21. // #include "OperationFinder.hpp" #include #include using namespace clang; using namespace clang::ast_matchers; namespace { StatementMatcher AssignmentMatcher = binaryOperation(isAssignmentOperator(), hasLHS(expr().bind("lhs")), hasRHS(expr().bind("rhs"))).bind("assignment"); StatementMatcher ArithmeticMatcher = binaryOperation(hasAnyOperatorName("+", "-", "/", "*", "<", ">", "<=", ">=", "==", "<<", ">>", "%"), hasLHS(expr().bind("lhs")), hasRHS(expr().bind("lhs"))).bind("arithmetic"); StatementMatcher UnaryArithmeticMatcher = unaryOperator(hasAnyOperatorName("!", "++", "--"), hasUnaryOperand(expr().bind("lhs"))).bind("unary_arithmetic"); StatementMatcher CompoundMatcher = compoundStmt().bind("compound_stmt"); bool isInMainFile(const MatchFinder::MatchResult &result, const SourceLocation &loc) { return result.Context->getSourceManager().isWrittenInMainFile(loc); } template StringRef getOpcode(const TOp *op) { return op->getOpcodeStr(op->getOpcode()); } } void OperationFinder::addMatcher(MatchFinder &finder) { finder.addMatcher(traverse(TK_IgnoreUnlessSpelledInSource, ArithmeticMatcher), this); finder.addMatcher(traverse(TK_IgnoreUnlessSpelledInSource, AssignmentMatcher), this); finder.addMatcher(traverse(TK_IgnoreUnlessSpelledInSource, CompoundMatcher), this); finder.addMatcher(traverse(TK_IgnoreUnlessSpelledInSource, UnaryArithmeticMatcher), this); } void OperationFinder::run(const MatchFinder::MatchResult &result) { if (result.Nodes.getNodeAs("assignment")) { _processAssignment(result); } else if (result.Nodes.getNodeAs("arithmetic")) { _processArithmetic(result); } else if (result.Nodes.getNodeAs("compound_stmt")) { _processCompoundStmt(result); } else if (result.Nodes.getNodeAs("unary_arithmetic")) { _processUnaryArithmetic(result); } } void OperationFinder::_processAssignment(const clang::ast_matchers::MatchFinder::MatchResult& result) { const BinaryOperator* op = result.Nodes.getNodeAs("assignment"); assert(op); _operation_analyzer.processAssignment(op, *result.SourceManager); } void OperationFinder::_processArithmetic(const MatchFinder::MatchResult& result) { const BinaryOperator* op = result.Nodes.getNodeAs("arithmetic"); assert(op); _operation_analyzer.processBinaryArithmetic(op, *result.SourceManager); } void OperationFinder::_processCompoundStmt(const clang::ast_matchers::MatchFinder::MatchResult& result) { const CompoundStmt* stmt = result.Nodes.getNodeAs("compound_stmt"); assert(stmt); const CompoundAssignOperator* op = dyn_cast(stmt->getStmtExprResult()); if (!op || !op->isCompoundAssignmentOp()) return; _operation_analyzer.processCompoundAssignment(op, *result.SourceManager); } void OperationFinder::_processUnaryArithmetic(const MatchFinder::MatchResult &result) { const UnaryOperator* op = result.Nodes.getNodeAs("unary_arithmetic"); assert(op); _operation_analyzer.processUnaryArithmetic(op, *result.SourceManager); }