DeadStoresChecker.cpp revision cfa88f893915ceb8ae4ce2f17c46c24a4d67502f
156b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek//==- DeadStoresChecker.cpp - Check for stores to dead variables -*- C++ -*-==//
21ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//
31ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//                     The LLVM Compiler Infrastructure
41ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//
50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source
60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details.
71ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//
81ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//===----------------------------------------------------------------------===//
91ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//
10843e934ba8c6ebc00d2f6969a50af7074597e8e3Gabor Greif//  This file defines a DeadStores, a flow-sensitive checker that looks for
111ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//  stores to variables that are no longer live.
121ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//
131ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//===----------------------------------------------------------------------===//
141ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
157dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis#include "ClangSACheckers.h"
16ce1cab9fc0b4aec9cdef1b30a14e4ccdca3ac5f1Ted Kremenek#include "clang/AST/ASTContext.h"
172fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/AST/Attr.h"
181a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek#include "clang/AST/ParentMap.h"
192827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek#include "clang/AST/RecursiveASTVisitor.h"
2019948ac84f145b9ea576db2faefda1927c249e44Ted Kremenek#include "clang/Analysis/Analyses/LiveVariables.h"
2119948ac84f145b9ea576db2faefda1927c249e44Ted Kremenek#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
2219948ac84f145b9ea576db2faefda1927c249e44Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
2319948ac84f145b9ea576db2faefda1927c249e44Ted Kremenek#include "clang/StaticAnalyzer/Core/Checker.h"
2419948ac84f145b9ea576db2faefda1927c249e44Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
2519948ac84f145b9ea576db2faefda1927c249e44Ted Kremenek#include "llvm/ADT/BitVector.h"
268fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h"
272827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek#include "llvm/Support/SaveAndRestore.h"
281ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
291ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenekusing namespace clang;
309ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
311ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
322827f5af018c515986ffb1779ec2e7246988f150Ted Kremeneknamespace {
332827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek
342827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek/// A simple visitor to record what VarDecls occur in EH-handling code.
352827f5af018c515986ffb1779ec2e7246988f150Ted Kremenekclass EHCodeVisitor : public RecursiveASTVisitor<EHCodeVisitor> {
362827f5af018c515986ffb1779ec2e7246988f150Ted Kremenekpublic:
372827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  bool inEH;
382827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  llvm::DenseSet<const VarDecl *> &S;
392827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek
402827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  bool TraverseObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
412827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    SaveAndRestore<bool> inFinally(inEH, true);
422827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    return ::RecursiveASTVisitor<EHCodeVisitor>::TraverseObjCAtFinallyStmt(S);
432827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  }
442827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek
452827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  bool TraverseObjCAtCatchStmt(ObjCAtCatchStmt *S) {
462827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    SaveAndRestore<bool> inCatch(inEH, true);
472827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    return ::RecursiveASTVisitor<EHCodeVisitor>::TraverseObjCAtCatchStmt(S);
482827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  }
492827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek
502827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  bool TraverseCXXCatchStmt(CXXCatchStmt *S) {
512827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    SaveAndRestore<bool> inCatch(inEH, true);
522827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    return TraverseStmt(S->getHandlerBlock());
532827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  }
542827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek
552827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  bool VisitDeclRefExpr(DeclRefExpr *DR) {
562827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    if (inEH)
572827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek      if (const VarDecl *D = dyn_cast<VarDecl>(DR->getDecl()))
582827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek        S.insert(D);
592827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    return true;
602827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  }
612827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek
622827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  EHCodeVisitor(llvm::DenseSet<const VarDecl *> &S) :
632827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  inEH(false), S(S) {}
642827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek};
651a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
66848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek// FIXME: Eventually migrate into its own file, and have it managed by
67848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek// AnalysisManager.
68848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenekclass ReachableCode {
69848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  const CFG &cfg;
70848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  llvm::BitVector reachable;
71848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenekpublic:
72848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  ReachableCode(const CFG &cfg)
73848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    : cfg(cfg), reachable(cfg.getNumBlockIDs(), false) {}
74848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
75848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  void computeReachableBlocks();
76848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
77848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  bool isReachable(const CFGBlock *block) const {
78848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    return reachable[block->getBlockID()];
79848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  }
80848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek};
81848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek}
82848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
83848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenekvoid ReachableCode::computeReachableBlocks() {
84848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  if (!cfg.getNumBlockIDs())
85848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    return;
86848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
875f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<const CFGBlock*, 10> worklist;
88848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  worklist.push_back(&cfg.getEntry());
89848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
90848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  while (!worklist.empty()) {
91848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    const CFGBlock *block = worklist.back();
92848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    worklist.pop_back();
93848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    llvm::BitVector::reference isReachable = reachable[block->getBlockID()];
94848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    if (isReachable)
95848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      continue;
96848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    isReachable = true;
97848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    for (CFGBlock::const_succ_iterator i = block->succ_begin(),
98848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek                                       e = block->succ_end(); i != e; ++i)
99848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      if (const CFGBlock *succ = *i)
100848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek        worklist.push_back(succ);
101848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  }
102848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek}
103848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
104bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenekstatic const Expr *LookThroughTransitiveAssignments(const Expr *Ex) {
105bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek  while (Ex) {
106bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek    const BinaryOperator *BO =
107bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek      dyn_cast<BinaryOperator>(Ex->IgnoreParenCasts());
108bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek    if (!BO)
109bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek      break;
110bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek    if (BO->getOpcode() == BO_Assign) {
111bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek      Ex = BO->getRHS();
112bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek      continue;
113bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek    }
114bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek    break;
115bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek  }
116bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek  return Ex;
117bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek}
118bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek
119848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremeneknamespace {
120882998923889a2fcce9b49696506c499e22cf38fTed Kremenekclass DeadStoreObs : public LiveVariables::Observer {
121848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  const CFG &cfg;
122c0508f9fe37a3afb1ccad39879348272545e55dbChris Lattner  ASTContext &Ctx;
1238f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek  BugReporter& BR;
1241d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek  AnalysisDeclContext* AC;
1251a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek  ParentMap& Parents;
126882998923889a2fcce9b49696506c499e22cf38fTed Kremenek  llvm::SmallPtrSet<const VarDecl*, 20> Escaped;
1276f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<ReachableCode> reachableCode;
128848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  const CFGBlock *currentBlock;
129cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  OwningPtr<llvm::DenseSet<const VarDecl *> > InEH;
1301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1312cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek  enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit };
1321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1331ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenekpublic:
134848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  DeadStoreObs(const CFG &cfg, ASTContext &ctx,
1351d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek               BugReporter& br, AnalysisDeclContext* ac, ParentMap& parents,
136882998923889a2fcce9b49696506c499e22cf38fTed Kremenek               llvm::SmallPtrSet<const VarDecl*, 20> &escaped)
137590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks    : cfg(cfg), Ctx(ctx), BR(br), AC(ac), Parents(parents),
138848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      Escaped(escaped), currentBlock(0) {}
1391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
140fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek  virtual ~DeadStoreObs() {}
141b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek
1422827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  bool isLive(const LiveVariables::LivenessValues &Live, const VarDecl *D) {
1432827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    if (Live.isLive(D))
1442827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek      return true;
1452827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    // Lazily construct the set that records which VarDecls are in
1462827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    // EH code.
1472827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    if (!InEH.get()) {
1482827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek      InEH.reset(new llvm::DenseSet<const VarDecl *>());
1492827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek      EHCodeVisitor V(*InEH.get());
1502827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek      V.TraverseStmt(AC->getBody());
1512827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    }
1522827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    // Treat all VarDecls that occur in EH code as being "always live"
1532827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    // when considering to suppress dead stores.  Frequently stores
1542827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    // are followed by reads in EH code, but we don't have the ability
1552827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    // to analyze that yet.
1562827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    return InEH->count(D);
1572827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  }
1582827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek
1599c378f705405d37f49795d5e915989de774fe11fTed Kremenek  void Report(const VarDecl *V, DeadStoreKind dsk,
160590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks              PathDiagnosticLocation L, SourceRange R) {
161f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek    if (Escaped.count(V))
162f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek      return;
163848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
164848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    // Compute reachable blocks within the CFG for trivial cases
165848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    // where a bogus dead store can be reported because itself is unreachable.
166848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    if (!reachableCode.get()) {
167848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      reachableCode.reset(new ReachableCode(cfg));
168848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      reachableCode->computeReachableBlocks();
169848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    }
170848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
171848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    if (!reachableCode->isReachable(currentBlock))
172848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      return;
1738f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek
174f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith    SmallString<64> buf;
1757df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose    llvm::raw_svector_ostream os(buf);
1767df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose    const char *BugType = 0;
1771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1782cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    switch (dsk) {
1792cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      case DeadInit:
180efc620c4eb14d2ff59e3ec0714602997ffeddfd7Ted Kremenek        BugType = "Dead initialization";
181b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer        os << "Value stored to '" << *V
1827df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose           << "' during its initialization is never read";
1832cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        break;
1841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1852cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      case DeadIncrement:
186efc620c4eb14d2ff59e3ec0714602997ffeddfd7Ted Kremenek        BugType = "Dead increment";
1872cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      case Standard:
188efc620c4eb14d2ff59e3ec0714602997ffeddfd7Ted Kremenek        if (!BugType) BugType = "Dead assignment";
189b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer        os << "Value stored to '" << *V << "' is never read";
1902cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        break;
1911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1922cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      case Enclosing:
19356b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek        // Don't report issues in this case, e.g.: "if (x = foo())",
19456b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek        // where 'x' is unused later.  We have yet to see a case where
19556b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek        // this is a real bug.
19656b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek        return;
197f9c2a5d1b49b60962b613a1dfffa23831ca298a2Ted Kremenek    }
1981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19907189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek    BR.EmitBasicReport(AC->getDecl(), BugType, "Dead store", os.str(), L, R);
2001a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek  }
2011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2029c378f705405d37f49795d5e915989de774fe11fTed Kremenek  void CheckVarDecl(const VarDecl *VD, const Expr *Ex, const Expr *Val,
2032cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek                    DeadStoreKind dsk,
204882998923889a2fcce9b49696506c499e22cf38fTed Kremenek                    const LiveVariables::LivenessValues &Live) {
2051a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
206852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    if (!VD->hasLocalStorage())
207852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek      return;
208852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    // Reference types confuse the dead stores checker.  Skip them
209852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    // for now.
210852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    if (VD->getType()->getAs<ReferenceType>())
211852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek      return;
212852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
2132827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    if (!isLive(Live, VD) &&
214590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks        !(VD->getAttr<UnusedAttr>() || VD->getAttr<BlocksAttr>())) {
215590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks
216590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks      PathDiagnosticLocation ExLoc =
217590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks        PathDiagnosticLocation::createBegin(Ex, BR.getSourceManager(), AC);
218590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks      Report(VD, dsk, ExLoc, Val->getSourceRange());
219590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks    }
2203eb817e5095d25e7bf4a8df9ed3f9b13bed6f298Ted Kremenek  }
2211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2229c378f705405d37f49795d5e915989de774fe11fTed Kremenek  void CheckDeclRef(const DeclRefExpr *DR, const Expr *Val, DeadStoreKind dsk,
223882998923889a2fcce9b49696506c499e22cf38fTed Kremenek                    const LiveVariables::LivenessValues& Live) {
2249c378f705405d37f49795d5e915989de774fe11fTed Kremenek    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
225882998923889a2fcce9b49696506c499e22cf38fTed Kremenek      CheckVarDecl(VD, DR, Val, dsk, Live);
2262cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek  }
2271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2289c378f705405d37f49795d5e915989de774fe11fTed Kremenek  bool isIncrement(VarDecl *VD, const BinaryOperator* B) {
2292cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    if (B->isCompoundAssignmentOp())
2302cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      return true;
2311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2329c378f705405d37f49795d5e915989de774fe11fTed Kremenek    const Expr *RHS = B->getRHS()->IgnoreParenCasts();
233882998923889a2fcce9b49696506c499e22cf38fTed Kremenek    const BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS);
2341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2352cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    if (!BRHS)
2362cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      return false;
2371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
238882998923889a2fcce9b49696506c499e22cf38fTed Kremenek    const DeclRefExpr *DR;
2391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2402cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getLHS()->IgnoreParenCasts())))
2412cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      if (DR->getDecl() == VD)
2422cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        return true;
2431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2442cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getRHS()->IgnoreParenCasts())))
2452cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      if (DR->getDecl() == VD)
2462cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        return true;
2471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2482cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    return false;
249a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek  }
2501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2519c378f705405d37f49795d5e915989de774fe11fTed Kremenek  virtual void observeStmt(const Stmt *S, const CFGBlock *block,
252882998923889a2fcce9b49696506c499e22cf38fTed Kremenek                           const LiveVariables::LivenessValues &Live) {
2531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
254848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    currentBlock = block;
255848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
2561c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek    // Skip statements in macros.
2571c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek    if (S->getLocStart().isMacroID())
2581c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek      return;
2591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
260f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek    // Only cover dead stores from regular assignments.  ++/-- dead stores
261f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek    // have never flagged a real bug.
262882998923889a2fcce9b49696506c499e22cf38fTed Kremenek    if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
263fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      if (!B->isAssignmentOp()) return; // Skip non-assignments.
2641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2659c378f705405d37f49795d5e915989de774fe11fTed Kremenek      if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(B->getLHS()))
2661a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek        if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
267e12691c2a2109016df12b2cbf54d51a921e6b618Ted Kremenek          // Special case: check for assigning null to a pointer.
2681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          //  This is a common form of defensive programming.
269bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek          const Expr *RHS = LookThroughTransitiveAssignments(B->getRHS());
270bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek
271891322002b5f5886d812f6e8df12174fb2d8e73bTed Kremenek          QualType T = VD->getType();
272891322002b5f5886d812f6e8df12174fb2d8e73bTed Kremenek          if (T->isPointerType() || T->isObjCObjectPointerType()) {
273bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek            if (RHS->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNull))
27493fab7c94008d9e2b1e4ce15784544c6710945feTed Kremenek              return;
275e12691c2a2109016df12b2cbf54d51a921e6b618Ted Kremenek          }
27693fab7c94008d9e2b1e4ce15784544c6710945feTed Kremenek
277bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek          RHS = RHS->IgnoreParenCasts();
2783b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek          // Special case: self-assignments.  These are often used to shut up
2793b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek          //  "unused variable" compiler warnings.
280bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek          if (const DeclRefExpr *RhsDR = dyn_cast<DeclRefExpr>(RHS))
2813b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek            if (VD == dyn_cast<VarDecl>(RhsDR->getDecl()))
2823b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek              return;
2831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2843b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek          // Otherwise, issue a warning.
285b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek          DeadStoreKind dsk = Parents.isConsumedExpr(B)
2861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                              ? Enclosing
2877f5fce7200fdbf03f7d70134a57271e584fcb766Ted Kremenek                              : (isIncrement(VD,B) ? DeadIncrement : Standard);
2881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
289882998923889a2fcce9b49696506c499e22cf38fTed Kremenek          CheckVarDecl(VD, DR, B->getRHS(), dsk, Live);
2901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        }
2911ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek    }
292882998923889a2fcce9b49696506c499e22cf38fTed Kremenek    else if (const UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
293f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek      if (!U->isIncrementOp() || U->isPrefix())
294a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek        return;
2951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
296882998923889a2fcce9b49696506c499e22cf38fTed Kremenek      const Stmt *parent = Parents.getParentIgnoreParenCasts(U);
297f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek      if (!parent || !isa<ReturnStmt>(parent))
298380277e46ec1d2d9abedcddf357ceea935cbe576Ted Kremenek        return;
299b0f36323d9d8392075274b95816e2241f99ddb0dTed Kremenek
300882998923889a2fcce9b49696506c499e22cf38fTed Kremenek      const Expr *Ex = U->getSubExpr()->IgnoreParenCasts();
3011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3029c378f705405d37f49795d5e915989de774fe11fTed Kremenek      if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex))
303882998923889a2fcce9b49696506c499e22cf38fTed Kremenek        CheckDeclRef(DR, U, DeadIncrement, Live);
3041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    }
3059c378f705405d37f49795d5e915989de774fe11fTed Kremenek    else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S))
306fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      // Iterate through the decls.  Warn if any initializers are complex
307fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      // expressions that are not live (never used).
308882998923889a2fcce9b49696506c499e22cf38fTed Kremenek      for (DeclStmt::const_decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
30914f8b4ff660bcaa763974b8d0fae81857c594495Ted Kremenek           DI != DE; ++DI) {
3101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3119c378f705405d37f49795d5e915989de774fe11fTed Kremenek        VarDecl *V = dyn_cast<VarDecl>(*DI);
312fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek
313fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek        if (!V)
314fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek          continue;
315852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
316852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek        if (V->hasLocalStorage()) {
317852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek          // Reference types confuse the dead stores checker.  Skip them
318852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek          // for now.
319852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek          if (V->getType()->getAs<ReferenceType>())
320852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek            return;
321852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
322bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek          if (const Expr *E = V->getInit()) {
323bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek            while (const ExprWithCleanups *exprClean =
324bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek                    dyn_cast<ExprWithCleanups>(E))
325f85e193739c953358c865005855253af4f68a497John McCall              E = exprClean->getSubExpr();
326f85e193739c953358c865005855253af4f68a497John McCall
327bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek            // Look through transitive assignments, e.g.:
328bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek            // int x = y = 0;
329bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek            E = LookThroughTransitiveAssignments(E);
330bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek
33143f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek            // Don't warn on C++ objects (yet) until we can show that their
33243f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek            // constructors/destructors don't have side effects.
33343f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek            if (isa<CXXConstructExpr>(E))
33443f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek              return;
335604d939ac15d1398761df313679673d30bb10f27Ted Kremenek
336fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek            // A dead initialization is a variable that is dead after it
337fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek            // is initialized.  We don't flag warnings for those variables
338fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek            // marked 'unused'.
3392827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek            if (!isLive(Live, V) && V->getAttr<UnusedAttr>() == 0) {
340c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // Special case: check for initializations with constants.
341c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              //
342c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              //  e.g. : int x = 0;
343c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              //
344c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // If x is EVER assigned a new value later, don't issue
345c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // a warning.  This is because such initialization can be
346c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // due to defensive programming.
3470e35b4ecee380c2b4c33d75da6bc2fb6f6bc7df3Richard Smith              if (E->isEvaluatable(Ctx))
348d3098ee64c069a3eff4d2d0a5d655d968c7b5dd2Ted Kremenek                return;
3491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
350bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek              if (const DeclRefExpr *DRE =
351bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek                  dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
352bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek                if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
353ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  // Special case: check for initialization from constant
354ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  variables.
355ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //
356ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  e.g. extern const int MyConstant;
357ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //       int x = MyConstant;
358ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //
359d3098ee64c069a3eff4d2d0a5d655d968c7b5dd2Ted Kremenek                  if (VD->hasGlobalStorage() &&
360ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                      VD->getType().isConstQualified())
361ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                    return;
362ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  // Special case: check for initialization from scalar
363ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  parameters.  This is often a form of defensive
364ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  programming.  Non-scalars are still an error since
365ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  because it more likely represents an actual algorithmic
366ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  bug.
367ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  if (isa<ParmVarDecl>(VD) && VD->getType()->isScalarType())
368ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                    return;
369ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                }
3701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
371590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks              PathDiagnosticLocation Loc =
372590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks                PathDiagnosticLocation::create(V, BR.getSourceManager());
373590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks              Report(V, DeadInit, Loc, E->getSourceRange());
374ce1cab9fc0b4aec9cdef1b30a14e4ccdca3ac5f1Ted Kremenek            }
375fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek          }
376852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek        }
377fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      }
3781ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek  }
3791ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek};
3801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3811ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek} // end anonymous namespace
3821ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
383d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek//===----------------------------------------------------------------------===//
384e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek// Driver function to invoke the Dead-Stores checker on a CFG.
385e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek//===----------------------------------------------------------------------===//
386e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
387f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremeneknamespace {
388ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass FindEscaped : public CFGRecStmtDeclVisitor<FindEscaped>{
389f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  CFG *cfg;
390f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenekpublic:
391f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  FindEscaped(CFG *c) : cfg(c) {}
3921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
393f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  CFG& getCFG() { return *cfg; }
3941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
395882998923889a2fcce9b49696506c499e22cf38fTed Kremenek  llvm::SmallPtrSet<const VarDecl*, 20> Escaped;
396f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek
397f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  void VisitUnaryOperator(UnaryOperator* U) {
398f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek    // Check for '&'.  Any VarDecl whose value has its address-taken we
399f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek    // treat as escaped.
4009c378f705405d37f49795d5e915989de774fe11fTed Kremenek    Expr *E = U->getSubExpr()->IgnoreParenCasts();
4012de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall    if (U->getOpcode() == UO_AddrOf)
4029c378f705405d37f49795d5e915989de774fe11fTed Kremenek      if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
4039c378f705405d37f49795d5e915989de774fe11fTed Kremenek        if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
404f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek          Escaped.insert(VD);
405f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek          return;
406f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek        }
407f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek    Visit(E);
408f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  }
409f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek};
410f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek} // end anonymous namespace
4111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
412f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek
4137dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
4147dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis// DeadStoresChecker
4157dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
4167dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis
4177dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidisnamespace {
418ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass DeadStoresChecker : public Checker<check::ASTCodeBody> {
4197dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidispublic:
4207dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
4217dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis                        BugReporter &BR) const {
422a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek    if (LiveVariables *L = mgr.getAnalysis<LiveVariables>(D)) {
4237dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis      CFG &cfg = *mgr.getCFG(D);
4241d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek      AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D);
4257dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis      ParentMap &pmap = mgr.getParentMap(D);
4267dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis      FindEscaped FS(&cfg);
4277dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis      FS.getCFG().VisitBlockStmts(FS);
428590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks      DeadStoreObs A(cfg, BR.getContext(), BR, AC, pmap, FS.Escaped);
429882998923889a2fcce9b49696506c499e22cf38fTed Kremenek      L->runOnAllBlocks(A);
4307dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis    }
4317dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis  }
4327dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis};
4337dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis}
4347dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis
4357dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidisvoid ento::registerDeadStoresChecker(CheckerManager &mgr) {
4367dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis  mgr.registerChecker<DeadStoresChecker>();
437d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek}
438