File indexing completed on 2023-03-17 11:26:52
0001 #include "getByChecker.h"
0002 using namespace clang;
0003 using namespace ento;
0004 using namespace llvm;
0005
0006 namespace clangcms {
0007
0008 class Walker : public clang::StmtVisitor<Walker> {
0009 const CheckerBase *Checker;
0010 clang::ento::BugReporter &BR;
0011 clang::AnalysisDeclContext *AC;
0012
0013 public:
0014 Walker(const CheckerBase *checker, clang::ento::BugReporter &br, clang::AnalysisDeclContext *ac)
0015 : Checker(checker), BR(br), AC(ac) {}
0016
0017 void VisitChildren(clang::Stmt *S);
0018 void VisitStmt(clang::Stmt *S) { VisitChildren(S); }
0019 void VisitCXXMemberCallExpr(clang::CXXMemberCallExpr *CE);
0020 };
0021
0022 void Walker::VisitChildren(clang::Stmt *S) {
0023 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I != E; ++I)
0024 if (clang::Stmt *child = *I) {
0025 Visit(child);
0026 }
0027 }
0028
0029 void Walker::VisitCXXMemberCallExpr(CXXMemberCallExpr *CE) {
0030 LangOptions LangOpts;
0031 LangOpts.CPlusPlus = true;
0032 PrintingPolicy Policy(LangOpts);
0033 const Decl *D = AC->getDecl();
0034 std::string dname = "";
0035 if (const NamedDecl *ND = llvm::dyn_cast_or_null<NamedDecl>(D))
0036 dname = ND->getQualifiedNameAsString();
0037 CXXMethodDecl *MD = CE->getMethodDecl();
0038 if (!MD)
0039 return;
0040 std::string mname = MD->getQualifiedNameAsString();
0041 llvm::SmallString<100> buf;
0042 llvm::raw_svector_ostream os(buf);
0043 if (mname == "edm::Event::getByLabel" || mname == "edm::Event::getManyByType") {
0044 os << "function '";
0045 llvm::dyn_cast<CXXMethodDecl>(D)->getNameForDiagnostic(os, Policy, true);
0046 os << "' ";
0047 if (mname == "edm::Event::getByLabel") {
0048 os << "calls edm::Event::getByLabel with arguments '";
0049 QualType QT;
0050 for (auto I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
0051 QT = (*I)->getType();
0052 std::string qtname = QT.getCanonicalType().getAsString();
0053 if (qtname.substr(0, 17) == "class edm::Handle") {
0054
0055
0056
0057 const CXXRecordDecl *RD = QT->getAsCXXRecordDecl();
0058 std::string rname = RD->getQualifiedNameAsString();
0059 os << rname << " ";
0060 const ClassTemplateSpecializationDecl *SD = dyn_cast<ClassTemplateSpecializationDecl>(RD);
0061 for (unsigned J = 0, F = SD->getTemplateArgs().size(); J != F; ++J) {
0062 #if LLVM_VERSION_MAJOR >= 13
0063 SD->getTemplateArgs().data()[J].print(Policy, os, false);
0064 #else
0065 SD->getTemplateArgs().data()[J].print(Policy, os);
0066 #endif
0067 os << ", ";
0068 }
0069 } else {
0070 os << " " << qtname << " ";
0071 (*I)->printPretty(os, nullptr, Policy);
0072 os << ", ";
0073 }
0074 }
0075 os << "'\n";
0076 } else {
0077 os << "calls edm::Event::getManyByType with argument '";
0078 QualType QT = (*CE->arg_begin())->getType();
0079 const CXXRecordDecl *RD = QT->getAsCXXRecordDecl();
0080 os << "getManyByType , ";
0081 const ClassTemplateSpecializationDecl *SD = dyn_cast<ClassTemplateSpecializationDecl>(RD);
0082 const TemplateArgument TA = SD->getTemplateArgs().data()[0];
0083 const QualType AQT = TA.getAsType();
0084 const CXXRecordDecl *SRD = AQT->getAsCXXRecordDecl();
0085 os << SRD->getQualifiedNameAsString() << " ";
0086 const ClassTemplateSpecializationDecl *SVD = dyn_cast<ClassTemplateSpecializationDecl>(SRD);
0087 for (unsigned J = 0, F = SVD->getTemplateArgs().size(); J != F; ++J) {
0088 #if LLVM_VERSION_MAJOR >= 13
0089 SVD->getTemplateArgs().data()[J].print(Policy, os, false);
0090 #else
0091 SVD->getTemplateArgs().data()[J].print(Policy, os);
0092 #endif
0093 os << ", ";
0094 }
0095 }
0096
0097
0098 PathDiagnosticLocation CELoc = PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
0099 BugType *BT = new BugType(Checker, "edm::getByLabel or edm::getManyByType called", "Deprecated API");
0100 std::unique_ptr<BasicBugReport> R = std::make_unique<BasicBugReport>(*BT, llvm::StringRef(os.str()), CELoc);
0101 R->addRange(CE->getSourceRange());
0102 BR.emitReport(std::move(R));
0103 } else {
0104 for (auto I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
0105 QualType QT = (*I)->getType();
0106 std::string qtname = QT.getAsString();
0107
0108 if (qtname == "edm::Event" || qtname == "const edm::Event" || qtname == "edm::Event *" ||
0109 qtname == "const edm::Event *") {
0110 std::string tname;
0111 os << "function '" << dname << "' ";
0112 os << "calls '";
0113 MD->getNameForDiagnostic(os, Policy, true);
0114 os << "' with argument of type '" << qtname << "'\n";
0115 PathDiagnosticLocation CELoc = PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
0116 BugType *BT = new BugType(Checker, "function call with argument of type edm::Event", "Deprecated API");
0117 std::unique_ptr<BasicBugReport> R = std::make_unique<BasicBugReport>(*BT, llvm::StringRef(os.str()), CELoc);
0118 R->addRange(CE->getSourceRange());
0119 BR.emitReport(std::move(R));
0120 }
0121 }
0122 }
0123 }
0124
0125 void getByChecker::checkASTDecl(const CXXMethodDecl *MD, AnalysisManager &mgr, BugReporter &BR) const {
0126 const SourceManager &SM = BR.getSourceManager();
0127 PathDiagnosticLocation DLoc = PathDiagnosticLocation::createBegin(MD, SM);
0128 if (SM.isInSystemHeader(DLoc.asLocation()) || SM.isInExternCSystemHeader(DLoc.asLocation()))
0129 return;
0130 if (!MD->doesThisDeclarationHaveABody())
0131 return;
0132 clangcms::Walker walker(this, BR, mgr.getAnalysisDeclContext(MD));
0133 walker.Visit(MD->getBody());
0134 return;
0135 }
0136
0137 void getByChecker::checkASTDecl(const FunctionTemplateDecl *TD, AnalysisManager &mgr, BugReporter &BR) const {
0138 const clang::SourceManager &SM = BR.getSourceManager();
0139 clang::ento::PathDiagnosticLocation DLoc = clang::ento::PathDiagnosticLocation::createBegin(TD, SM);
0140 if (SM.isInSystemHeader(DLoc.asLocation()) || SM.isInExternCSystemHeader(DLoc.asLocation()))
0141 return;
0142
0143 for (auto I = TD->spec_begin(), E = TD->spec_end(); I != E; ++I) {
0144 if (I->doesThisDeclarationHaveABody()) {
0145 clangcms::Walker walker(this, BR, mgr.getAnalysisDeclContext(*I));
0146 walker.Visit(I->getBody());
0147 }
0148 }
0149 return;
0150 }
0151
0152 }