Back to home page

Project CMSSW displayed by LXR

 
 

    


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             //                  os<<"argument name '";
0056             //                  (*I)->printPretty(os,0,Policy);
0057             //                  os<<"' ";
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       //            llvm::errs()<<os.str()<<"\n";
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         //          if (qtname.find(" edm::Event") != std::string::npos ) llvm::errs()<<"arg type '" << qtname <<"'\n";
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 }  // namespace clangcms