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 }