Refactor AST matcher to a separate class

This commit is contained in:
Erki 2021-03-02 23:24:38 +02:00
parent 0e7cf93c9b
commit aff90d5a9d
7 changed files with 143 additions and 104 deletions

40
op-finder/ASTHelpers.hpp Normal file
View File

@ -0,0 +1,40 @@
//
// Created by erki on 02.03.21.
//
#ifndef C_ANALYZER_ASTHELPERS_HPP
#define C_ANALYZER_ASTHELPERS_HPP
#include <clang/AST/ASTContext.h>
template<typename TOp>
clang::StringRef getOpcode(const TOp *op)
{
return op->getOpcodeStr(op->getOpcode());
}
inline clang::SourceLocation resolveOperationSourceLocation(const clang::SourceManager& source_manager,
const clang::SourceLocation& original)
{
if (source_manager.isMacroBodyExpansion(original))
{
return source_manager.getExpansionLoc(original);
}
return original;
}
template<typename TOp>
std::tuple<std::string, unsigned int, unsigned int> resolveLocations(const TOp* op,
const clang::SourceManager& source_manager)
{
const auto& loc = resolveOperationSourceLocation(source_manager, op->getBeginLoc());
return {
source_manager.getFilename(loc).str(),
source_manager.getSpellingLineNumber(loc),
source_manager.getSpellingColumnNumber(loc)
};
}
#endif //C_ANALYZER_ASTHELPERS_HPP

View File

@ -21,6 +21,7 @@ add_executable(op-finder
main.cpp
OperationFinder.cpp
OperationStorage.cpp
OperationAstMatcher.cpp
)
target_include_directories(op-finder

View File

@ -0,0 +1,57 @@
//
// Created by erki on 02.03.21.
//
#include "OperationAstMatcher.hpp"
#include "OperationFinder.hpp"
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");
}
OperationASTMatcher::OperationASTMatcher(OperationFinder* finder)
: _op_finder(finder)
{ }
void OperationASTMatcher::addToFinder(clang::ast_matchers::MatchFinder& finder)
{
finder.addMatcher(traverse(TK_IgnoreUnlessSpelledInSource, ArithmeticMatcher), this);
finder.addMatcher(traverse(TK_IgnoreUnlessSpelledInSource, AssignmentMatcher), this);
finder.addMatcher(traverse(TK_IgnoreUnlessSpelledInSource, UnaryArithmeticMatcher), this);
}
void OperationASTMatcher::run(const clang::ast_matchers::MatchFinder::MatchResult& result)
{
if (const auto* op = result.Nodes.getNodeAs<clang::BinaryOperator>("assignment"))
{
_op_finder->processAssignment(op, *result.SourceManager);
}
else if (const auto* op = result.Nodes.getNodeAs<clang::BinaryOperator>("arithmetic"))
{
_op_finder->processArithmetic(op, *result.SourceManager);
}
else if (const auto* op = result.Nodes.getNodeAs<clang::UnaryOperator>("unary_arithmetic"))
{
_op_finder->processUnaryArithmetic(op, *result.SourceManager);
}
}

View File

@ -0,0 +1,25 @@
//
// Created by erki on 02.03.21.
//
#ifndef C_ANALYZER_OPERATIONASTMATCHER_HPP
#define C_ANALYZER_OPERATIONASTMATCHER_HPP
#include <clang/ASTMatchers/ASTMatchFinder.h>
class OperationFinder;
class OperationASTMatcher : public clang::ast_matchers::MatchFinder::MatchCallback
{
public:
explicit OperationASTMatcher(OperationFinder* finder);
void addToFinder(clang::ast_matchers::MatchFinder& finder);
void run(const clang::ast_matchers::MatchFinder::MatchResult& result) override;
private:
OperationFinder* _op_finder;
};
#endif //C_ANALYZER_OPERATIONASTMATCHER_HPP

View File

