104 lines
2.0 KiB
C++
104 lines
2.0 KiB
C++
//
|
|
// Created by erki on 02.03.21.
|
|
//
|
|
|
|
#include "OperationFinderAstVisitor.hpp"
|
|
|
|
#include "OperationFinder.hpp"
|
|
#include "ASTHelpers.hpp"
|
|
|
|
OperationFinderAstVisitor::OperationFinderAstVisitor(OperationFinder* op_finder)
|
|
: _context(nullptr)
|
|
, _op_finder(op_finder)
|
|
{ }
|
|
|
|
void OperationFinderAstVisitor::NewContext(clang::ASTContext* context)
|
|
{
|
|
_context = context;
|
|
}
|
|
|
|
bool OperationFinderAstVisitor::VisitForStmt(clang::ForStmt* stmt)
|
|
{
|
|
assert(_context);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OperationFinderAstVisitor::VisitBinaryOperator(clang::BinaryOperator* op)
|
|
{
|
|
assert(_context);
|
|
|
|
if (!op->isCompoundAssignmentOp())
|
|
_op_finder->processArithmetic(op, _context->getSourceManager());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OperationFinderAstVisitor::VisitUnaryOperator(clang::UnaryOperator* op)
|
|
{
|
|
assert(_context);
|
|
|
|
_op_finder->processUnaryArithmetic(op, _context->getSourceManager());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OperationFinderAstVisitor::dataTraverseStmtPre(clang::Stmt* stmt)
|
|
{
|
|
assert(_context);
|
|
|
|
if (auto* loop = clang::dyn_cast<clang::ForStmt>(stmt))
|
|
{
|
|
if (loop->getInit())
|
|
{
|
|
_loop_init = loop->getInit();
|
|
}
|
|
else
|
|
{
|
|
_op_finder->forLoopEntered();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_checkIfForLoopInitDone(stmt);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OperationFinderAstVisitor::dataTraverseStmtPost(clang::Stmt* stmt)
|
|
{
|
|
assert(_context);
|
|
|
|
if (clang::dyn_cast<clang::ForStmt>(stmt))
|
|
_op_finder->forLoopExited();
|
|
|
|
return true;
|
|
}
|
|
|
|
void OperationFinderAstVisitor::_checkIfForLoopInitDone(clang::Stmt* stmt)
|
|
{
|
|
if (!_loop_init || stmt == _loop_init)
|
|
return;
|
|
|
|
const auto [file, line, column] = resolveLocationsWithLoc(stmt->getEndLoc(), _context->getSourceManager());
|
|
const auto [for_file, for_line, for_column] = resolveLocationsWithLoc(_loop_init->getEndLoc(), _context->getSourceManager());
|
|
|
|
bool is_done = false;
|
|
|
|
if (line > for_line)
|
|
{
|
|
is_done = true;
|
|
}
|
|
else if (line == for_line && column > for_column)
|
|
{
|
|
is_done = true;
|
|
}
|
|
|
|
if (is_done)
|
|
{
|
|
_loop_init = nullptr;
|
|
_op_finder->forLoopEntered();
|
|
}
|
|
}
|