Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:31:50

0001 #include <clang/AST/DeclCXX.h>
0002 #include <clang/AST/ExprCXX.h>
0003 #include <clang/AST/Decl.h>
0004 #include <clang/AST/DeclTemplate.h>
0005 #include <clang/AST/StmtVisitor.h>
0006 #include <clang/AST/ParentMap.h>
0007 #include <clang/Analysis/CFGStmtMap.h>
0008 #include <clang/Analysis/CallGraph.h>
0009 #include <llvm/Support/SaveAndRestore.h>
0010 #include <clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h>
0011 #include <clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h>
0012 #include <clang/StaticAnalyzer/Core/Checker.h>
0013 #include <clang/StaticAnalyzer/Core/BugReporter/BugReporter.h>
0014 #include <clang/StaticAnalyzer/Core/BugReporter/BugType.h>
0015 #include <llvm/ADT/SmallString.h>
0016 #include <clang/AST/DeclTemplate.h>
0017 #include <iostream>
0018 #include <fstream>
0019 #include <iterator>
0020 #include <string>
0021 #include <algorithm>
0022 #include "CmsException.h"
0023 #include "CmsSupport.h"
0024 #include "FunctionDumper.h"
0025 
0026 using namespace clang;
0027 using namespace ento;
0028 using namespace llvm;
0029 
0030 namespace clangcms {
0031 
0032   class FDumper : public clang::StmtVisitor<FDumper> {
0033     clang::ento::BugReporter &BR;
0034     clang::AnalysisDeclContext *AC;
0035     const FunctionDecl *AD;
0036 
0037     enum Kind { NotVisited, Visited };
0038 
0039     /// A DenseMap that records visited states of CallExpr.
0040     llvm::DenseMap<const clang::Expr *, Kind> VisitedExpr;
0041 
0042   public:
0043     FDumper(clang::ento::BugReporter &br, clang::AnalysisDeclContext *ac, const FunctionDecl *fd)
0044         : BR(br), AC(ac), AD(fd) {}
0045 
0046     /// This method adds a CallExpr to the worklist
0047     void setVisited(Expr *E) {
0048       Kind &K = VisitedExpr[E];
0049       if (K = NotVisited) {
0050         VisitedExpr[E] = Visited;
0051         return;
0052       }
0053     }
0054 
0055     bool wasVisited(Expr *E) {
0056       Kind &K = VisitedExpr[E];
0057       if (K = Visited)
0058         return true;
0059       return false;
0060     }
0061 
0062     const clang::Stmt *ParentStmt(const Stmt *S) {
0063       const Stmt *P = AC->getParentMap().getParentIgnoreParens(S);
0064       if (!P)
0065         return nullptr;
0066       return P;
0067     }
0068 
0069     void fixAnonNS(std::string &name) {
0070       const std::string anon_ns = "(anonymous namespace)";
0071       if (name.substr(0, anon_ns.size()) == anon_ns) {
0072         const char *fname = BR.getSourceManager().getPresumedLoc(AD->getLocation()).getFilename();
0073         const char *sname = "/src/";
0074         const char *filename = std::strstr(fname, sname);
0075         if (filename != nullptr)
0076           name = name.substr(0, anon_ns.size() - 1) + " in " + filename + ")" + name.substr(anon_ns.size());
0077       }
0078       return;
0079     }
0080 
0081     void VisitChildren(clang::Stmt *S);
0082     void VisitStmt(clang::Stmt *S) { VisitChildren(S); }
0083     void VisitCallExpr(CallExpr *CE);
0084     void VisitCXXMemberCallExpr(CXXMemberCallExpr *CXE);
0085     void VisitCXXConstructExpr(CXXConstructExpr *CCE);
0086   };
0087 
0088   void FDumper::VisitChildren(clang::Stmt *S) {
0089     for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I != E; ++I)
0090       if (clang::Stmt *child = *I) {
0091         Visit(child);
0092       }
0093   }
0094 
0095   void FDumper::VisitCXXConstructExpr(CXXConstructExpr *CCE) {
0096     std::string buf;
0097     llvm::raw_string_ostream os(buf);
0098     LangOptions LangOpts;
0099     LangOpts.CPlusPlus = true;
0100     PrintingPolicy Policy(LangOpts);
0101     std::string mdname = support::getQualifiedName(*AD);
0102     fixAnonNS(mdname);
0103     CXXConstructorDecl *CCD = CCE->getConstructor();
0104     if (!CCD)
0105       return;
0106     const char *sfile = BR.getSourceManager().getPresumedLoc(CCE->getExprLoc()).getFilename();
0107     std::string sname(sfile);
0108     if (!support::isInterestingLocation(sname))
0109       return;
0110     std::string mname;
0111     mname = support::getQualifiedName(*CCD);
0112     fixAnonNS(mname);
0113     std::string tname = "function-dumper.txt.unsorted";
0114     std::string ostring = "function '" + mdname + "' " + "calls function '" + mname + "'\n";
0115     support::writeLog(ostring, tname);
0116 
0117     VisitChildren(CCE);
0118   }
0119 
0120   void FDumper::VisitCXXMemberCallExpr(CXXMemberCallExpr *CXE) {
0121     std::string buf;
0122     llvm::raw_string_ostream os(buf);
0123     LangOptions LangOpts;
0124     LangOpts.CPlusPlus = true;
0125     PrintingPolicy Policy(LangOpts);
0126     std::string mdname = support::getQualifiedName(*AD);
0127     fixAnonNS(mdname);
0128     CXXMethodDecl *MD = CXE->getMethodDecl();
0129     if (!MD)
0130       return;
0131     const char *sfile = BR.getSourceManager().getPresumedLoc(CXE->getExprLoc()).getFilename();
0132     std::string sname(sfile);
0133     if (!support::isInterestingLocation(sname))
0134       return;
0135     std::string mname;
0136     mname = support::getQualifiedName(*MD);
0137     fixAnonNS(mname);
0138     std::string tname = "function-dumper.txt.unsorted";
0139     std::string ostring;
0140     ostring = "function '" + mdname + "' " + "calls function '" + mname + "'\n";
0141     support::writeLog(ostring, tname);
0142 
0143     VisitChildren(CXE);
0144   }
0145 
0146   void FDumper::VisitCallExpr(CallExpr *CE) {
0147     std::string buf;
0148     llvm::raw_string_ostream os(buf);
0149     LangOptions LangOpts;
0150     LangOpts.CPlusPlus = true;
0151     PrintingPolicy Policy(LangOpts);
0152     std::string mdname = support::getQualifiedName(*AD);
0153     fixAnonNS(mdname);
0154     FunctionDecl *FD = CE->getDirectCallee();
0155     if (!FD)
0156       return;
0157     const char *sfile = BR.getSourceManager().getPresumedLoc(CE->getExprLoc()).getFilename();
0158     std::string sname(sfile);
0159     if (!support::isInterestingLocation(sname))
0160       return;
0161     std::string mname;
0162     mname = support::getQualifiedName(*FD);
0163     fixAnonNS(mname);
0164     std::string tname = "function-dumper.txt.unsorted";
0165     std::string ostring;
0166     ostring = "function '" + mdname + "' " + "calls function '" + mname + "'\n";
0167     support::writeLog(ostring, tname);
0168 
0169     VisitChildren(CE);
0170   }
0171 
0172   void FunctionDumper::checkASTDecl(const CXXMethodDecl *MD, AnalysisManager &mgr, BugReporter &BR) const {
0173     if (MD->getLocation().isInvalid())
0174       return;
0175     const char *sfile = BR.getSourceManager().getPresumedLoc(MD->getLocation()).getFilename();
0176     std::string sname(sfile);
0177     if (!support::isInterestingLocation(sname))
0178       return;
0179     if (!support::isCmsLocalFile(sfile))
0180       return;
0181     if (!MD->doesThisDeclarationHaveABody())
0182       return;
0183     FDumper walker(BR, mgr.getAnalysisDeclContext(MD), MD);
0184     walker.Visit(MD->getBody());
0185     std::string mname = support::getQualifiedName(*MD);
0186     walker.fixAnonNS(mname);
0187     std::string tname = "function-dumper.txt.unsorted";
0188     for (auto I = MD->begin_overridden_methods(), E = MD->end_overridden_methods(); I != E; ++I) {
0189       std::string oname = support::getQualifiedName(*(*I));
0190       walker.fixAnonNS(oname);
0191       std::string ostring = "function '" + mname + "' " + "overrides function '" + oname + "'\n";
0192       support::writeLog(ostring, tname);
0193     }
0194     return;
0195   }
0196 
0197   void FunctionDumper::checkASTDecl(const FunctionDecl *MD, AnalysisManager &mgr, BugReporter &BR) const {
0198     if (MD->getLocation().isInvalid())
0199       return;
0200     const char *sfile = BR.getSourceManager().getPresumedLoc(MD->getLocation()).getFilename();
0201     std::string sname(sfile);
0202     if (!support::isInterestingLocation(sname))
0203       return;
0204     if (!support::isCmsLocalFile(sfile))
0205       return;
0206     if (!MD->doesThisDeclarationHaveABody())
0207       return;
0208     FDumper walker(BR, mgr.getAnalysisDeclContext(MD), MD);
0209     walker.Visit(MD->getBody());
0210     return;
0211   }
0212 
0213   void FunctionDumper::checkASTDecl(const FunctionTemplateDecl *TD, AnalysisManager &mgr, BugReporter &BR) const {
0214     if (TD->getLocation().isInvalid())
0215       return;
0216     const char *sfile = BR.getSourceManager().getPresumedLoc(TD->getLocation()).getFilename();
0217     std::string sname(sfile);
0218     if (!support::isInterestingLocation(sname))
0219       return;
0220     if (!support::isCmsLocalFile(sfile))
0221       return;
0222     for (auto I = TD->spec_begin(), E = TD->spec_end(); I != E; ++I) {
0223       if (I->doesThisDeclarationHaveABody()) {
0224         FDumper walker(BR, mgr.getAnalysisDeclContext(*I), (*I));
0225         walker.Visit(I->getBody());
0226       }
0227     }
0228     return;
0229   }
0230 
0231 }  // namespace clangcms