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
|
main.cpp
|
||||||
OperationFinder.cpp
|
OperationFinder.cpp
|
||||||
OperationStorage.cpp
|
OperationStorage.cpp
|
||||||
|
OperationAstMatcher.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(op-finder
|
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 <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 << ":"
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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());
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user