diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp | 120 |
1 files changed, 62 insertions, 58 deletions
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp index ec2a88a..901af43 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp @@ -50,7 +50,7 @@ void ReachableCode::computeReachableBlocks() { if (!cfg.getNumBlockIDs()) return; - llvm::SmallVector<const CFGBlock*, 10> worklist; + SmallVector<const CFGBlock*, 10> worklist; worklist.push_back(&cfg.getEntry()); while (!worklist.empty()) { @@ -68,12 +68,13 @@ void ReachableCode::computeReachableBlocks() { } namespace { -class DeadStoreObs : public LiveVariables::ObserverTy { +class DeadStoreObs : public LiveVariables::Observer { const CFG &cfg; ASTContext &Ctx; BugReporter& BR; + AnalysisContext* AC; ParentMap& Parents; - llvm::SmallPtrSet<VarDecl*, 20> Escaped; + llvm::SmallPtrSet<const VarDecl*, 20> Escaped; llvm::OwningPtr<ReachableCode> reachableCode; const CFGBlock *currentBlock; @@ -81,14 +82,15 @@ class DeadStoreObs : public LiveVariables::ObserverTy { public: DeadStoreObs(const CFG &cfg, ASTContext &ctx, - BugReporter& br, ParentMap& parents, - llvm::SmallPtrSet<VarDecl*, 20> &escaped) - : cfg(cfg), Ctx(ctx), BR(br), Parents(parents), + BugReporter& br, AnalysisContext* ac, ParentMap& parents, + llvm::SmallPtrSet<const VarDecl*, 20> &escaped) + : cfg(cfg), Ctx(ctx), BR(br), AC(ac), Parents(parents), Escaped(escaped), currentBlock(0) {} virtual ~DeadStoreObs() {} - void Report(VarDecl* V, DeadStoreKind dsk, SourceLocation L, SourceRange R) { + void Report(const VarDecl *V, DeadStoreKind dsk, + PathDiagnosticLocation L, SourceRange R) { if (Escaped.count(V)) return; @@ -102,26 +104,25 @@ public: if (!reachableCode->isReachable(currentBlock)) return; - const std::string &name = V->getNameAsString(); - - const char* BugType = 0; - std::string msg; + llvm::SmallString<64> buf; + llvm::raw_svector_ostream os(buf); + const char *BugType = 0; switch (dsk) { default: - assert(false && "Impossible dead store type."); + llvm_unreachable("Impossible dead store type."); case DeadInit: BugType = "Dead initialization"; - msg = "Value stored to '" + name + - "' during its initialization is never read"; + os << "Value stored to '" << *V + << "' during its initialization is never read"; break; case DeadIncrement: BugType = "Dead increment"; case Standard: if (!BugType) BugType = "Dead assignment"; - msg = "Value stored to '" + name + "' is never read"; + os << "Value stored to '" << *V << "' is never read"; break; case Enclosing: @@ -131,13 +132,12 @@ public: return; } - BR.EmitBasicReport(BugType, "Dead store", msg, L, R); + BR.EmitBasicReport(BugType, "Dead store", os.str(), L, R); } - void CheckVarDecl(VarDecl* VD, Expr* Ex, Expr* Val, + void CheckVarDecl(const VarDecl *VD, const Expr *Ex, const Expr *Val, DeadStoreKind dsk, - const LiveVariables::AnalysisDataTy& AD, - const LiveVariables::ValTy& Live) { + const LiveVariables::LivenessValues &Live) { if (!VD->hasLocalStorage()) return; @@ -146,30 +146,32 @@ public: if (VD->getType()->getAs<ReferenceType>()) return; - if (!Live(VD, AD) && - !(VD->getAttr<UnusedAttr>() || VD->getAttr<BlocksAttr>())) - Report(VD, dsk, Ex->getSourceRange().getBegin(), - Val->getSourceRange()); + if (!Live.isLive(VD) && + !(VD->getAttr<UnusedAttr>() || VD->getAttr<BlocksAttr>())) { + + PathDiagnosticLocation ExLoc = + PathDiagnosticLocation::createBegin(Ex, BR.getSourceManager(), AC); + Report(VD, dsk, ExLoc, Val->getSourceRange()); + } } - void CheckDeclRef(DeclRefExpr* DR, Expr* Val, DeadStoreKind dsk, - const LiveVariables::AnalysisDataTy& AD, - const LiveVariables::ValTy& Live) { - if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) - CheckVarDecl(VD, DR, Val, dsk, AD, Live); + void CheckDeclRef(const DeclRefExpr *DR, const Expr *Val, DeadStoreKind dsk, + const LiveVariables::LivenessValues& Live) { + if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) + CheckVarDecl(VD, DR, Val, dsk, Live); } - bool isIncrement(VarDecl* VD, BinaryOperator* B) { + bool isIncrement(VarDecl *VD, const BinaryOperator* B) { if (B->isCompoundAssignmentOp()) return true; - Expr* RHS = B->getRHS()->IgnoreParenCasts(); - BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS); + const Expr *RHS = B->getRHS()->IgnoreParenCasts(); + const BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS); if (!BRHS) return false; - DeclRefExpr *DR; + const DeclRefExpr *DR; if ((DR = dyn_cast<DeclRefExpr>(BRHS->getLHS()->IgnoreParenCasts()))) if (DR->getDecl() == VD) @@ -182,9 +184,8 @@ public: return false; } - virtual void ObserveStmt(Stmt* S, const CFGBlock *block, - const LiveVariables::AnalysisDataTy& AD, - const LiveVariables::ValTy& Live) { + virtual void observeStmt(const Stmt *S, const CFGBlock *block, + const LiveVariables::LivenessValues &Live) { currentBlock = block; @@ -194,10 +195,10 @@ public: // Only cover dead stores from regular assignments. ++/-- dead stores // have never flagged a real bug. - if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { + if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { if (!B->isAssignmentOp()) return; // Skip non-assignments. - if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS())) + if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(B->getLHS())) if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { // Special case: check for assigning null to a pointer. // This is a common form of defensive programming. @@ -208,10 +209,10 @@ public: return; } - Expr* RHS = B->getRHS()->IgnoreParenCasts(); + Expr *RHS = B->getRHS()->IgnoreParenCasts(); // Special case: self-assignments. These are often used to shut up // "unused variable" compiler warnings. - if (DeclRefExpr* RhsDR = dyn_cast<DeclRefExpr>(RHS)) + if (DeclRefExpr *RhsDR = dyn_cast<DeclRefExpr>(RHS)) if (VD == dyn_cast<VarDecl>(RhsDR->getDecl())) return; @@ -220,29 +221,29 @@ public: ? Enclosing : (isIncrement(VD,B) ? DeadIncrement : Standard); - CheckVarDecl(VD, DR, B->getRHS(), dsk, AD, Live); + CheckVarDecl(VD, DR, B->getRHS(), dsk, Live); } } - else if (UnaryOperator* U = dyn_cast<UnaryOperator>(S)) { + else if (const UnaryOperator* U = dyn_cast<UnaryOperator>(S)) { if (!U->isIncrementOp() || U->isPrefix()) return; - Stmt *parent = Parents.getParentIgnoreParenCasts(U); + const Stmt *parent = Parents.getParentIgnoreParenCasts(U); if (!parent || !isa<ReturnStmt>(parent)) return; - Expr *Ex = U->getSubExpr()->IgnoreParenCasts(); + const Expr *Ex = U->getSubExpr()->IgnoreParenCasts(); - if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(Ex)) - CheckDeclRef(DR, U, DeadIncrement, AD, Live); + if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) + CheckDeclRef(DR, U, DeadIncrement, Live); } - else if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) + else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) // Iterate through the decls. Warn if any initializers are complex // expressions that are not live (never used). - for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE=DS->decl_end(); + for (DeclStmt::const_decl_iterator DI=DS->decl_begin(), DE=DS->decl_end(); DI != DE; ++DI) { - VarDecl* V = dyn_cast<VarDecl>(*DI); + VarDecl *V = dyn_cast<VarDecl>(*DI); if (!V) continue; @@ -253,7 +254,7 @@ public: if (V->getType()->getAs<ReferenceType>()) return; - if (Expr* E = V->getInit()) { + if (Expr *E = V->getInit()) { while (ExprWithCleanups *exprClean = dyn_cast<ExprWithCleanups>(E)) E = exprClean->getSubExpr(); @@ -265,7 +266,7 @@ public: // A dead initialization is a variable that is dead after it // is initialized. We don't flag warnings for those variables // marked 'unused'. - if (!Live(V, AD) && V->getAttr<UnusedAttr>() == 0) { + if (!Live.isLive(V) && V->getAttr<UnusedAttr>() == 0) { // Special case: check for initializations with constants. // // e.g. : int x = 0; @@ -296,7 +297,9 @@ public: return; } - Report(V, DeadInit, V->getLocation(), E->getSourceRange()); + PathDiagnosticLocation Loc = + PathDiagnosticLocation::create(V, BR.getSourceManager()); + Report(V, DeadInit, Loc, E->getSourceRange()); } } } @@ -318,15 +321,15 @@ public: CFG& getCFG() { return *cfg; } - llvm::SmallPtrSet<VarDecl*, 20> Escaped; + llvm::SmallPtrSet<const VarDecl*, 20> Escaped; void VisitUnaryOperator(UnaryOperator* U) { // Check for '&'. Any VarDecl whose value has its address-taken we // treat as escaped. - Expr* E = U->getSubExpr()->IgnoreParenCasts(); + Expr *E = U->getSubExpr()->IgnoreParenCasts(); if (U->getOpcode() == UO_AddrOf) - if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E)) - if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) { + if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) + if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { Escaped.insert(VD); return; } @@ -345,13 +348,14 @@ class DeadStoresChecker : public Checker<check::ASTCodeBody> { public: void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, BugReporter &BR) const { - if (LiveVariables *L = mgr.getLiveVariables(D)) { + if (LiveVariables *L = mgr.getAnalysis<LiveVariables>(D)) { CFG &cfg = *mgr.getCFG(D); + AnalysisContext *AC = mgr.getAnalysisContext(D); ParentMap &pmap = mgr.getParentMap(D); FindEscaped FS(&cfg); FS.getCFG().VisitBlockStmts(FS); - DeadStoreObs A(cfg, BR.getContext(), BR, pmap, FS.Escaped); - L->runOnAllBlocks(cfg, &A); + DeadStoreObs A(cfg, BR.getContext(), BR, AC, pmap, FS.Escaped); + L->runOnAllBlocks(A); } } }; |