File indexing completed on 2024-10-08 23:10:07
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 assert(llvm::dyn_cast<CXXMethodDecl>(D));
0046 llvm::dyn_cast<CXXMethodDecl>(D)->getNameForDiagnostic(os, Policy, true);
0047 os << "' ";
0048 if (mname == "edm::Event::getByLabel") {
0049 os << "calls edm::Event::getByLabel with arguments '";
0050 QualType QT;
0051 for (auto I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
0052 QT = (*I)->getType();
0053 std::string qtname = QT.getCanonicalType().getAsString();
0054 if (qtname.substr(0, 17) == "class edm::Handle") {
0055
0056
0057
0058 const CXXRecordDecl *RD = QT->getAsCXXRecordDecl();
0059 std::string rname = RD->getQualifiedNameAsString();
0060 os << rname << " ";
0061 const ClassTemplateSpecializationDecl *SD = dyn_cast<ClassTemplateSpecializationDecl>(RD);
0062 assert(SD);
0063 for (unsigned J = 0, F = SD->getTemplateArgs().size(); J != F; ++J) {
0064 #if LLVM_VERSION_MAJOR >= 13
0065 SD->getTemplateArgs().data()[J].print(Policy, os, false);
0066 #else
0067 SD->getTemplateArgs().data()[J].print(Policy, os);
0068 #endif
0069 os << ", ";
0070 }
0071 } else {
0072 os << " " << qtname << " ";
0073 (*I)->printPretty(os, nullptr, Policy);
0074 os << ", ";
0075 }
0076 }
0077 os << "'\n";
0078 } else {
0079 os << "calls edm::Event::getManyByType with argument '";
0080 QualType QT = (*CE->arg_begin())->getType();
0081 const CXXRecordDecl *RD = QT->getAsCXXRecordDecl();
0082 os << "getManyByType , ";
0083 const ClassTemplateSpecializationDecl *SD = dyn_cast<ClassTemplateSpecializationDecl>(RD);
0084 assert(SD);
0085 const TemplateArgument TA = SD->getTemplateArgs().data()[0];
0086 const QualType AQT = TA.getAsType();
0087 const CXXRecordDecl *SRD = AQT->getAsCXXRecordDecl();
0088 os << SRD->getQualifiedNameAsString() << " ";
0089 const ClassTemplateSpecializationDecl *SVD = dyn_cast<ClassTemplateSpecializationDecl>(SRD);
0090 for (unsigned J = 0, F = SVD->getTemplateArgs().size(); J != F; ++J) {
0091 #if LLVM_VERSION_MAJOR >= 13
0092 SVD->getTemplateArgs().data()[J].print(Policy, os, false);
0093 #else
0094 SVD->getTemplateArgs().data()[J].print(Policy, os);
0095 #endif
0096 os << ", ";
0097 }
0098 }
0099
0100
0101 PathDiagnosticLocation CELoc = PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
0102 BugType *BT = new BugType(Checker, "edm::getByLabel or edm::getManyByType called", "Deprecated API");
0103 std::unique_ptr<BasicBugReport> R = std::make_unique<BasicBugReport>(*BT, llvm::StringRef(os.str()), CELoc);
0104 R->addRange(CE->getSourceRange());
0105 BR.emitReport(std::move(R));
0106 } else {
0107 for (auto I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
0108 QualType QT = (*I)->getType();
0109 std::string qtname = QT.getAsString();
0110
0111 if (qtname == "edm::Event" || qtname == "const edm::Event" || qtname == "edm::Event *" ||
0112 qtname == "const edm::Event *") {
0113 std::string tname;
0114 os << "function '" << dname << "' ";
0115 os << "calls '";
0116 MD->getNameForDiagnostic(os, Policy, true);
0117 os << "' with argument of type '" << qtname << "'\n";
0118 PathDiagnosticLocation CELoc = PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
0119 BugType *BT = new BugType(Checker, "function call with argument of type edm::Event", "Deprecated API");
0120 std::unique_ptr<BasicBugReport> R = std::make_unique<BasicBugReport>(*BT, llvm::StringRef(os.str()), CELoc);
0121 R->addRange(CE->getSourceRange());
0122 BR.emitReport(std::move(R));
0123 }
0124 }
0125 }
0126 }
0127
0128 void getByChecker::checkASTDecl(const CXXMethodDecl *MD, AnalysisManager &mgr, BugReporter &BR) const {
0129 const SourceManager &SM = BR.getSourceManager();
0130 PathDiagnosticLocation DLoc = PathDiagnosticLocation::createBegin(MD, SM);
0131 if (SM.isInSystemHeader(DLoc.asLocation()) || SM.isInExternCSystemHeader(DLoc.asLocation()))
0132 return;
0133 if (!MD->doesThisDeclarationHaveABody())
0134 return;
0135 clangcms::Walker walker(this, BR, mgr.getAnalysisDeclContext(MD));
0136 walker.Visit(MD->getBody());
0137 return;
0138 }
0139
0140 void getByChecker::checkASTDecl(const FunctionTemplateDecl *TD, AnalysisManager &mgr, BugReporter &BR) const {
0141 const clang::SourceManager &SM = BR.getSourceManager();
0142 clang::ento::PathDiagnosticLocation DLoc = clang::ento::PathDiagnosticLocation::createBegin(TD, SM);
0143 if (SM.isInSystemHeader(DLoc.asLocation()) || SM.isInExternCSystemHeader(DLoc.asLocation()))
0144 return;
0145
0146 for (auto I = TD->spec_begin(), E = TD->spec_end(); I != E; ++I) {
0147 if (I->doesThisDeclarationHaveABody()) {
0148 clangcms::Walker walker(this, BR, mgr.getAnalysisDeclContext(*I));
0149 walker.Visit(I->getBody());
0150 }
0151 }
0152 return;
0153 }
0154
0155 }