/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
Utilities/StaticAnalyzers/src/TrunCastChecker.cpp
215 строк
9 KB
Shahzad Malik Muzaffar
sync back llvm10 changes
25 май 2020, 09:57
25 май 2020, 09:57
df26429
Код
Авторство
О чём код?
#include <clang/AST/Attr.h> #include <clang/AST/DeclCXX.h> #include <clang/AST/ExprCXX.h> #include <clang/AST/Expr.h> #include <clang/AST/Decl.h> #include <clang/AST/DeclTemplate.h> #include <clang/AST/StmtVisitor.h> #include <clang/AST/ParentMap.h> #include <clang/Analysis/CFGStmtMap.h> #include <clang/Analysis/CallGraph.h> #include <llvm/Support/SaveAndRestore.h> #include <clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h> #include <clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h> #include <clang/StaticAnalyzer/Core/Checker.h> #include <clang/StaticAnalyzer/Core/BugReporter/BugReporter.h> #include <clang/StaticAnalyzer/Core/BugReporter/BugType.h> #include <llvm/ADT/SmallString.h> #include "TrunCastChecker.h" #include "CmsSupport.h" using namespace clang; using namespace ento; using namespace llvm; namespace clangcms { class ICEVisitor : public clang::StmtVisitor<ICEVisitor> { const clang::ento::CheckerBase *Checker; clang::ento::BugReporter &BR; clang::AnalysisDeclContext *AC; public: ICEVisitor(const clang::ento::CheckerBase *checker, clang::ento::BugReporter &br, clang::AnalysisDeclContext *ac) : Checker(checker), BR(br), AC(ac) {} void VisitImplicitCastExpr(ImplicitCastExpr *CE); void VisitBinaryOperator(BinaryOperator *BO); void VisitChildren(clang::Stmt *S); void VisitStmt(clang::Stmt *S) { VisitChildren(S); } }; void ICEVisitor::VisitChildren(clang::Stmt *S) { for (auto I = S->child_begin(), E = S->child_end(); I != E; ++I) if (clang::Stmt *child = *I) { Visit(child); } } void ICEVisitor::VisitBinaryOperator(BinaryOperator *BO) { const NamedDecl *ACD = dyn_cast_or_null<NamedDecl>(AC->getDecl()); VisitChildren(BO); std::string ename = "EventNumber_t"; clang::Expr *LHS = BO->getLHS(); clang::Expr *RHS = BO->getRHS(); if (!LHS || !RHS) return; std::string lname = LHS->getType().getAsString(); std::string rname = RHS->getType().getAsString(); if (IntegerLiteral::classof(LHS->IgnoreCasts()) || IntegerLiteral::classof(RHS->IgnoreCasts())) return; if (!(lname == ename || rname == ename)) return; if (lname == ename && rname == ename) return; clang::QualType OTy; clang::QualType TTy; if (lname == ename && ImplicitCastExpr::classof(RHS)) { ImplicitCastExpr *ICE = dyn_cast_or_null<ImplicitCastExpr>(RHS); TTy = BR.getContext().getCanonicalType(LHS->getType()); OTy = BR.getContext().getCanonicalType(ICE->getSubExprAsWritten()->getType()); } if (rname == ename && ImplicitCastExpr::classof(LHS)) { ImplicitCastExpr *ICE = dyn_cast_or_null<ImplicitCastExpr>(LHS); TTy = BR.getContext().getCanonicalType(RHS->getType()); OTy = BR.getContext().getCanonicalType(ICE->getSubExprAsWritten()->getType()); } if (TTy.isNull() || OTy.isNull()) return; QualType ToTy = TTy.getUnqualifiedType(); QualType OrigTy = OTy.getUnqualifiedType(); if (!(ToTy->isIntegerType() || ToTy->isFloatingType())) return; if (ToTy->isBooleanType()) return; CharUnits size_otype = BR.getContext().getTypeSizeInChars(OrigTy); CharUnits size_ttype = BR.getContext().getTypeSizeInChars(ToTy); std::string oname = OrigTy.getAsString(); std::string tname = ToTy.getAsString(); if (ToTy->isFloatingType()) { llvm::SmallString<100> buf; llvm::raw_svector_ostream os(buf); os << "Cast-to type, " << tname << ". Cast-from type, " << oname << " . " << support::getQualifiedName(*(ACD)); clang::ento::PathDiagnosticLocation CELoc = clang::ento::PathDiagnosticLocation::createBegin(BO, BR.getSourceManager(), AC); BR.EmitBasicReport(ACD, CheckerNameRef(), "implicit cast of int type to float type", "CMS code rules", os.str(), CELoc, BO->getSourceRange()); } if ((size_otype > size_ttype)) { llvm::SmallString<100> buf; llvm::raw_svector_ostream os(buf); os << "Cast-to type, " << tname << ". Cast-from type, " << oname << ". Cast may result in truncation. " << support::getQualifiedName(*(ACD)); clang::ento::PathDiagnosticLocation CELoc = clang::ento::PathDiagnosticLocation::createBegin(BO, BR.getSourceManager(), AC); BR.EmitBasicReport(ACD, CheckerNameRef(), "implicit cast of int type to smaller int type could truncate", "CMS code rules", os.str(), CELoc, BO->getSourceRange()); } if ((size_otype == size_ttype) && (ToTy->hasSignedIntegerRepresentation() && OrigTy->hasUnsignedIntegerRepresentation() || ToTy->hasUnsignedIntegerRepresentation() && OrigTy->hasSignedIntegerRepresentation())) { llvm::SmallString<100> buf; llvm::raw_svector_ostream os(buf); os << "Cast-to type, " << tname << ". Cast-from type, " << oname << ". Changes int sign type. " << support::getQualifiedName(*(ACD)); clang::ento::PathDiagnosticLocation CELoc = clang::ento::PathDiagnosticLocation::createBegin(BO, BR.getSourceManager(), AC); BR.EmitBasicReport( ACD, CheckerNameRef(), "implicit cast ins sign type", "CMS code rules", os.str(), CELoc, BO->getSourceRange()); } return; return; } void ICEVisitor::VisitImplicitCastExpr(ImplicitCastExpr *CE) { const NamedDecl *ACD = dyn_cast<NamedDecl>(AC->getDecl()); VisitChildren(CE); const Expr *SE = CE->getSubExprAsWritten(); std::string sename = SE->getType().getAsString(); const clang::Expr *E = CE->getSubExpr(); if (!(sename == "EventNumber_t")) return; QualType OTy = BR.getContext().getCanonicalType(E->getType()); QualType TTy = BR.getContext().getCanonicalType(CE->getType()); QualType ToTy = TTy.getUnqualifiedType(); QualType OrigTy = OTy.getUnqualifiedType(); if (!(ToTy->isIntegerType() || ToTy->isFloatingType())) return; if (ToTy->isBooleanType()) return; CharUnits size_otype = BR.getContext().getTypeSizeInChars(OrigTy); CharUnits size_ttype = BR.getContext().getTypeSizeInChars(ToTy); std::string oname = OrigTy.getAsString(); std::string tname = ToTy.getAsString(); if (ToTy->isFloatingType()) { llvm::SmallString<100> buf; llvm::raw_svector_ostream os(buf); os << "Cast-to type, " << tname << ". Cast-from type, " << oname << " . " << support::getQualifiedName(*(ACD)); clang::ento::PathDiagnosticLocation CELoc = clang::ento::PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); BR.EmitBasicReport(ACD, CheckerNameRef(), "implicit cast of int type to float type", "CMS code rules", os.str(), CELoc, CE->getSourceRange()); } if ((size_otype > size_ttype)) { llvm::SmallString<100> buf; llvm::raw_svector_ostream os(buf); os << "Cast-to type, " << tname << ". Cast-from type, " << oname << ". Cast may result in truncation. " << support::getQualifiedName(*(ACD)); clang::ento::PathDiagnosticLocation CELoc = clang::ento::PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); BR.EmitBasicReport(ACD, CheckerNameRef(), "implicit cast of int type to smaller int type could truncate", "CMS code rules", os.str(), CELoc, CE->getSourceRange()); } if (ToTy->hasSignedIntegerRepresentation() && OrigTy->hasUnsignedIntegerRepresentation() || ToTy->hasUnsignedIntegerRepresentation() && OrigTy->hasSignedIntegerRepresentation()) { llvm::SmallString<100> buf; llvm::raw_svector_ostream os(buf); os << "Cast-to type, " << tname << ". Cast-from type, " << oname << ". Changes int sign type. " << support::getQualifiedName(*(ACD)); clang::ento::PathDiagnosticLocation CELoc = clang::ento::PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); BR.EmitBasicReport(ACD, CheckerNameRef(), "implicit cast changes int sign type", "CMS code rules", os.str(), CELoc, CE->getSourceRange()); } return; } void TrunCastChecker::checkASTDecl(const CXXRecordDecl *D, AnalysisManager &Mgr, BugReporter &BR) const { for (auto I = D->method_begin(), E = D->method_end(); I != E; ++I) { if (!llvm::isa<clang::CXXMethodDecl>((*I))) continue; clang::CXXMethodDecl *MD = llvm::cast<clang::CXXMethodDecl>((*I)->getMostRecentDecl()); if (!MD->hasBody()) continue; clang::Stmt *Body = MD->getBody(); ICEVisitor icevisitor(this, BR, Mgr.getAnalysisDeclContext(MD)); icevisitor.Visit(Body); } } } // namespace clangcms