File indexing completed on 2023-10-25 10:05:55
0001 #include "FiniteMathChecker.h"
0002 #include <clang/AST/AST.h>
0003 #include <clang/AST/ASTConsumer.h>
0004 #include <clang/AST/DeclGroup.h>
0005 #include <clang/AST/RecursiveASTVisitor.h>
0006 #include <clang/AST/Expr.h>
0007
0008 #include "CmsSupport.h"
0009 #include <iostream>
0010 #include <memory>
0011
0012 #include <utility>
0013
0014 using namespace clang;
0015 using namespace clang::ento;
0016 using namespace llvm;
0017
0018 namespace clangcms {
0019
0020 class FMWalkAST : public clang::StmtVisitor<FMWalkAST> {
0021 const CheckerBase *Checker;
0022 clang::ento::BugReporter &BR;
0023 clang::AnalysisDeclContext *AC;
0024 const NamedDecl *ND;
0025
0026 public:
0027 FMWalkAST(const CheckerBase *checker,
0028 clang::ento::BugReporter &br,
0029 clang::AnalysisDeclContext *ac,
0030 const NamedDecl *nd)
0031 : Checker(checker), BR(br), AC(ac), ND(nd) {}
0032
0033
0034 void VisitChildren(clang::Stmt *S);
0035 void VisitStmt(clang::Stmt *S) { VisitChildren(S); }
0036 void VisitCallExpr(clang::CallExpr *CE);
0037 };
0038
0039 void FMWalkAST::VisitChildren(clang::Stmt *S) {
0040 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I != E; ++I)
0041 if (clang::Stmt *child = *I) {
0042 Visit(child);
0043 }
0044 }
0045
0046 void FMWalkAST::VisitCallExpr(clang::CallExpr *CE) {
0047 const clang::Expr *Callee = CE->getCallee();
0048 const FunctionDecl *FD = CE->getDirectCallee();
0049 if (!FD)
0050 return;
0051
0052 const char *sfile = BR.getSourceManager().getPresumedLoc(CE->getExprLoc()).getFilename();
0053 std::string sname(sfile);
0054 if (!support::isInterestingLocation(sname))
0055 return;
0056
0057
0058 clang::IdentifierInfo *II = FD->getIdentifier();
0059 if (!II)
0060 return;
0061
0062 if (!II->isStr("isnan") && !II->isStr("isinf"))
0063 return;
0064
0065 clang::ento::PathDiagnosticLocation CELoc =
0066 clang::ento::PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
0067 BugType *BT = new clang::ento::BugType(Checker,
0068 "std::isnan / std::isinf does not work when fast-math is used. Please use "
0069 "edm::isNotFinite from 'FWCore/Utilities/interface/isFinite.h'",
0070 "fastmath plugin");
0071 std::unique_ptr<clang::ento::BasicBugReport> report =
0072 std::make_unique<clang::ento::BasicBugReport>(*BT, BT->getCheckerName(), CELoc);
0073 BR.emitReport(std::move(report));
0074 }
0075
0076 void FiniteMathChecker::checkASTDecl(const clang::CXXRecordDecl *RD,
0077 clang::ento::AnalysisManager &mgr,
0078 clang::ento::BugReporter &BR) const {
0079 const clang::SourceManager &SM = BR.getSourceManager();
0080 const char *sfile = SM.getPresumedLoc(RD->getLocation()).getFilename();
0081 if (!support::isCmsLocalFile(sfile))
0082 return;
0083
0084 for (clang::CXXRecordDecl::method_iterator I = RD->method_begin(), E = RD->method_end(); I != E; ++I) {
0085 clang::CXXMethodDecl *MD = llvm::cast<clang::CXXMethodDecl>((*I)->getMostRecentDecl());
0086 clang::Stmt *Body = MD->getBody();
0087 if (Body) {
0088 FMWalkAST walker(this, BR, mgr.getAnalysisDeclContext(MD), MD);
0089 walker.Visit(Body);
0090 }
0091 }
0092 }
0093 }