Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 10:05:56

0001 #include <clang/AST/Attr.h>
0002 #include <clang/AST/DeclCXX.h>
0003 #include <clang/AST/ExprCXX.h>
0004 #include <clang/AST/Expr.h>
0005 #include <clang/AST/Decl.h>
0006 #include <clang/AST/DeclTemplate.h>
0007 #include <clang/AST/StmtVisitor.h>
0008 #include <clang/AST/ParentMap.h>
0009 #include <clang/Analysis/CFGStmtMap.h>
0010 #include <clang/Analysis/CallGraph.h>
0011 #include <llvm/Support/SaveAndRestore.h>
0012 #include <clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h>
0013 #include <clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h>
0014 #include <clang/StaticAnalyzer/Core/Checker.h>
0015 #include <clang/StaticAnalyzer/Core/BugReporter/BugReporter.h>
0016 #include <clang/StaticAnalyzer/Core/BugReporter/BugType.h>
0017 #include <llvm/ADT/SmallString.h>
0018 #include "TrunCastChecker.h"
0019 #include "CmsSupport.h"
0020 
0021 using namespace clang;
0022 using namespace ento;
0023 using namespace llvm;
0024 
0025 namespace clangcms {
0026 
0027   class ICEVisitor : public clang::StmtVisitor<ICEVisitor> {
0028     const clang::ento::CheckerBase *Checker;
0029     clang::ento::BugReporter &BR;
0030     clang::AnalysisDeclContext *AC;
0031 
0032   public:
0033     ICEVisitor(const clang::ento::CheckerBase *checker, clang::ento::BugReporter &br, clang::AnalysisDeclContext *ac)
0034         : Checker(checker), BR(br), AC(ac) {}
0035 
0036     void VisitImplicitCastExpr(ImplicitCastExpr *CE);
0037     void VisitBinaryOperator(BinaryOperator *BO);
0038     void VisitChildren(clang::Stmt *S);
0039     void VisitStmt(clang::Stmt *S) { VisitChildren(S); }
0040   };
0041 
0042   void ICEVisitor::VisitChildren(clang::Stmt *S) {
0043     for (auto I = S->child_begin(), E = S->child_end(); I != E; ++I)
0044       if (clang::Stmt *child = *I) {
0045         Visit(child);
0046       }
0047   }
0048 
0049   void ICEVisitor::VisitBinaryOperator(BinaryOperator *BO) {
0050     const NamedDecl *ACD = dyn_cast_or_null<NamedDecl>(AC->getDecl());
0051     VisitChildren(BO);
0052     std::string ename = "EventNumber_t";
0053     clang::Expr *LHS = BO->getLHS();
0054     clang::Expr *RHS = BO->getRHS();
0055     if (!LHS || !RHS)
0056       return;
0057     std::string lname = LHS->getType().getAsString();
0058     std::string rname = RHS->getType().getAsString();
0059     if (IntegerLiteral::classof(LHS->IgnoreCasts()) || IntegerLiteral::classof(RHS->IgnoreCasts()))
0060       return;
0061     if (!(lname == ename || rname == ename))
0062       return;
0063     if (lname == ename && rname == ename)
0064       return;
0065     clang::QualType OTy;
0066     clang::QualType TTy;
0067     if (lname == ename && ImplicitCastExpr::classof(RHS)) {
0068       ImplicitCastExpr *ICE = dyn_cast_or_null<ImplicitCastExpr>(RHS);
0069       TTy = BR.getContext().getCanonicalType(LHS->getType());
0070       OTy = BR.getContext().getCanonicalType(ICE->getSubExprAsWritten()->getType());
0071     }
0072     if (rname == ename && ImplicitCastExpr::classof(LHS)) {
0073       ImplicitCastExpr *ICE = dyn_cast_or_null<ImplicitCastExpr>(LHS);
0074       TTy = BR.getContext().getCanonicalType(RHS->getType());
0075       OTy = BR.getContext().getCanonicalType(ICE->getSubExprAsWritten()->getType());
0076     }
0077     if (TTy.isNull() || OTy.isNull())
0078       return;
0079     QualType ToTy = TTy.getUnqualifiedType();
0080     QualType OrigTy = OTy.getUnqualifiedType();
0081     if (!(ToTy->isIntegerType() || ToTy->isFloatingType()))
0082       return;
0083     if (ToTy->isBooleanType())
0084       return;
0085     CharUnits size_otype = BR.getContext().getTypeSizeInChars(OrigTy);
0086     CharUnits size_ttype = BR.getContext().getTypeSizeInChars(ToTy);
0087     std::string oname = OrigTy.getAsString();
0088     std::string tname = ToTy.getAsString();
0089     if (ToTy->isFloatingType()) {
0090       llvm::SmallString<100> buf;
0091       llvm::raw_svector_ostream os(buf);
0092       os << "Cast-to type, " << tname << ". Cast-from type, " << oname << " . " << support::getQualifiedName(*(ACD));
0093       clang::ento::PathDiagnosticLocation CELoc =
0094           clang::ento::PathDiagnosticLocation::createBegin(BO, BR.getSourceManager(), AC);
0095       BR.EmitBasicReport(ACD,
0096                          CheckerNameRef(),
0097                          "implicit cast of int type to float type",
0098                          "CMS code rules",
0099                          os.str(),
0100                          CELoc,
0101                          BO->getSourceRange());
0102     }
0103     if ((size_otype > size_ttype)) {
0104       llvm::SmallString<100> buf;
0105       llvm::raw_svector_ostream os(buf);
0106       os << "Cast-to type, " << tname << ". Cast-from type, " << oname << ". Cast may result in truncation. "
0107          << support::getQualifiedName(*(ACD));
0108       clang::ento::PathDiagnosticLocation CELoc =
0109           clang::ento::PathDiagnosticLocation::createBegin(BO, BR.getSourceManager(), AC);
0110       BR.EmitBasicReport(ACD,
0111                          CheckerNameRef(),
0112                          "implicit cast of int type to smaller int type could truncate",
0113                          "CMS code rules",
0114                          os.str(),
0115                          CELoc,
0116                          BO->getSourceRange());
0117     }
0118     if ((size_otype == size_ttype) &&
0119         (ToTy->hasSignedIntegerRepresentation() && OrigTy->hasUnsignedIntegerRepresentation() ||
0120          ToTy->hasUnsignedIntegerRepresentation() && OrigTy->hasSignedIntegerRepresentation())) {
0121       llvm::SmallString<100> buf;
0122       llvm::raw_svector_ostream os(buf);
0123       os << "Cast-to type, " << tname << ". Cast-from type, " << oname << ". Changes int sign type. "
0124          << support::getQualifiedName(*(ACD));
0125       clang::ento::PathDiagnosticLocation CELoc =
0126           clang::ento::PathDiagnosticLocation::createBegin(BO, BR.getSourceManager(), AC);
0127       BR.EmitBasicReport(
0128           ACD, CheckerNameRef(), "implicit cast ins sign type", "CMS code rules", os.str(), CELoc, BO->getSourceRange());
0129     }
0130     return;
0131     return;
0132   }
0133 
0134   void ICEVisitor::VisitImplicitCastExpr(ImplicitCastExpr *CE) {
0135     const NamedDecl *ACD = dyn_cast<NamedDecl>(AC->getDecl());
0136     VisitChildren(CE);
0137     const Expr *SE = CE->getSubExprAsWritten();
0138     std::string sename = SE->getType().getAsString();
0139     const clang::Expr *E = CE->getSubExpr();
0140     if (!(sename == "EventNumber_t"))
0141       return;
0142     QualType OTy = BR.getContext().getCanonicalType(E->getType());
0143     QualType TTy = BR.getContext().getCanonicalType(CE->getType());
0144     QualType ToTy = TTy.getUnqualifiedType();
0145     QualType OrigTy = OTy.getUnqualifiedType();
0146     if (!(ToTy->isIntegerType() || ToTy->isFloatingType()))
0147       return;
0148     if (ToTy->isBooleanType())
0149       return;
0150     CharUnits size_otype = BR.getContext().getTypeSizeInChars(OrigTy);
0151     CharUnits size_ttype = BR.getContext().getTypeSizeInChars(ToTy);
0152     std::string oname = OrigTy.getAsString();
0153     std::string tname = ToTy.getAsString();
0154     if (ToTy->isFloatingType()) {
0155       llvm::SmallString<100> buf;
0156       llvm::raw_svector_ostream os(buf);
0157       os << "Cast-to type, " << tname << ". Cast-from type, " << oname << " . " << support::getQualifiedName(*(ACD));
0158       clang::ento::PathDiagnosticLocation CELoc =
0159           clang::ento::PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
0160       BR.EmitBasicReport(ACD,
0161                          CheckerNameRef(),
0162                          "implicit cast of int type to float type",
0163                          "CMS code rules",
0164                          os.str(),
0165                          CELoc,
0166                          CE->getSourceRange());
0167     }
0168     if ((size_otype > size_ttype)) {
0169       llvm::SmallString<100> buf;
0170       llvm::raw_svector_ostream os(buf);
0171       os << "Cast-to type, " << tname << ". Cast-from type, " << oname << ". Cast may result in truncation. "
0172          << support::getQualifiedName(*(ACD));
0173       clang::ento::PathDiagnosticLocation CELoc =
0174           clang::ento::PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
0175       BR.EmitBasicReport(ACD,
0176                          CheckerNameRef(),
0177                          "implicit cast of int type to smaller int type could truncate",
0178                          "CMS code rules",
0179                          os.str(),
0180                          CELoc,
0181                          CE->getSourceRange());
0182     }
0183     if (ToTy->hasSignedIntegerRepresentation() && OrigTy->hasUnsignedIntegerRepresentation() ||
0184         ToTy->hasUnsignedIntegerRepresentation() && OrigTy->hasSignedIntegerRepresentation()) {
0185       llvm::SmallString<100> buf;
0186       llvm::raw_svector_ostream os(buf);
0187       os << "Cast-to type, " << tname << ". Cast-from type, " << oname << ". Changes int sign type. "
0188          << support::getQualifiedName(*(ACD));
0189       clang::ento::PathDiagnosticLocation CELoc =
0190           clang::ento::PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
0191       BR.EmitBasicReport(ACD,
0192                          CheckerNameRef(),
0193                          "implicit cast changes int sign type",
0194                          "CMS code rules",
0195                          os.str(),
0196                          CELoc,
0197                          CE->getSourceRange());
0198     }
0199     return;
0200   }
0201 
0202   void TrunCastChecker::checkASTDecl(const CXXRecordDecl *D, AnalysisManager &Mgr, BugReporter &BR) const {
0203     for (auto I = D->method_begin(), E = D->method_end(); I != E; ++I) {
0204       if (!llvm::isa<clang::CXXMethodDecl>((*I)))
0205         continue;
0206       clang::CXXMethodDecl *MD = llvm::cast<clang::CXXMethodDecl>((*I)->getMostRecentDecl());
0207       if (!MD->hasBody())
0208         continue;
0209       clang::Stmt *Body = MD->getBody();
0210       ICEVisitor icevisitor(this, BR, Mgr.getAnalysisDeclContext(MD));
0211       icevisitor.Visit(Body);
0212     }
0213   }
0214 
0215 }  // namespace clangcms