DeadStoresChecker.cpp revision 561d3abc881033776ece385a01a510e1cbc1fa92
16e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//==- DeadStoresChecker.cpp - Check for stores to dead variables -*- C++ -*-==//
26e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//
36e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//                     The LLVM Compiler Infrastructure
46e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//
56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source
66e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// License. See LICENSE.TXT for details.
76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//
86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//===----------------------------------------------------------------------===//
96e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//
106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//  This file defines a DeadStores, a flow-sensitive checker that looks for
116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//  stores to variables that are no longer live.
126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//
136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//===----------------------------------------------------------------------===//
146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ClangSACheckers.h"
166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/Checker.h"
176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/Analysis/Analyses/LiveVariables.h"
186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/Basic/Diagnostic.h"
236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/AST/ASTContext.h"
246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/AST/ParentMap.h"
256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "llvm/ADT/SmallPtrSet.h"
266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)using namespace clang;
286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)using namespace ento;
296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace {
316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// FIXME: Eventually migrate into its own file, and have it managed by
336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// AnalysisManager.
346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class ReachableCode {
356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const CFG &cfg;
366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  llvm::BitVector reachable;
376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)public:
386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ReachableCode(const CFG &cfg)
396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    : cfg(cfg), reachable(cfg.getNumBlockIDs(), false) {}
406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void computeReachableBlocks();
426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  bool isReachable(const CFGBlock *block) const {
446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return reachable[block->getBlockID()];
456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)};
476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ReachableCode::computeReachableBlocks() {
506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!cfg.getNumBlockIDs())
516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return;
526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  SmallVector<const CFGBlock*, 10> worklist;
546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  worklist.push_back(&cfg.getEntry());
556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  while (!worklist.empty()) {
576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const CFGBlock *block = worklist.back();
586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    worklist.pop_back();
596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    llvm::BitVector::reference isReachable = reachable[block->getBlockID()];
606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (isReachable)
616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      continue;
626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    isReachable = true;
636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    for (CFGBlock::const_succ_iterator i = block->succ_begin(),
646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                       e = block->succ_end(); i != e; ++i)
656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (const CFGBlock *succ = *i)
666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        worklist.push_back(succ);
676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace {
716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class DeadStoreObs : public LiveVariables::Observer {
726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const CFG &cfg;
736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ASTContext &Ctx;
746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  BugReporter& BR;
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  AnalysisDeclContext* AC;
766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ParentMap& Parents;
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  llvm::SmallPtrSet<const VarDecl*, 20> Escaped;
786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  llvm::OwningPtr<ReachableCode> reachableCode;
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const CFGBlock *currentBlock;
806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit };
826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)public:
846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DeadStoreObs(const CFG &cfg, ASTContext &ctx,
856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)               BugReporter& br, AnalysisDeclContext* ac, ParentMap& parents,
866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)               llvm::SmallPtrSet<const VarDecl*, 20> &escaped)
876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    : cfg(cfg), Ctx(ctx), BR(br), AC(ac), Parents(parents),
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      Escaped(escaped), currentBlock(0) {}
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual ~DeadStoreObs() {}
916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void Report(const VarDecl *V, DeadStoreKind dsk,
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              PathDiagnosticLocation L, SourceRange R) {
946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (Escaped.count(V))
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return;
966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Compute reachable blocks within the CFG for trivial cases
986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // where a bogus dead store can be reported because itself is unreachable.
996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (!reachableCode.get()) {
1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reachableCode.reset(new ReachableCode(cfg));
1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      reachableCode->computeReachableBlocks();
1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (!reachableCode->isReachable(currentBlock))
1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return;
1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    llvm::SmallString<64> buf;
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    llvm::raw_svector_ostream os(buf);
1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const char *BugType = 0;
1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    switch (dsk) {
1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      case DeadInit:
1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        BugType = "Dead initialization";
1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        os << "Value stored to '" << *V
1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)           << "' during its initialization is never read";
1166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        break;
1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      case DeadIncrement:
1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        BugType = "Dead increment";
1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      case Standard:
1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        if (!BugType) BugType = "Dead assignment";
1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        os << "Value stored to '" << *V << "' is never read";
1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        break;
1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      case Enclosing:
1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        // Don't report issues in this case, e.g.: "if (x = foo())",
1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        // where 'x' is unused later.  We have yet to see a case where
1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        // this is a real bug.
1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return;
1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    BR.EmitBasicReport(BugType, "Dead store", os.str(), L, R);
1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void CheckVarDecl(const VarDecl *VD, const Expr *Ex, const Expr *Val,
1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                    DeadStoreKind dsk,
1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                    const LiveVariables::LivenessValues &Live) {
1386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (!VD->hasLocalStorage())
1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return;
1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Reference types confuse the dead stores checker.  Skip them
1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // for now.
1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (VD->getType()->getAs<ReferenceType>())
1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return;
1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (!Live.isLive(VD) &&
1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        !(VD->getAttr<UnusedAttr>() || VD->getAttr<BlocksAttr>())) {
1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      PathDiagnosticLocation ExLoc =
1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        PathDiagnosticLocation::createBegin(Ex, BR.getSourceManager(), AC);
1516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      Report(VD, dsk, ExLoc, Val->getSourceRange());
1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void CheckDeclRef(const DeclRefExpr *DR, const Expr *Val, DeadStoreKind dsk,
1566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                    const LiveVariables::LivenessValues& Live) {
1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      CheckVarDecl(VD, DR, Val, dsk, Live);
1596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  bool isIncrement(VarDecl *VD, const BinaryOperator* B) {
1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (B->isCompoundAssignmentOp())
1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return true;
1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const Expr *RHS = B->getRHS()->IgnoreParenCasts();
1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS);
1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (!BRHS)
1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return false;
1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const DeclRefExpr *DR;
1726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getLHS()->IgnoreParenCasts())))
1746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (DR->getDecl() == VD)
1756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return true;
1766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getRHS()->IgnoreParenCasts())))
1786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (DR->getDecl() == VD)
1796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return true;
1806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return false;
1826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual void observeStmt(const Stmt *S, const CFGBlock *block,
1856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                           const LiveVariables::LivenessValues &Live) {
1866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    currentBlock = block;
1886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Skip statements in macros.
1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (S->getLocStart().isMacroID())
1916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return;
1926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Only cover dead stores from regular assignments.  ++/-- dead stores
1946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // have never flagged a real bug.
1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (!B->isAssignmentOp()) return; // Skip non-assignments.
1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(B->getLHS()))
1996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
2006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          // Special case: check for assigning null to a pointer.
2016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          //  This is a common form of defensive programming.
2026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          QualType T = VD->getType();
2036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          if (T->isPointerType() || T->isObjCObjectPointerType()) {
2046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            if (B->getRHS()->isNullPointerConstant(Ctx,
2056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                              Expr::NPC_ValueDependentIsNull))
2066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              return;
2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          }
2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          Expr *RHS = B->getRHS()->IgnoreParenCasts();
2106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          // Special case: self-assignments.  These are often used to shut up
2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          //  "unused variable" compiler warnings.
2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          if (DeclRefExpr *RhsDR = dyn_cast<DeclRefExpr>(RHS))
2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            if (VD == dyn_cast<VarDecl>(RhsDR->getDecl()))
2146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              return;
2156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          // Otherwise, issue a warning.
2176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          DeadStoreKind dsk = Parents.isConsumedExpr(B)
2186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                              ? Enclosing
2196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                              : (isIncrement(VD,B) ? DeadIncrement : Standard);
2206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          CheckVarDecl(VD, DR, B->getRHS(), dsk, Live);
2226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        }
2236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
2246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    else if (const UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
2256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (!U->isIncrementOp() || U->isPrefix())
2266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return;
2276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      const Stmt *parent = Parents.getParentIgnoreParenCasts(U);
2296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (!parent || !isa<ReturnStmt>(parent))
2306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return;
2316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      const Expr *Ex = U->getSubExpr()->IgnoreParenCasts();
2336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex))
2356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        CheckDeclRef(DR, U, DeadIncrement, Live);
2366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
2376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S))
2386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      // Iterate through the decls.  Warn if any initializers are complex
2396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      // expressions that are not live (never used).
2406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      for (DeclStmt::const_decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
2416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)           DI != DE; ++DI) {
2426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        VarDecl *V = dyn_cast<VarDecl>(*DI);
2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        if (!V)
2466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          continue;
2476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        if (V->hasLocalStorage()) {
2496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          // Reference types confuse the dead stores checker.  Skip them
2506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          // for now.
2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          if (V->getType()->getAs<ReferenceType>())
2526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            return;
2536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          if (Expr *E = V->getInit()) {
2556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            while (ExprWithCleanups *exprClean = dyn_cast<ExprWithCleanups>(E))
2566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              E = exprClean->getSubExpr();
2576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            // Don't warn on C++ objects (yet) until we can show that their
2596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            // constructors/destructors don't have side effects.
2606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            if (isa<CXXConstructExpr>(E))
2616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              return;
2626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            // A dead initialization is a variable that is dead after it
2646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            // is initialized.  We don't flag warnings for those variables
2656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            // marked 'unused'.
2666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            if (!Live.isLive(V) && V->getAttr<UnusedAttr>() == 0) {
2676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              // Special case: check for initializations with constants.
2686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              //
2696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              //  e.g. : int x = 0;
2706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              //
2716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              // If x is EVER assigned a new value later, don't issue
2726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              // a warning.  This is because such initialization can be
2736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              // due to defensive programming.
2746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              if (E->isEvaluatable(Ctx))
2756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                return;
2766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              if (DeclRefExpr *DRE=dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
2786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
2796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                  // Special case: check for initialization from constant
2806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                  //  variables.
2816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                  //
2826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                  //  e.g. extern const int MyConstant;
2836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                  //       int x = MyConstant;
2846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                  //
2856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                  if (VD->hasGlobalStorage() &&
2866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                      VD->getType().isConstQualified())
2876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                    return;
2886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                  // Special case: check for initialization from scalar
2896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                  //  parameters.  This is often a form of defensive
2906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                  //  programming.  Non-scalars are still an error since
2916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                  //  because it more likely represents an actual algorithmic
2926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                  //  bug.
2936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                  if (isa<ParmVarDecl>(VD) && VD->getType()->isScalarType())
2946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                    return;
2956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                }
2966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              PathDiagnosticLocation Loc =
2986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                PathDiagnosticLocation::create(V, BR.getSourceManager());
2996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              Report(V, DeadInit, Loc, E->getSourceRange());
3006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            }
3016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          }
3026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        }
3036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      }
3046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
3056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)};
3066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} // end anonymous namespace
3086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//===----------------------------------------------------------------------===//
3106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Driver function to invoke the Dead-Stores checker on a CFG.
3116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//===----------------------------------------------------------------------===//
3126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace {
3146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class FindEscaped : public CFGRecStmtDeclVisitor<FindEscaped>{
3156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  CFG *cfg;
3166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)public:
3176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  FindEscaped(CFG *c) : cfg(c) {}
3186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  CFG& getCFG() { return *cfg; }
3206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  llvm::SmallPtrSet<const VarDecl*, 20> Escaped;
3226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void VisitUnaryOperator(UnaryOperator* U) {
3246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Check for '&'.  Any VarDecl whose value has its address-taken we
3256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // treat as escaped.
3266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    Expr *E = U->getSubExpr()->IgnoreParenCasts();
3276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (U->getOpcode() == UO_AddrOf)
3286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
3296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
3306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          Escaped.insert(VD);
3316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          return;
3326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        }
3336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    Visit(E);
3346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
3356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)};
3366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} // end anonymous namespace
3376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//===----------------------------------------------------------------------===//
3406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// DeadStoresChecker
3416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//===----------------------------------------------------------------------===//
3426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace {
3446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class DeadStoresChecker : public Checker<check::ASTCodeBody> {
3456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)public:
3466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
3476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                        BugReporter &BR) const {
3486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (LiveVariables *L = mgr.getAnalysis<LiveVariables>(D)) {
3496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      CFG &cfg = *mgr.getCFG(D);
3506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D);
3516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      ParentMap &pmap = mgr.getParentMap(D);
3526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      FindEscaped FS(&cfg);
3536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      FS.getCFG().VisitBlockStmts(FS);
3546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      DeadStoreObs A(cfg, BR.getContext(), BR, AC, pmap, FS.Escaped);
3556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      L->runOnAllBlocks(A);
3566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
3576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
3586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)};
3596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
3606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ento::registerDeadStoresChecker(CheckerManager &mgr) {
3626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  mgr.registerChecker<DeadStoresChecker>();
3636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
3646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)