DeadStoresChecker.cpp revision 9c378f705405d37f49795d5e915989de774fe11f
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"
16ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h"
17cf6e41baf2b23b6b56f0f79fff5554b7745737acTed Kremenek#include "clang/Analysis/Analyses/LiveVariables.h"
18fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
199b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
209b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
21f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
221ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek#include "clang/Basic/Diagnostic.h"
23ce1cab9fc0b4aec9cdef1b30a14e4ccdca3ac5f1Ted Kremenek#include "clang/AST/ASTContext.h"
241a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek#include "clang/AST/ParentMap.h"
25f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek#include "llvm/ADT/SmallPtrSet.h"
261ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
271ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenekusing namespace clang;
289ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
291ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
301ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremeneknamespace {
311a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
32848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek// FIXME: Eventually migrate into its own file, and have it managed by
33848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek// AnalysisManager.
34848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenekclass ReachableCode {
35848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  const CFG &cfg;
36848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  llvm::BitVector reachable;
37848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenekpublic:
38848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  ReachableCode(const CFG &cfg)
39848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    : cfg(cfg), reachable(cfg.getNumBlockIDs(), false) {}
40848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
41848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  void computeReachableBlocks();
42848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
43848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  bool isReachable(const CFGBlock *block) const {
44848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    return reachable[block->getBlockID()];
45848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  }
46848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek};
47848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek}
48848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
49848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenekvoid ReachableCode::computeReachableBlocks() {
50848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  if (!cfg.getNumBlockIDs())
51848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    return;
52848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
535f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<const CFGBlock*, 10> worklist;
54848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  worklist.push_back(&cfg.getEntry());
55848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
56848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  while (!worklist.empty()) {
57848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    const CFGBlock *block = worklist.back();
58848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    worklist.pop_back();
59848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    llvm::BitVector::reference isReachable = reachable[block->getBlockID()];
60848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    if (isReachable)
61848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      continue;
62848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    isReachable = true;
63848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    for (CFGBlock::const_succ_iterator i = block->succ_begin(),
64848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek                                       e = block->succ_end(); i != e; ++i)
65848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      if (const CFGBlock *succ = *i)
66848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek        worklist.push_back(succ);
67848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  }
68848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek}
69848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
70848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremeneknamespace {
71882998923889a2fcce9b49696506c499e22cf38fTed Kremenekclass DeadStoreObs : public LiveVariables::Observer {
72848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  const CFG &cfg;
73c0508f9fe37a3afb1ccad39879348272545e55dbChris Lattner  ASTContext &Ctx;
748f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek  BugReporter& BR;
751a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek  ParentMap& Parents;
76882998923889a2fcce9b49696506c499e22cf38fTed Kremenek  llvm::SmallPtrSet<const VarDecl*, 20> Escaped;
77848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  llvm::OwningPtr<ReachableCode> reachableCode;
78848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  const CFGBlock *currentBlock;
791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
802cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek  enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit };
811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
821ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenekpublic:
83848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek  DeadStoreObs(const CFG &cfg, ASTContext &ctx,
84848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek               BugReporter& br, ParentMap& parents,
85882998923889a2fcce9b49696506c499e22cf38fTed Kremenek               llvm::SmallPtrSet<const VarDecl*, 20> &escaped)
86848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    : cfg(cfg), Ctx(ctx), BR(br), Parents(parents),
87848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      Escaped(escaped), currentBlock(0) {}
881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
89fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek  virtual ~DeadStoreObs() {}
90b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek
919c378f705405d37f49795d5e915989de774fe11fTed Kremenek  void Report(const VarDecl *V, DeadStoreKind dsk,
92882998923889a2fcce9b49696506c499e22cf38fTed Kremenek              SourceLocation L, SourceRange R) {
93f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek    if (Escaped.count(V))
94f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek      return;
95848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
96848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    // Compute reachable blocks within the CFG for trivial cases
97848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    // where a bogus dead store can be reported because itself is unreachable.
98848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    if (!reachableCode.get()) {
99848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      reachableCode.reset(new ReachableCode(cfg));
100848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      reachableCode->computeReachableBlocks();
101848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    }
102848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
103848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    if (!reachableCode->isReachable(currentBlock))
104848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek      return;
1058f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek
106848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    const std::string &name = V->getNameAsString();
1071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1082cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    const char* BugType = 0;
1092cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    std::string msg;
1101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1112cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    switch (dsk) {
1122cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      default:
1132cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        assert(false && "Impossible dead store type.");
1141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1152cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      case DeadInit:
116efc620c4eb14d2ff59e3ec0714602997ffeddfd7Ted Kremenek        BugType = "Dead initialization";
1172cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        msg = "Value stored to '" + name +
1182cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek          "' during its initialization is never read";
1192cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        break;
1201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1212cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      case DeadIncrement:
122efc620c4eb14d2ff59e3ec0714602997ffeddfd7Ted Kremenek        BugType = "Dead increment";
1232cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      case Standard:
124efc620c4eb14d2ff59e3ec0714602997ffeddfd7Ted Kremenek        if (!BugType) BugType = "Dead assignment";
1252cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        msg = "Value stored to '" + name + "' is never read";
1262cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        break;
1271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1282cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      case Enclosing:
12956b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek        // Don't report issues in this case, e.g.: "if (x = foo())",
13056b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek        // where 'x' is unused later.  We have yet to see a case where
13156b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek        // this is a real bug.
13256b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek        return;
133f9c2a5d1b49b60962b613a1dfffa23831ca298a2Ted Kremenek    }
1341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
135f0171732efb4647772ad2a45c0f31978b0e34f71Benjamin Kramer    BR.EmitBasicReport(BugType, "Dead store", msg, L, R);
1361a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek  }
1371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1389c378f705405d37f49795d5e915989de774fe11fTed Kremenek  void CheckVarDecl(const VarDecl *VD, const Expr *Ex, const Expr *Val,
1392cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek                    DeadStoreKind dsk,
140882998923889a2fcce9b49696506c499e22cf38fTed Kremenek                    const LiveVariables::LivenessValues &Live) {
1411a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
142852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    if (!VD->hasLocalStorage())
143852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek      return;
144852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    // Reference types confuse the dead stores checker.  Skip them
145852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    // for now.
146852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    if (VD->getType()->getAs<ReferenceType>())
147852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek      return;
148852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
149882998923889a2fcce9b49696506c499e22cf38fTed Kremenek    if (!Live.isLive(VD) &&
15074635d8cd3c367890735dc4af2c2825a7e4b434cTed Kremenek        !(VD->getAttr<UnusedAttr>() || VD->getAttr<BlocksAttr>()))
1512cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      Report(VD, dsk, Ex->getSourceRange().getBegin(),
1521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump             Val->getSourceRange());
1533eb817e5095d25e7bf4a8df9ed3f9b13bed6f298Ted Kremenek  }
1541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1559c378f705405d37f49795d5e915989de774fe11fTed Kremenek  void CheckDeclRef(const DeclRefExpr *DR, const Expr *Val, DeadStoreKind dsk,
156882998923889a2fcce9b49696506c499e22cf38fTed Kremenek                    const LiveVariables::LivenessValues& Live) {
1579c378f705405d37f49795d5e915989de774fe11fTed Kremenek    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
158882998923889a2fcce9b49696506c499e22cf38fTed Kremenek      CheckVarDecl(VD, DR, Val, dsk, Live);
1592cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek  }
1601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1619c378f705405d37f49795d5e915989de774fe11fTed Kremenek  bool isIncrement(VarDecl *VD, const BinaryOperator* B) {
1622cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    if (B->isCompoundAssignmentOp())
1632cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      return true;
1641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1659c378f705405d37f49795d5e915989de774fe11fTed Kremenek    const Expr *RHS = B->getRHS()->IgnoreParenCasts();
166882998923889a2fcce9b49696506c499e22cf38fTed Kremenek    const BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS);
1671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1682cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    if (!BRHS)
1692cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      return false;
1701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
171882998923889a2fcce9b49696506c499e22cf38fTed Kremenek    const DeclRefExpr *DR;
1721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1732cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getLHS()->IgnoreParenCasts())))
1742cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      if (DR->getDecl() == VD)
1752cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        return true;
1761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1772cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getRHS()->IgnoreParenCasts())))
1782cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      if (DR->getDecl() == VD)
1792cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        return true;
1801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1812cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    return false;
182a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek  }
1831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1849c378f705405d37f49795d5e915989de774fe11fTed Kremenek  virtual void observeStmt(const Stmt *S, const CFGBlock *block,
185882998923889a2fcce9b49696506c499e22cf38fTed Kremenek                           const LiveVariables::LivenessValues &Live) {
1861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
187848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek    currentBlock = block;
188848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek
1891c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek    // Skip statements in macros.
1901c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek    if (S->getLocStart().isMacroID())
1911c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek      return;
1921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
193f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek    // Only cover dead stores from regular assignments.  ++/-- dead stores
194f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek    // have never flagged a real bug.
195882998923889a2fcce9b49696506c499e22cf38fTed Kremenek    if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
196fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      if (!B->isAssignmentOp()) return; // Skip non-assignments.
1971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1989c378f705405d37f49795d5e915989de774fe11fTed Kremenek      if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(B->getLHS()))
1991a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek        if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
200e12691c2a2109016df12b2cbf54d51a921e6b618Ted Kremenek          // Special case: check for assigning null to a pointer.
2011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          //  This is a common form of defensive programming.
202891322002b5f5886d812f6e8df12174fb2d8e73bTed Kremenek          QualType T = VD->getType();
203891322002b5f5886d812f6e8df12174fb2d8e73bTed Kremenek          if (T->isPointerType() || T->isObjCObjectPointerType()) {
20493fab7c94008d9e2b1e4ce15784544c6710945feTed Kremenek            if (B->getRHS()->isNullPointerConstant(Ctx,
20593fab7c94008d9e2b1e4ce15784544c6710945feTed Kremenek                                              Expr::NPC_ValueDependentIsNull))
20693fab7c94008d9e2b1e4ce15784544c6710945feTed Kremenek              return;
207e12691c2a2109016df12b2cbf54d51a921e6b618Ted Kremenek          }
20893fab7c94008d9e2b1e4ce15784544c6710945feTed Kremenek
2099c378f705405d37f49795d5e915989de774fe11fTed Kremenek          Expr *RHS = B->getRHS()->IgnoreParenCasts();
2103b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek          // Special case: self-assignments.  These are often used to shut up
2113b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek          //  "unused variable" compiler warnings.
2129c378f705405d37f49795d5e915989de774fe11fTed Kremenek          if (DeclRefExpr *RhsDR = dyn_cast<DeclRefExpr>(RHS))
2133b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek            if (VD == dyn_cast<VarDecl>(RhsDR->getDecl()))
2143b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek              return;
2151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2163b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek          // Otherwise, issue a warning.
217b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek          DeadStoreKind dsk = Parents.isConsumedExpr(B)
2181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                              ? Enclosing
2197f5fce7200fdbf03f7d70134a57271e584fcb766Ted Kremenek                              : (isIncrement(VD,B) ? DeadIncrement : Standard);
2201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
221882998923889a2fcce9b49696506c499e22cf38fTed Kremenek          CheckVarDecl(VD, DR, B->getRHS(), dsk, Live);
2221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        }
2231ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek    }
224882998923889a2fcce9b49696506c499e22cf38fTed Kremenek    else if (const UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
225f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek      if (!U->isIncrementOp() || U->isPrefix())
226a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek        return;
2271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
228882998923889a2fcce9b49696506c499e22cf38fTed Kremenek      const Stmt *parent = Parents.getParentIgnoreParenCasts(U);
229f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek      if (!parent || !isa<ReturnStmt>(parent))
230380277e46ec1d2d9abedcddf357ceea935cbe576Ted Kremenek        return;
231b0f36323d9d8392075274b95816e2241f99ddb0dTed Kremenek
232882998923889a2fcce9b49696506c499e22cf38fTed Kremenek      const Expr *Ex = U->getSubExpr()->IgnoreParenCasts();
2331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2349c378f705405d37f49795d5e915989de774fe11fTed Kremenek      if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex))
235882998923889a2fcce9b49696506c499e22cf38fTed Kremenek        CheckDeclRef(DR, U, DeadIncrement, Live);
2361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    }
2379c378f705405d37f49795d5e915989de774fe11fTed Kremenek    else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S))
238fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      // Iterate through the decls.  Warn if any initializers are complex
239fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      // expressions that are not live (never used).
240882998923889a2fcce9b49696506c499e22cf38fTed Kremenek      for (DeclStmt::const_decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
24114f8b4ff660bcaa763974b8d0fae81857c594495Ted Kremenek           DI != DE; ++DI) {
2421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2439c378f705405d37f49795d5e915989de774fe11fTed Kremenek        VarDecl *V = dyn_cast<VarDecl>(*DI);
244fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek
245fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek        if (!V)
246fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek          continue;
247852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
248852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek        if (V->hasLocalStorage()) {
249852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek          // Reference types confuse the dead stores checker.  Skip them
250852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek          // for now.
251852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek          if (V->getType()->getAs<ReferenceType>())
252852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek            return;
253852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
2549c378f705405d37f49795d5e915989de774fe11fTed Kremenek          if (Expr *E = V->getInit()) {
255f85e193739c953358c865005855253af4f68a497John McCall            while (ExprWithCleanups *exprClean = dyn_cast<ExprWithCleanups>(E))
256f85e193739c953358c865005855253af4f68a497John McCall              E = exprClean->getSubExpr();
257f85e193739c953358c865005855253af4f68a497John McCall
25843f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek            // Don't warn on C++ objects (yet) until we can show that their
25943f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek            // constructors/destructors don't have side effects.
26043f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek            if (isa<CXXConstructExpr>(E))
26143f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek              return;
262604d939ac15d1398761df313679673d30bb10f27Ted Kremenek
263fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek            // A dead initialization is a variable that is dead after it
264fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek            // is initialized.  We don't flag warnings for those variables
265fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek            // marked 'unused'.
266882998923889a2fcce9b49696506c499e22cf38fTed Kremenek            if (!Live.isLive(V) && V->getAttr<UnusedAttr>() == 0) {
267c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // Special case: check for initializations with constants.
268c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              //
269c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              //  e.g. : int x = 0;
270c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              //
271c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // If x is EVER assigned a new value later, don't issue
272c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // a warning.  This is because such initialization can be
273c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // due to defensive programming.
2744204f07fc8bffe6d320b2de95fea274ccf37a17bJohn McCall              if (E->isConstantInitializer(Ctx, false))
275d3098ee64c069a3eff4d2d0a5d655d968c7b5dd2Ted Kremenek                return;
2761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
277d3098ee64c069a3eff4d2d0a5d655d968c7b5dd2Ted Kremenek              if (DeclRefExpr *DRE=dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
278ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
279ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  // Special case: check for initialization from constant
280ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  variables.
281ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //
282ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  e.g. extern const int MyConstant;
283ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //       int x = MyConstant;
284ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //
285d3098ee64c069a3eff4d2d0a5d655d968c7b5dd2Ted Kremenek                  if (VD->hasGlobalStorage() &&
286ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                      VD->getType().isConstQualified())
287ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                    return;
288ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  // Special case: check for initialization from scalar
289ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  parameters.  This is often a form of defensive
290ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  programming.  Non-scalars are still an error since
291ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  because it more likely represents an actual algorithmic
292ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  bug.
293ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  if (isa<ParmVarDecl>(VD) && VD->getType()->isScalarType())
294ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                    return;
295ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                }
2961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
297d3098ee64c069a3eff4d2d0a5d655d968c7b5dd2Ted Kremenek              Report(V, DeadInit, V->getLocation(), E->getSourceRange());
298ce1cab9fc0b4aec9cdef1b30a14e4ccdca3ac5f1Ted Kremenek            }
299fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek          }
300852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek        }
301fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      }
3021ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek  }
3031ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek};
3041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3051ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek} // end anonymous namespace
3061ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
307d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek//===----------------------------------------------------------------------===//
308e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek// Driver function to invoke the Dead-Stores checker on a CFG.
309e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek//===----------------------------------------------------------------------===//
310e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
311f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremeneknamespace {
312ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass FindEscaped : public CFGRecStmtDeclVisitor<FindEscaped>{
313f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  CFG *cfg;
314f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenekpublic:
315f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  FindEscaped(CFG *c) : cfg(c) {}
3161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
317f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  CFG& getCFG() { return *cfg; }
3181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
319882998923889a2fcce9b49696506c499e22cf38fTed Kremenek  llvm::SmallPtrSet<const VarDecl*, 20> Escaped;
320f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek
321f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  void VisitUnaryOperator(UnaryOperator* U) {
322f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek    // Check for '&'.  Any VarDecl whose value has its address-taken we
323f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek    // treat as escaped.
3249c378f705405d37f49795d5e915989de774fe11fTed Kremenek    Expr *E = U->getSubExpr()->IgnoreParenCasts();
3252de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall    if (U->getOpcode() == UO_AddrOf)
3269c378f705405d37f49795d5e915989de774fe11fTed Kremenek      if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
3279c378f705405d37f49795d5e915989de774fe11fTed Kremenek        if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
328f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek          Escaped.insert(VD);
329f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek          return;
330f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek        }
331f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek    Visit(E);
332f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  }
333f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek};
334f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek} // end anonymous namespace
3351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
336f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek
3377dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
3387dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis// DeadStoresChecker
3397dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
3407dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis
3417dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidisnamespace {
342ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass DeadStoresChecker : public Checker<check::ASTCodeBody> {
3437dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidispublic:
3447dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
3457dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis                        BugReporter &BR) const {
3467dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis    if (LiveVariables *L = mgr.getLiveVariables(D)) {
3477dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis      CFG &cfg = *mgr.getCFG(D);
3487dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis      ParentMap &pmap = mgr.getParentMap(D);
3497dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis      FindEscaped FS(&cfg);
3507dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis      FS.getCFG().VisitBlockStmts(FS);
3517dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis      DeadStoreObs A(cfg, BR.getContext(), BR, pmap, FS.Escaped);
352882998923889a2fcce9b49696506c499e22cf38fTed Kremenek      L->runOnAllBlocks(A);
3537dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis    }
3547dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis  }
3557dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis};
3567dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis}
3577dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis
3587dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidisvoid ento::registerDeadStoresChecker(CheckerManager &mgr) {
3597dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis  mgr.registerChecker<DeadStoresChecker>();
360d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek}
361