Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:31:51

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     if (!PD->hasAttr<CMSSaAllowAttr>())
0050       return;
0051     std::string pname = support::getQualifiedName(*PD);
0052     Report(mname, pname, CCE);
0053 
0054     VisitChildren(CCE);
0055   }
0056 
0057   void PEFWalker::VisitCXXMemberCallExpr(CXXMemberCallExpr *CE) {
0058     CXXMethodDecl *MD = CE->getMethodDecl();
0059     if (!MD)
0060       return;
0061     const NamedDecl *PD = llvm::dyn_cast_or_null<NamedDecl>(AC->getDecl());
0062     if (!PD)
0063       return;
0064     if (!PD->hasAttr<CMSSaAllowAttr>())
0065       return;
0066     std::string mname = support::getQualifiedName(*MD);
0067     std::string pname = support::getQualifiedName(*PD);
0068     Report(mname, pname, CE);
0069   }
0070 
0071   void PEFWalker::VisitCallExpr(CallExpr *CE) {
0072     std::string buf;
0073     llvm::raw_string_ostream os(buf);
0074     LangOptions LangOpts;
0075     LangOpts.CPlusPlus = true;
0076     PrintingPolicy Policy(LangOpts);
0077     FunctionDecl *FD = CE->getDirectCallee();
0078     if (!FD)
0079       return;
0080     const char *sfile = BR.getSourceManager().getPresumedLoc(CE->getExprLoc()).getFilename();
0081     std::string sname(sfile);
0082     if (!support::isInterestingLocation(sname))
0083       return;
0084     std::string mname;
0085     mname = support::getQualifiedName(*FD);
0086     const NamedDecl *PD = llvm::dyn_cast_or_null<NamedDecl>(AC->getDecl());
0087     if (!PD)
0088       return;
0089     if (!PD->hasAttr<CMSSaAllowAttr>())
0090       return;
0091     std::string pname = support::getQualifiedName(*PD);
0092     Report(mname, pname, CE);
0093 
0094     VisitChildren(CE);
0095   }
0096 
0097   void PEFWalker::Report(const std::string &mname, const std::string &pname, const Expr *CE) const {
0098     PathDiagnosticLocation CELoc = PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
0099     std::string ename = "edm::ParameterSet::exists";
0100     std::string eaname = "edm::ParameterSet::existsAs";
0101     std::string pdname = "edm::ParameterDescription";
0102     llvm::SmallString<100> buf;
0103     llvm::raw_svector_ostream os(buf);
0104     if (mname.find(ename) != std::string::npos || mname.find(eaname) != std::string::npos) {
0105       if (pname.find(pdname) != std::string::npos)
0106         return;
0107       os << "function " << mname << " is called in function " << pname;
0108       BugType *BT = new BugType(
0109           Checker, "Function edm::ParameterSet::exists() or edm::ParameterSet::existsAs<>() called", "CMS code rules");
0110       std::unique_ptr<BasicBugReport> R = std::make_unique<BasicBugReport>(*BT, os.str(), CELoc);
0111       R->setDeclWithIssue(AC->getDecl());
0112       R->addRange(CE->getExprLoc());
0113       BR.emitReport(std::move(R));
0114       std::string tname = "function-checker.txt.unsorted";
0115       std::string ostring = "function '" + pname + "' calls function '" + mname + "'.\n";
0116       support::writeLog(ostring, tname);
0117     }
0118   }
0119 
0120   void PsetExistsFCallChecker::checkASTDecl(const CXXMethodDecl *MD, AnalysisManager &mgr, BugReporter &BR) const {
0121     const SourceManager &SM = BR.getSourceManager();
0122     PathDiagnosticLocation DLoc = PathDiagnosticLocation::createBegin(MD, SM);
0123     if (SM.isInSystemHeader(DLoc.asLocation()) || SM.isInExternCSystemHeader(DLoc.asLocation()))
0124       return;
0125     if (!MD->doesThisDeclarationHaveABody())
0126       return;
0127     clangcms::PEFWalker walker(this, BR, mgr.getAnalysisDeclContext(MD));
0128     walker.Visit(MD->getBody());
0129     return;
0130   }
0131 
0132   void PsetExistsFCallChecker::checkASTDecl(const FunctionTemplateDecl *TD,
0133                                             AnalysisManager &mgr,
0134                                             BugReporter &BR) const {
0135     const clang::SourceManager &SM = BR.getSourceManager();
0136     clang::ento::PathDiagnosticLocation DLoc = clang::ento::PathDiagnosticLocation::createBegin(TD, SM);
0137     if (SM.isInSystemHeader(DLoc.asLocation()) || SM.isInExternCSystemHeader(DLoc.asLocation()))
0138       return;
0139 
0140     for (auto I = TD->spec_begin(), E = TD->spec_end(); I != E; ++I) {
0141       if (I->doesThisDeclarationHaveABody()) {
0142         clangcms::PEFWalker walker(this, BR, mgr.getAnalysisDeclContext(*I));
0143         walker.Visit(I->getBody());
0144       }
0145     }
0146     return;
0147   }
0148 
0149 }  // namespace clangcms