@ -6,99 +6,20 @@
#include <iostream>
#include "ASTHelpers.hpp"
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");
//StatementMatcher ForStatementMatcher =
// forStmt(hasInitStatement(expr().bind("init"))).bind("for_stmt");
template<typename TOp>
StringRef getOpcode(const TOp *op)
{
return op->getOpcodeStr(op->getOpcode());
}
SourceLocation ResolveOperationSourceLocation(const SourceManager& source_manager, const SourceLocation& original)
{
if (source_manager.isMacroBodyExpansion(original))
{
return source_manager.getExpansionLoc(original);
}
return original;
}
template<typename TOp>
std::tuple<std::string, unsigned int, unsigned int> resolveLocations(const TOp* op, const SourceManager& source_manager)
{
const auto& loc = ResolveOperationSourceLocation(source_manager, op->getBeginLoc());
return {
source_manager.getFilename(loc).str(),
source_manager.getSpellingLineNumber(loc),
source_manager.getSpellingColumnNumber(loc)
};
}
}
OperationFinder::OperationFinder(IOperationOutput* storage)
: _storage(storage)
{
assert(storage);
}
void OperationFinder::addMatcher(MatchFinder &finder)
void OperationFinder::processAssignment(const clang::BinaryOperator* op, const clang::SourceManager& source_manager)
{
finder.addMatcher(traverse(TK_IgnoreUnlessSpelledInSource, ArithmeticMatcher), this);
finder.addMatcher(traverse(TK_IgnoreUnlessSpelledInSource, AssignmentMatcher), 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::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);
const auto [file_name, line_number, column_number] = resolveLocations(op, *result.SourceManager);
const auto [file_name, line_number, column_number] = resolveLocations(op, source_manager);
llvm::outs() << file_name << ":"
<< line_number << ":"
@ -116,13 +37,9 @@ void OperationFinder::_processAssignment(const clang::ast_matchers::MatchFinder:
llvm::outs() << "\n";
}
void OperationFinder::_processArithmetic(const MatchFinder::MatchResult& result)
void OperationFinder::processArithmetic(const clang::BinaryOperator* op, const clang::SourceManager& source_manager)
{
const BinaryOperator* op = result.Nodes.getNodeAs<clang::BinaryOperator>("arithmetic");
assert(op);
const auto [file_name, line_number, column_number] = resolveLocations(op, *result.SourceManager);
const auto [file_name, line_number, column_number] = resolveLocations(op, source_manager);
llvm::outs() << file_name << ":"
<< line_number << ":"
@ -140,15 +57,14 @@ void OperationFinder::_processArithmetic(const MatchFinder::MatchResult& result)
llvm::outs() << "\n";
}
void OperationFinder::_processUnaryArithmetic(const MatchFinder::MatchResult &result)
void OperationFinder::processUnaryArithmetic(const clang::UnaryOperator* op, const clang::SourceManager& source_manager)
{
const UnaryOperator* op = result.Nodes.getNodeAs<UnaryOperator>("unary_arithmetic");
const Expr* lhs = result.Nodes.getNodeAs<Expr>("lhs");
const Expr* lhs = op->getExprStmt();
assert(op);
assert(lhs);
const auto [file_name, line_number, column_number] = resolveLocations(op, *result.SourceManager);
const auto [file_name, line_number, column_number] = resolveLocations(op, source_manager);
llvm::outs() << file_name << ":"
<< line_number << ":"

View File

@ -5,24 +5,20 @@
#ifndef LLVM_PROTO_OPERATIONFINDER_HPP
#define LLVM_PROTO_OPERATIONFINDER_HPP
#include <clang/ASTMatchers/ASTMatchers.h>
#include <clang/ASTMatchers/ASTMatchFinder.h>
#include "OperationLog.hpp"
class OperationFinder : public clang::ast_matchers::MatchFinder::MatchCallback
class OperationFinder
{
public:
explicit OperationFinder(IOperationOutput* storage);
void addMatcher(clang::ast_matchers::MatchFinder& finder);
void processAssignment(const clang::BinaryOperator* op, const clang::SourceManager& source_manager);
void processArithmetic(const clang::BinaryOperator* op, const clang::SourceManager& source_manager);
void processUnaryArithmetic(const clang::UnaryOperator* op, const clang::SourceManager& source_manager);
void run(const clang::ast_matchers::MatchFinder::MatchResult& result) override;
private:
void _processAssignment(const clang::ast_matchers::MatchFinder::MatchResult& result);
void _processArithmetic(const clang::ast_matchers::MatchFinder::MatchResult& result);
void _processUnaryArithmetic(const clang::ast_matchers::MatchFinder::MatchResult& result);
void _processExpressionTypes(OperationLog& log, const clang::Expr* source, const clang::Expr* op1, const clang::Expr* op2);
IOperationOutput* _storage;

View File

@ -5,6 +5,7 @@
// Declares llvm::cl::extrahelp.
#include "llvm/Support/CommandLine.h"
#include "OperationAstMatcher.hpp"
#include "OperationFinder.hpp"
#include "OperationStorage.hpp"
@ -49,9 +50,12 @@ int main(int argc, const char** argv)
OperationStorage storage(OutputFile.getValue());
OperationFinder op_finder(&storage);
MatchFinder finder;
MatchFinder matcher;
OperationASTMatcher finder(&op_finder);
op_finder.addMatcher(finder);
finder.addToFinder(matcher);
return Tool.run(newFrontendActionFactory(&finder).get());
//Tool.run(newFrontendActionFactory<DebuggeringASTAction>().get());
return Tool.run(newFrontendActionFactory(&matcher).get());
}