115 lines
3.3 KiB
C++
115 lines
3.3 KiB
C++
//
|
|
// Created by erki on 16.02.21.
|
|
//
|
|
|
|
#include "OperationFinder.hpp"
|
|
|
|
#include <iostream>
|
|
#include <sstream>
|
|
|
|
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<typename TOp>
|
|
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<clang::BinaryOperator>("assignment"))
|
|
{
|
|
_processAssignment(result);
|
|
}
|
|
else if (result.Nodes.getNodeAs<clang::BinaryOperator>("arithmetic"))
|
|
{
|
|
_processArithmetic(result);
|
|
}
|
|
else if (result.Nodes.getNodeAs<clang::CompoundStmt>("compound_stmt"))
|
|
{
|
|
_processCompoundStmt(result);
|
|
}
|
|
else if (result.Nodes.getNodeAs<clang::UnaryOperator>("unary_arithmetic"))
|
|
{
|
|
_processUnaryArithmetic(result);
|
|
}
|
|
}
|
|
|
|
void OperationFinder::_processAssignment(const clang::ast_matchers::MatchFinder::MatchResult& result)
|
|
{
|
|
const BinaryOperator* op = result.Nodes.getNodeAs<BinaryOperator>("assignment");
|
|
|
|
assert(op);
|
|
|
|
_operation_analyzer.processAssignment(op, *result.SourceManager);
|
|
}
|
|
|
|
void OperationFinder::_processArithmetic(const MatchFinder::MatchResult& result)
|
|
{
|
|
const BinaryOperator* op = result.Nodes.getNodeAs<clang::BinaryOperator>("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<CompoundStmt>("compound_stmt");
|
|
|
|
assert(stmt);
|
|
|
|
const CompoundAssignOperator* op = dyn_cast<CompoundAssignOperator>(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<UnaryOperator>("unary_arithmetic");
|
|
|
|
assert(op);
|
|
|
|
_operation_analyzer.processUnaryArithmetic(op, *result.SourceManager);
|
|
}
|