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/StaticAnalyzer/Core/BugReporter/BugReporter.h"
2219948ac84f145b9ea576db2faefda1927c249e44Ted Kremenek#include "clang/StaticAnalyzer/Core/Checker.h"
2319948ac84f145b9ea576db2faefda1927c249e44Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
2419948ac84f145b9ea576db2faefda1927c249e44Ted Kremenek#include "llvm/ADT/BitVector.h"
258fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h"
262827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek#include "llvm/Support/SaveAndRestore.h"
271ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
281ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenekusing namespace clang;
299ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
301ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
312827f5af018c515986ffb1779ec2e7246988f150Ted Kremeneknamespace {
322827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek
332827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek/// A simple visitor to record what VarDecls occur in EH-handling code.
342827f5af018c515986ffb1779ec2e7246988f150Ted Kremenekclass EHCodeVisitor : public RecursiveASTVisitor<EHCodeVisitor> {
352827f5af018c515986ffb1779ec2e7246988f150Ted Kremenekpublic:
362827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  bool inEH;
372827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  llvm::DenseSet<const VarDecl *> &S;
382827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek
392827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  bool TraverseObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
402827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    SaveAndRestore<bool> inFinally(inEH, true);
412827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    return ::RecursiveASTVisitor<EHCodeVisitor>::TraverseObjCAtFinallyStmt(S);
422827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  }
432827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek
442827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  bool TraverseObjCAtCatchStmt(ObjCAtCatchStmt *S) {
452827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    SaveAndRestore<bool> inCatch(inEH, true);
462827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    return ::RecursiveASTVisitor<EHCodeVisitor>::TraverseObjCAtCatchStmt(S);
472827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  }
482827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek
492827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  bool TraverseCXXCatchStmt(CXXCatchStmt *S) {
502827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    SaveAndRestore<bool> inCatch(inEH, true);
512827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    return TraverseStmt(S->getHandlerBlock());
522827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  }
532827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek
542827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  bool VisitDeclRefExpr(DeclRefExpr *DR) {
552827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    if (inEH)
562827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek      if (const VarDecl *D = dyn_cast<VarDecl>(DR->getDecl()))
572827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek        S.insert(D);
582827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    return true;
592827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  }
602827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek
612827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  EHCodeVisitor(llvm::DenseSet<const VarDecl *> &S) :
622827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  inEH(false), S(S) {}
632827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek};
641a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
65848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek// FIXME: Eventually migrate into its own file, and have it managed by
66848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek// AnalysisManager.
67848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenekclass ReachableCode {
68848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  const CFG &cfg;
69848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  llvm::BitVector reachable;
70848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenekpublic:
71848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  ReachableCode(const CFG &cfg)
72848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    : cfg(cfg), reachable(cfg.getNumBlockIDs(), false) {}
73848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
74848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  void computeReachableBlocks();
75848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
76848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  bool isReachable(const CFGBlock *block) const {
77848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    return reachable[block->getBlockID()];
78848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  }
79848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek};
80848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek}
81848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
82848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenekvoid ReachableCode::computeReachableBlocks() {
83848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  if (!cfg.getNumBlockIDs())
84848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    return;
85848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
865f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<const CFGBlock*, 10> worklist;
87848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  worklist.push_back(&cfg.getEntry());
88848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
89848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  while (!worklist.empty()) {
90848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    const CFGBlock *block = worklist.back();
91848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    worklist.pop_back();
92848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    llvm::BitVector::reference isReachable = reachable[block->getBlockID()];
93848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    if (isReachable)
94848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      continue;
95848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    isReachable = true;
96848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    for (CFGBlock::const_succ_iterator i = block->succ_begin(),
97848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek                                       e = block->succ_end(); i != e; ++i)
98848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      if (const CFGBlock *succ = *i)
99848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek        worklist.push_back(succ);
100848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  }
101848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek}
102848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
1039ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaksstatic const Expr *
1049ed6d8068f767819951bc4eebf6f4912087c442aAnna ZaksLookThroughTransitiveAssignmentsAndCommaOperators(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    }
1149ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaks    if (BO->getOpcode() == BO_Comma) {
1159ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaks      Ex = BO->getRHS();
1169ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaks      continue;
1179ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaks    }
118bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek    break;
119bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek  }
120bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek  return Ex;
121bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek}
122bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek
123848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremeneknamespace {
124882998923889a2fcce9b49696506c499e22cf38fTed Kremenekclass DeadStoreObs : public LiveVariables::Observer {
125848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  const CFG &cfg;
126c0508f9fe37a3afb1ccad39879348272545e55dbChris Lattner  ASTContext &Ctx;
1278f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek  BugReporter& BR;
1281d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek  AnalysisDeclContext* AC;
1291a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek  ParentMap& Parents;
130882998923889a2fcce9b49696506c499e22cf38fTed Kremenek  llvm::SmallPtrSet<const VarDecl*, 20> Escaped;
1316f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<ReachableCode> reachableCode;
132848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  const CFGBlock *currentBlock;
133cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  OwningPtr<llvm::DenseSet<const VarDecl *> > InEH;
1341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1352cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek  enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit };
1361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1371ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenekpublic:
138848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  DeadStoreObs(const CFG &cfg, ASTContext &ctx,
1391d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek               BugReporter& br, AnalysisDeclContext* ac, ParentMap& parents,
140882998923889a2fcce9b49696506c499e22cf38fTed Kremenek               llvm::SmallPtrSet<const VarDecl*, 20> &escaped)
141590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks    : cfg(cfg), Ctx(ctx), BR(br), AC(ac), Parents(parents),
142848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      Escaped(escaped), currentBlock(0) {}
1431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
144fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek  virtual ~DeadStoreObs() {}
145b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek
1462827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  bool isLive(const LiveVariables::LivenessValues &Live, const VarDecl *D) {
1472827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    if (Live.isLive(D))
1482827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek      return true;
1492827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    // Lazily construct the set that records which VarDecls are in
1502827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    // EH code.
1512827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    if (!InEH.get()) {
1522827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek      InEH.reset(new llvm::DenseSet<const VarDecl *>());
1532827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek      EHCodeVisitor V(*InEH.get());
1542827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek      V.TraverseStmt(AC->getBody());
1552827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    }
1562827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    // Treat all VarDecls that occur in EH code as being "always live"
1572827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    // when considering to suppress dead stores.  Frequently stores
1582827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    // are followed by reads in EH code, but we don't have the ability
1592827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    // to analyze that yet.
1602827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    return InEH->count(D);
1612827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek  }
1622827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek
1639c378f705405d37f49795d5e915989de774fe11fTed Kremenek  void Report(const VarDecl *V, DeadStoreKind dsk,
164590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks              PathDiagnosticLocation L, SourceRange R) {
165f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek    if (Escaped.count(V))
166f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek      return;
167848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
168848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    // Compute reachable blocks within the CFG for trivial cases
169848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    // where a bogus dead store can be reported because itself is unreachable.
170848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    if (!reachableCode.get()) {
171848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      reachableCode.reset(new ReachableCode(cfg));
172848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      reachableCode->computeReachableBlocks();
173848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    }
174848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
175848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    if (!reachableCode->isReachable(currentBlock))
176848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      return;
1778f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek
178f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith    SmallString<64> buf;
1797df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose    llvm::raw_svector_ostream os(buf);
1807df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose    const char *BugType = 0;
1811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1822cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    switch (dsk) {
1832cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      case DeadInit:
184efc620c4eb14d2ff59e3ec0714602997ffeddfd7Ted Kremenek        BugType = "Dead initialization";
185b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer        os << "Value stored to '" << *V
1867df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose           << "' during its initialization is never read";
1872cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        break;
1881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1892cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      case DeadIncrement:
190efc620c4eb14d2ff59e3ec0714602997ffeddfd7Ted Kremenek        BugType = "Dead increment";
1912cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      case Standard:
192efc620c4eb14d2ff59e3ec0714602997ffeddfd7Ted Kremenek        if (!BugType) BugType = "Dead assignment";
193b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer        os << "Value stored to '" << *V << "' is never read";
1942cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        break;
1951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1962cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      case Enclosing:
19756b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek        // Don't report issues in this case, e.g.: "if (x = foo())",
19856b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek        // where 'x' is unused later.  We have yet to see a case where
19956b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek        // this is a real bug.
20056b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek        return;
201f9c2a5d1b49b60962b613a1dfffa23831ca298a2Ted Kremenek    }
2021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20307189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek    BR.EmitBasicReport(AC->getDecl(), BugType, "Dead store", os.str(), L, R);
2041a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek  }
2051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2069c378f705405d37f49795d5e915989de774fe11fTed Kremenek  void CheckVarDecl(const VarDecl *VD, const Expr *Ex, const Expr *Val,
2072cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek                    DeadStoreKind dsk,
208882998923889a2fcce9b49696506c499e22cf38fTed Kremenek                    const LiveVariables::LivenessValues &Live) {
2091a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
210852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    if (!VD->hasLocalStorage())
211852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek      return;
212852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    // Reference types confuse the dead stores checker.  Skip them
213852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    // for now.
214852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    if (VD->getType()->getAs<ReferenceType>())
215852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek      return;
216852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
2172827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek    if (!isLive(Live, VD) &&
218590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks        !(VD->getAttr<UnusedAttr>() || VD->getAttr<BlocksAttr>())) {
219590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks
220590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks      PathDiagnosticLocation ExLoc =
221590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks        PathDiagnosticLocation::createBegin(Ex, BR.getSourceManager(), AC);
222590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks      Report(VD, dsk, ExLoc, Val->getSourceRange());
223590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks    }
2243eb817e5095d25e7bf4a8df9ed3f9b13bed6f298Ted Kremenek  }
2251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2269c378f705405d37f49795d5e915989de774fe11fTed Kremenek  void CheckDeclRef(const DeclRefExpr *DR, const Expr *Val, DeadStoreKind dsk,
227882998923889a2fcce9b49696506c499e22cf38fTed Kremenek                    const LiveVariables::LivenessValues& Live) {
2289c378f705405d37f49795d5e915989de774fe11fTed Kremenek    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
229882998923889a2fcce9b49696506c499e22cf38fTed Kremenek      CheckVarDecl(VD, DR, Val, dsk, Live);
2302cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek  }
2311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2329c378f705405d37f49795d5e915989de774fe11fTed Kremenek  bool isIncrement(VarDecl *VD, const BinaryOperator* B) {
2332cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    if (B->isCompoundAssignmentOp())
2342cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      return true;
2351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2369c378f705405d37f49795d5e915989de774fe11fTed Kremenek    const Expr *RHS = B->getRHS()->IgnoreParenCasts();
237882998923889a2fcce9b49696506c499e22cf38fTed Kremenek    const BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS);
2381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2392cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    if (!BRHS)
2402cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      return false;
2411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
242882998923889a2fcce9b49696506c499e22cf38fTed Kremenek    const DeclRefExpr *DR;
2431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2442cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getLHS()->IgnoreParenCasts())))
2452cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      if (DR->getDecl() == VD)
2462cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        return true;
2471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2482cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getRHS()->IgnoreParenCasts())))
2492cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      if (DR->getDecl() == VD)
2502cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        return true;
2511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2522cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    return false;
253a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek  }
2541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2559c378f705405d37f49795d5e915989de774fe11fTed Kremenek  virtual void observeStmt(const Stmt *S, const CFGBlock *block,
256882998923889a2fcce9b49696506c499e22cf38fTed Kremenek                           const LiveVariables::LivenessValues &Live) {
2571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
258848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    currentBlock = block;
259848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
2601c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek    // Skip statements in macros.
2611c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek    if (S->getLocStart().isMacroID())
2621c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek      return;
2631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
264f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek    // Only cover dead stores from regular assignments.  ++/-- dead stores
265f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek    // have never flagged a real bug.
266882998923889a2fcce9b49696506c499e22cf38fTed Kremenek    if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
267fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      if (!B->isAssignmentOp()) return; // Skip non-assignments.
2681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2699c378f705405d37f49795d5e915989de774fe11fTed Kremenek      if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(B->getLHS()))
2701a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek        if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
271e12691c2a2109016df12b2cbf54d51a921e6b618Ted Kremenek          // Special case: check for assigning null to a pointer.
2721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          //  This is a common form of defensive programming.
2739ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaks          const Expr *RHS =
2749ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaks            LookThroughTransitiveAssignmentsAndCommaOperators(B->getRHS());
2759ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaks          RHS = RHS->IgnoreParenCasts();
276bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek
277891322002b5f5886d812f6e8df12174fb2d8e73bTed Kremenek          QualType T = VD->getType();
278891322002b5f5886d812f6e8df12174fb2d8e73bTed Kremenek          if (T->isPointerType() || T->isObjCObjectPointerType()) {
279bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek            if (RHS->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNull))
28093fab7c94008d9e2b1e4ce15784544c6710945feTed Kremenek              return;
281e12691c2a2109016df12b2cbf54d51a921e6b618Ted Kremenek          }
28293fab7c94008d9e2b1e4ce15784544c6710945feTed Kremenek
2833b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek          // Special case: self-assignments.  These are often used to shut up
2843b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek          //  "unused variable" compiler warnings.
285bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek          if (const DeclRefExpr *RhsDR = dyn_cast<DeclRefExpr>(RHS))
2863b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek            if (VD == dyn_cast<VarDecl>(RhsDR->getDecl()))
2873b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek              return;
2881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2893b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek          // Otherwise, issue a warning.
290b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek          DeadStoreKind dsk = Parents.isConsumedExpr(B)
2911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                              ? Enclosing
2927f5fce7200fdbf03f7d70134a57271e584fcb766Ted Kremenek                              : (isIncrement(VD,B) ? DeadIncrement : Standard);
2931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
294882998923889a2fcce9b49696506c499e22cf38fTed Kremenek          CheckVarDecl(VD, DR, B->getRHS(), dsk, Live);
2951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        }
2961ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek    }
297882998923889a2fcce9b49696506c499e22cf38fTed Kremenek    else if (const UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
298f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek      if (!U->isIncrementOp() || U->isPrefix())
299a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek        return;
3001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
301882998923889a2fcce9b49696506c499e22cf38fTed Kremenek      const Stmt *parent = Parents.getParentIgnoreParenCasts(U);
302f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek      if (!parent || !isa<ReturnStmt>(parent))
303380277e46ec1d2d9abedcddf357ceea935cbe576Ted Kremenek        return;
304b0f36323d9d8392075274b95816e2241f99ddb0dTed Kremenek
305882998923889a2fcce9b49696506c499e22cf38fTed Kremenek      const Expr *Ex = U->getSubExpr()->IgnoreParenCasts();
3061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3079c378f705405d37f49795d5e915989de774fe11fTed Kremenek      if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex))
308882998923889a2fcce9b49696506c499e22cf38fTed Kremenek        CheckDeclRef(DR, U, DeadIncrement, Live);
3091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    }
3109c378f705405d37f49795d5e915989de774fe11fTed Kremenek    else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S))
311fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      // Iterate through the decls.  Warn if any initializers are complex
312fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      // expressions that are not live (never used).
313882998923889a2fcce9b49696506c499e22cf38fTed Kremenek      for (DeclStmt::const_decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
31414f8b4ff660bcaa763974b8d0fae81857c594495Ted Kremenek           DI != DE; ++DI) {
3151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3169c378f705405d37f49795d5e915989de774fe11fTed Kremenek        VarDecl *V = dyn_cast<VarDecl>(*DI);
317fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek
318fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek        if (!V)
319fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek          continue;
320852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
321852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek        if (V->hasLocalStorage()) {
322852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek          // Reference types confuse the dead stores checker.  Skip them
323852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek          // for now.
324852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek          if (V->getType()->getAs<ReferenceType>())
325852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek            return;
326852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
327bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek          if (const Expr *E = V->getInit()) {
328bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek            while (const ExprWithCleanups *exprClean =
329bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek                    dyn_cast<ExprWithCleanups>(E))
330f85e193739c953358c865005855253af4f68a497John McCall              E = exprClean->getSubExpr();
331f85e193739c953358c865005855253af4f68a497John McCall
332bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek            // Look through transitive assignments, e.g.:
333bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek            // int x = y = 0;
3349ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaks            E = LookThroughTransitiveAssignmentsAndCommaOperators(E);
335bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek
33643f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek            // Don't warn on C++ objects (yet) until we can show that their
33743f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek            // constructors/destructors don't have side effects.
33843f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek            if (isa<CXXConstructExpr>(E))
33943f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek              return;
340604d939ac15d1398761df313679673d30bb10f27Ted Kremenek
341fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek            // A dead initialization is a variable that is dead after it
342fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek            // is initialized.  We don't flag warnings for those variables
343fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek            // marked 'unused'.
3442827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek            if (!isLive(Live, V) && V->getAttr<UnusedAttr>() == 0) {
345c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // Special case: check for initializations with constants.
346c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              //
347c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              //  e.g. : int x = 0;
348c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              //
349c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // If x is EVER assigned a new value later, don't issue
350c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // a warning.  This is because such initialization can be
351c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // due to defensive programming.
3520e35b4ecee380c2b4c33d75da6bc2fb6f6bc7df3Richard Smith              if (E->isEvaluatable(Ctx))
353d3098ee64c069a3eff4d2d0a5d655d968c7b5dd2Ted Kremenek                return;
3541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
355bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek              if (const DeclRefExpr *DRE =
356bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek                  dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
357bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek                if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
358ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  // Special case: check for initialization from constant
359ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  variables.
360ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //
361ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  e.g. extern const int MyConstant;
362ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //       int x = MyConstant;
363ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //
364d3098ee64c069a3eff4d2d0a5d655d968c7b5dd2Ted Kremenek                  if (VD->hasGlobalStorage() &&
365ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                      VD->getType().isConstQualified())
366ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                    return;
367ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  // Special case: check for initialization from scalar
368ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  parameters.  This is often a form of defensive
369ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  programming.  Non-scalars are still an error since
370ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  because it more likely represents an actual algorithmic
371ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  bug.
372ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  if (isa<ParmVarDecl>(VD) && VD->getType()->isScalarType())
373ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                    return;
374ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                }
3751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
376590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks              PathDiagnosticLocation Loc =
377590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks                PathDiagnosticLocation::create(V, BR.getSourceManager());
378590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks              Report(V, DeadInit, Loc, E->getSourceRange());
379ce1cab9fc0b4aec9cdef1b30a14e4ccdca3ac5f1Ted Kremenek            }
380fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek          }
381852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek        }
382fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      }
3831ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek  }
3841ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek};
3851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3861ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek} // end anonymous namespace
3871ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
388d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek//===----------------------------------------------------------------------===//
389e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek// Driver function to invoke the Dead-Stores checker on a CFG.
390e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek//===----------------------------------------------------------------------===//
391e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
392f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremeneknamespace {
393d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Roseclass FindEscaped {
394f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenekpublic:
395882998923889a2fcce9b49696506c499e22cf38fTed Kremenek  llvm::SmallPtrSet<const VarDecl*, 20> Escaped;
396f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek
397d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose  void operator()(const Stmt *S) {
398d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose    // Check for '&'. Any VarDecl whose address has been taken we treat as
399d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose    // escaped.
400d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose    // FIXME: What about references?
401d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose    const UnaryOperator *U = dyn_cast<UnaryOperator>(S);
402d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose    if (!U)
403d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose      return;
404d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose    if (U->getOpcode() != UO_AddrOf)
405d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose      return;
406d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose
407d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose    const Expr *E = U->getSubExpr()->IgnoreParenCasts();
408d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose    if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
409d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose      if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
410d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose        Escaped.insert(VD);
411f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  }
412f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek};
413f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek} // end anonymous namespace
4141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
415f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek
4167dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
4177dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis// DeadStoresChecker
4187dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
4197dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis
4207dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidisnamespace {
421ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass DeadStoresChecker : public Checker<check::ASTCodeBody> {
4227dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidispublic:
4237dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
4247dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis                        BugReporter &BR) const {
425724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek
426724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek    // Don't do anything for template instantiations.
427724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek    // Proving that code in a template instantiation is "dead"
428724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek    // means proving that it is dead in all instantiations.
429724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek    // This same problem exists with -Wunreachable-code.
430724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
431724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek      if (FD->isTemplateInstantiation())
432724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek        return;
433724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek
434a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek    if (LiveVariables *L = mgr.getAnalysis<LiveVariables>(D)) {
4357dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis      CFG &cfg = *mgr.getCFG(D);
4361d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek      AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D);
4377dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis      ParentMap &pmap = mgr.getParentMap(D);
438d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose      FindEscaped FS;
439d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose      cfg.VisitBlockStmts(FS);
440590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks      DeadStoreObs A(cfg, BR.getContext(), BR, AC, pmap, FS.Escaped);
441882998923889a2fcce9b49696506c499e22cf38fTed Kremenek      L->runOnAllBlocks(A);
4427dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis    }
4437dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis  }
4447dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis};
4457dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis}
4467dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis
4477dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidisvoid ento::registerDeadStoresChecker(CheckerManager &mgr) {
4487dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis  mgr.registerChecker<DeadStoresChecker>();
449d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek}
450