Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 11:26:53

0001 #include "PsetExistsFCallChecker.h"
0002 #include <iostream>
0003 #include <fstream>
0004 #include <iterator>
0005 #include <string>
0006 
0007 using namespace clang;
0008 using namespace ento;
0009 using namespace llvm;
0010 
0011 namespace clangcms {
0012 
0013   class PEFWalker : public clang::StmtVisitor<PEFWalker> {
0014     const CheckerBase *Checker;
0015     clang::ento::BugReporter &BR;
0016     clang::AnalysisDeclContext *AC;
0017 
0018   public:
0019     PEFWalker(const CheckerBase *checker, clang::ento::BugReporter &br, clang::AnalysisDeclContext *ac)
0020         : Checker(checker), BR(br), AC(ac) {}
0021 
0022     void VisitChildren(clang::Stmt *S);
0023     void VisitCallExpr(CallExpr *CE);
0024     void VisitStmt(clang::Stmt *S) { VisitChildren(S); }
0025     void VisitCXXMemberCallExpr(clang::CXXMemberCallExpr *CE);
0026     void VisitCXXConstructExpr(CXXConstructExpr *CCE);
0027     void Report(const std::string &mname, const std::string &pname, const Expr *CE) const;
0028   };
0029 
0030   void PEFWalker::VisitChildren(clang::Stmt *S) {
0031     for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I != E; ++I)
0032       if (clang::Stmt *child = *I) {
0033         Visit(child);
0034       }
0035   }
0036 
0037   void PEFWalker::VisitCXXConstructExpr(CXXConstructExpr *CCE) {
0038     CXXConstructorDecl *CCD = CCE->getConstructor();
0039     if (!CCD)
0040       return;
0041     const char *sfile = BR.getSourceManager().getPresumedLoc(CCE->getExprLoc()).getFilename();
0042     std::string sname(sfile);
0043     if (!support::isInterestingLocation(sname))
0044       return;
0045     std::string mname = support::getQualifiedName(*CCD);
0046     const NamedDecl *PD = llvm::dyn_cast_or_null<NamedDecl>(AC->getDecl());
0047     if (!PD)
0048       return;
0049     std::string pname = support::getQualifiedName(*PD);
0050     Report(mname, pname, CCE);
0051 
0052     VisitChildren(CCE);
0053   }
0054 
0055   void PEFWalker::VisitCXXMemberCallExpr(CXXMemberCallExpr *CE) {
0056     CXXMethodDecl *MD = CE->getMethodDecl();
0057     if (!MD)
0058       return;
0059     const NamedDecl *PD = llvm::dyn_cast_or_null<NamedDecl>(AC->getDecl());
0060     if (!PD)
0061       return;
0062     std::string mname = support::getQualifiedName(*MD);
0063     std::string pname = support::getQualifiedName(*PD);
0064     Report(mname, pname, CE);
0065   }
0066 
0067   void PEFWalker::VisitCallExpr(CallExpr *CE) {
0068     std::string buf;
0069     llvm::raw_string_ostream os(buf);
0070     LangOptions LangOpts;
0071     LangOpts.CPlusPlus = true;
0072     PrintingPolicy Policy(LangOpts);
0073     FunctionDecl *FD = CE->getDirectCallee();
0074     if (!FD)
0075       return;
0076     const char *sfile = BR.getSourceManager().getPresumedLoc(CE->getExprLoc()).getFilename();
0077     std::string sname(sfile);
0078     if (!support::isInterestingLocation(sname))
0079       return;
0080     std::string mname;
0081     mname = support::getQualifiedName(*FD);
0082     const NamedDecl *PD = llvm::dyn_cast_or_null<NamedDecl>(AC->getDecl());
0083     if (!PD)
0084       return;
0085     std::string pname = support::getQualifiedName(*PD);
0086     Report(mname, pname, CE);
0087 
0088     VisitChildren(CE);
0089   }
0090 
0091   void PEFWalker::Report(const std::string &mname, const std::string &pname, const Expr *CE) const {
0092     PathDiagnosticLocation CELoc = PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
0093     std::string ename = "edm::ParameterSet::exists";
0094     std::string eaname = "edm::ParameterSet::existsAs";
0095     std::string pdname = "edm::ParameterDescription";
0096     llvm::SmallString<100> buf;
0097     llvm::raw_svector_ostream os(buf);
0098     if (mname.find(ename) != std::string::npos || mname.find(eaname) != std::string::npos) {
0099       if (pname.find(pdname) != std::string::npos)
0100         return;
0101       os << "function " << mname << " is called in function " << pname;
0102       BugType *BT = new BugType(
0103           Checker, "Function edm::ParameterSet::exists() or edm::ParameterSet::existsAs<>() called", "CMS code rules");
0104       std::unique_ptr<BasicBugReport> R = std::make_unique<BasicBugReport>(*BT, os.str(), CELoc);
0105       R->setDeclWithIssue(AC->getDecl());
0106       R->addRange(CE->getExprLoc());
0107       BR.emitReport(std::move(R));
0108       std::string tname = "function-checker.txt.unsorted";
0109       std::string ostring = "function '" + pname + "' calls function '" + mname + "'.\n";
0110       support::writeLog(ostring, tname);
0111     }
0112   }
0113 
0114   void PsetExistsFCallChecker::checkASTDecl(const CXXMethodDecl *MD, AnalysisManager &mgr, BugReporter &BR) const {
0115     const SourceManager &SM = BR.getSourceManager();
0116     PathDiagnosticLocation DLoc = PathDiagnosticLocation::createBegin(MD, SM);
0117     if (SM.isInSystemHeader(DLoc.asLocation()) || SM.isInExternCSystemHeader(DLoc.asLocation()))
0118       return;
0119     if (!MD->doesThisDeclarationHaveABody())
0120       return;
0121     clangcms::PEFWalker walker(this, BR, mgr.getAnalysisDeclContext(MD));
0122     walker.Visit(MD->getBody());
0123     return;
0124   }
0125 
0126   void PsetExistsFCallChecker::checkASTDecl(const FunctionTemplateDecl *TD,
0127                                             AnalysisManager &mgr,
0128                                             BugReporter &BR) const {
0129     const clang::SourceManager &SM = BR.getSourceManager();
0130     clang::ento::PathDiagnosticLocation DLoc = clang::ento::PathDiagnosticLocation::createBegin(TD, SM);
0131     if (SM.isInSystemHeader(DLoc.asLocation()) || SM.isInExternCSystemHeader(DLoc.asLocation()))
0132       return;
0133 
0134     for (auto I = TD->spec_begin(), E = TD->spec_end(); I != E; ++I) {
0135       if (I->doesThisDeclarationHaveABody()) {
0136         clangcms::PEFWalker walker(this, BR, mgr.getAnalysisDeclContext(*I));
0137         walker.Visit(I->getBody());
0138       }
0139     }
0140     return;
0141   }
0142 
0143 }  // namespace clangcms