// // Created by erki on 24.02.21. // #include "OperationAnalyzer.hpp" #include using namespace clang; namespace { bool IsInMainFile(const SourceManager& source_manager, const SourceLocation& loc) { //return source_manager.isWrittenInMainFile(loc); return true; } template StringRef getOpcode(const TOp *op) { return op->getOpcodeStr(op->getOpcode()); } } void OperationAnalyzer::processAssignment(const BinaryOperator* op, const SourceManager& source_manager) { if (!IsInMainFile(source_manager, op->getBeginLoc())) return; const auto& loc = op->getBeginLoc(); llvm::outs() << source_manager.getFilename(loc) << ":" << source_manager.getSpellingLineNumber(loc) << ":" << source_manager.getSpellingColumnNumber(loc) << ":" << "Assignment: Assigned to: "; _processExpressionTypes(op, op->getLHS(), op->getRHS()); llvm::outs() << "\n"; } void OperationAnalyzer::processBinaryArithmetic(const BinaryOperator* op, const SourceManager& source_manager) { if (!IsInMainFile(source_manager, op->getBeginLoc())) return; const auto& loc = op->getBeginLoc(); llvm::outs() << source_manager.getFilename(loc) << ":" << source_manager.getSpellingLineNumber(loc) << ":" << source_manager.getSpellingColumnNumber(loc) << ":" << "Arithmetic: Type: " << getOpcode(op) << " LHS: "; _processExpressionTypes(op, op->getLHS(), op->getRHS()); llvm::outs() << "\n"; } void OperationAnalyzer::processCompoundAssignment(const clang::CompoundAssignOperator* op, const SourceManager& source_manager) { if (!IsInMainFile(source_manager, op->getBeginLoc())) return; const auto& loc = op->getBeginLoc(); llvm::outs() << source_manager.getFilename(loc) << ":" << source_manager.getSpellingLineNumber(loc) << ":" << source_manager.getSpellingColumnNumber(loc) << ":" << "Compound assignment: Op code: " << getOpcode(op) << " "; _processExpressionTypes(op, op->getLHS(), op->getRHS()); llvm::outs() << "\n"; } void OperationAnalyzer::processUnaryArithmetic(const UnaryOperator* op, const SourceManager& source_manager) { const Expr* lhs = op->getExprStmt(); if (!IsInMainFile(source_manager, lhs->getBeginLoc())) return; const auto& loc = lhs->getBeginLoc(); llvm::outs() << source_manager.getFilename(loc) << ":" << source_manager.getSpellingLineNumber(loc) << ":" << source_manager.getSpellingColumnNumber(loc) << ":" << "Unary arithmetic: Type: " << getOpcode(op) << " LHS: "; _processExpressionTypes(op, lhs, nullptr); llvm::outs() << "\n"; } void OperationAnalyzer::_processExpressionTypes(const Expr* source, const Expr* lhs, const Expr* rhs) { auto printTypeName = [](const QualType& t) -> void { if (t->isTypedefNameType()) { const TypedefType* tdt = cast(t); assert(tdt); llvm::outs() << "Typedef type: " << t.getAsString() << ", underlying: " << tdt->desugar().getAsString() << "."; } else if (t->isBuiltinType()) { llvm::outs() << "Builtin type: " << t.getAsString() << "."; } else { llvm::outs() << "Other type: " << t.getAsString() << "."; } }; llvm::outs() << "Expression types:\n\tExpression eval type: "; printTypeName(source->getType()); if (lhs) { llvm::outs() << "\n\tLHS eval type: "; printTypeName(lhs->getType()); } if (rhs) { llvm::outs() << "\n\tRHS eval type: "; printTypeName(rhs->getType()); } }