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 main.cpp
OperationFinder.cpp OperationFinder.cpp
OperationStorage.cpp OperationStorage.cpp
OperationAstMatcher.cpp
) )
target_include_directories(op-finder 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 <iostream>
#include "ASTHelpers.hpp"
using namespace clang; using namespace clang;
using namespace clang::ast_matchers; 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) OperationFinder::OperationFinder(IOperationOutput* storage)
: _storage(storage) : _storage(storage)
{ {
assert(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); const auto [file_name, line_number, column_number] = resolveLocations(op, source_manager);
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);
llvm::outs() << file_name << ":" llvm::outs() << file_name << ":"
<< line_number << ":" << line_number << ":"
@ -116,13 +37,9 @@ void OperationFinder::_processAssignment(const clang::ast_matchers::MatchFinder:
llvm::outs() << "\n"; 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"); const auto [file_name, line_number, column_number] = resolveLocations(op, source_manager);
assert(op);
const auto [file_name, line_number, column_number] = resolveLocations(op, *result.SourceManager);
llvm::outs() << file_name << ":" llvm::outs() << file_name << ":"
<< line_number << ":" << line_number << ":"
@ -140,15 +57,14 @@ void OperationFinder::_processArithmetic(const MatchFinder::MatchResult& result)
llvm::outs() << "\n"; 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 = op->getExprStmt();
const Expr* lhs = result.Nodes.getNodeAs<Expr>("lhs");
assert(op); assert(op);
assert(lhs); 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 << ":" llvm::outs() << file_name << ":"
<< line_number << ":" << line_number << ":"

View File

@ -5,24 +5,20 @@
#ifndef LLVM_PROTO_OPERATIONFINDER_HPP #ifndef LLVM_PROTO_OPERATIONFINDER_HPP
#define LLVM_PROTO_OPERATIONFINDER_HPP #define LLVM_PROTO_OPERATIONFINDER_HPP
#include <clang/ASTMatchers/ASTMatchers.h>
#include <clang/ASTMatchers/ASTMatchFinder.h> #include <clang/ASTMatchers/ASTMatchFinder.h>
#include "OperationLog.hpp" #include "OperationLog.hpp"
class OperationFinder : public clang::ast_matchers::MatchFinder::MatchCallback class OperationFinder
{ {
public: public:
explicit OperationFinder(IOperationOutput* storage); 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: 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); void _processExpressionTypes(OperationLog& log, const clang::Expr* source, const clang::Expr* op1, const clang::Expr* op2);
IOperationOutput* _storage; IOperationOutput* _storage;

View File

@ -5,6 +5,7 @@
// Declares llvm::cl::extrahelp. // Declares llvm::cl::extrahelp.
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "OperationAstMatcher.hpp"
#include "OperationFinder.hpp" #include "OperationFinder.hpp"
#include "OperationStorage.hpp" #include "OperationStorage.hpp"
@ -49,9 +50,12 @@ int main(int argc, const char** argv)
OperationStorage storage(OutputFile.getValue()); OperationStorage storage(OutputFile.getValue());
OperationFinder op_finder(&storage); 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());
} }