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 }