// // Created by erki on 16.02.21. // #include "OperationFinder.hpp" #include #include "ASTHelpers.hpp" using namespace clang; using namespace clang::ast_matchers; OperationFinder::OperationFinder(IOperationOutput* storage) : _storage(storage) { assert(storage); } void OperationFinder::processArithmetic(const clang::BinaryOperator* op, const clang::SourceManager& source_manager) { const auto [file_name, line_number, column_number] = resolveLocations(op, source_manager); llvm::outs() << file_name << ":" << line_number << ":" << column_number << ":" << "Binary arithmetic: Type: " << getOpcode(op) << " LHS: "; OperationLog log; log.line = line_number; log.operation = getOpcode(op).str(); log.current_for_loops = _for_loop_stack; log.is_fallthrough = _in_fallthrough; _processExpressionTypes(log, op, op->getLHS(), op->getRHS()); _storage->pushOperation(file_name, log); llvm::outs() << "\n"; } void OperationFinder::processUnaryArithmetic(const clang::UnaryOperator* op, const clang::SourceManager& source_manager) { const Expr* lhs = op->getExprStmt(); assert(op); assert(lhs); const auto [file_name, line_number, column_number] = resolveLocations(op, source_manager); llvm::outs() << file_name << ":" << line_number << ":" << column_number << ":" << "Unary arithmetic: Type: " << getOpcode(op) << " LHS: "; OperationLog log; log.line = line_number; log.operation = getOpcode(op).str(); log.current_for_loops = _for_loop_stack; log.is_fallthrough = _in_fallthrough; _processExpressionTypes(log, op, lhs, nullptr); _storage->pushOperation(file_name, log); llvm::outs() << "\n"; } void OperationFinder::fallthroughBranchEntered() { _in_fallthrough = true; } void OperationFinder::fallthroughBranchExited() { _in_fallthrough = false; } void OperationFinder::forLoopEntered() { _for_loop_stack.push_back(_next_for_loop_id); _next_for_loop_id++; } void OperationFinder::forLoopExited() { _for_loop_stack.pop_back(); } void OperationFinder::_processExpressionTypes(OperationLog& log, const Expr* source, const Expr* op1, const Expr* op2) { auto printTypeName = [](const QualType& t) -> std::string { if (t->isTypedefNameType()) { const TypedefType* tdt = cast(t); assert(tdt); llvm::outs() << "Typedef type: " << t.getAsString() << ", underlying: " << tdt->desugar().getAsString() << "."; return tdt->desugar().getAsString(); } else if (t->isBuiltinType()) { llvm::outs() << "Builtin type: " << t.getAsString() << "."; return t.getAsString(); } else { llvm::outs() << "Other type: " << t.getAsString() << "."; return t.getAsString(); } }; llvm::outs() << "Expression types:\n\tExpression eval type: "; log.operand_result = printTypeName(source->getType()); if (op1) { llvm::outs() << "\n\tLHS eval type: "; log.operand_lhs = printTypeName(op1->getType()); } if (op2) { llvm::outs() << "\n\tRHS eval type: "; log.operand_rhs = printTypeName(op2->getType()); } }