Refactor AST matcher to a separate class
This commit is contained in:
parent
0e7cf93c9b
commit
aff90d5a9d
40
op-finder/ASTHelpers.hpp
Normal file
40
op-finder/ASTHelpers.hpp
Normal 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
|
||||
@ -21,6 +21,7 @@ add_executable(op-finder
|
||||
main.cpp
|
||||
OperationFinder.cpp
|
||||
OperationStorage.cpp
|
||||
OperationAstMatcher.cpp
|
||||
)
|
||||
|
||||
target_include_directories(op-finder
|
||||
|
||||
57
op-finder/OperationAstMatcher.cpp
Normal file
57
op-finder/OperationAstMatcher.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
25
op-finder/OperationAstMatcher.hpp
Normal file
25
op-finder/OperationAstMatcher.hpp
Normal 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
|
||||
@ -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 << ":"
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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());
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user