masters-thesis/op-finder/OperationFinder.cpp

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);
}