Back to home page

Project CMSSW displayed by LXR

 
 

    


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     // Stmt visitor methods.
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     // Get the name of the callee.
0058     clang::IdentifierInfo *II = FD->getIdentifier();
0059     if (!II)  // if no identifier, not a simple C function
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 }  // namespace clangcms