DeadStoresChecker.cpp revision d1d8ddc5bae35610c243cc92812e72b83667d227
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//==- DeadStoresChecker.cpp - Check for stores to dead variables -*- C++ -*-==//
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//                     The LLVM Compiler Infrastructure
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// License. See LICENSE.TXT for details.
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===//
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//  This file defines a DeadStores, a flow-sensitive checker that looks for
1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//  stores to variables that are no longer live.
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===//
141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/Analysis/Analyses/LiveVariables.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/StaticAnalyzer/BugReporter/BugReporter.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/StaticAnalyzer/PathSensitive/ExprEngine.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "clang/Basic/Diagnostic.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/AST/ASTContext.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/AST/ParentMap.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "llvm/ADT/SmallPtrSet.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using namespace clang;
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using namespace ento;
286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)class DeadStoreObs : public LiveVariables::ObserverTy {
323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ASTContext &Ctx;
33c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  BugReporter& BR;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ParentMap& Parents;
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  llvm::SmallPtrSet<VarDecl*, 20> Escaped;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit };
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)public:
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeadStoreObs(ASTContext &ctx, BugReporter& br, ParentMap& parents,
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               llvm::SmallPtrSet<VarDecl*, 20> &escaped)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : Ctx(ctx), BR(br), Parents(parents), Escaped(escaped) {}
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~DeadStoreObs() {}
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Report(VarDecl* V, DeadStoreKind dsk, SourceLocation L, SourceRange R) {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (Escaped.count(V))
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string name = V->getNameAsString();
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char* BugType = 0;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string msg;
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (dsk) {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      default:
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        assert(false && "Impossible dead store type.");
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      case DeadInit:
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        BugType = "Dead initialization";
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        msg = "Value stored to '" + name +
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "' during its initialization is never read";
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        break;
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case DeadIncrement:
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BugType = "Dead increment";
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case Standard:
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (!BugType) BugType = "Dead assignment";
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        msg = "Value stored to '" + name + "' is never read";
703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        break;
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case Enclosing:
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Don't report issues in this case, e.g.: "if (x = foo())",
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // where 'x' is unused later.  We have yet to see a case where
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // this is a real bug.
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return;
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
7858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    BR.EmitBasicReport(BugType, "Dead store", msg, L, R);
8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void CheckVarDecl(VarDecl* VD, Expr* Ex, Expr* Val,
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                    DeadStoreKind dsk,
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    const LiveVariables::AnalysisDataTy& AD,
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    const LiveVariables::ValTy& Live) {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!VD->hasLocalStorage())
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Reference types confuse the dead stores checker.  Skip them
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // for now.
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (VD->getType()->getAs<ReferenceType>())
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!Live(VD, AD) &&
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        !(VD->getAttr<UnusedAttr>() || VD->getAttr<BlocksAttr>()))
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Report(VD, dsk, Ex->getSourceRange().getBegin(),
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             Val->getSourceRange());
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void CheckDeclRef(DeclRefExpr* DR, Expr* Val, DeadStoreKind dsk,
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    const LiveVariables::AnalysisDataTy& AD,
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    const LiveVariables::ValTy& Live) {
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()))
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CheckVarDecl(VD, DR, Val, dsk, AD, Live);
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool isIncrement(VarDecl* VD, BinaryOperator* B) {
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (B->isCompoundAssignmentOp())
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Expr* RHS = B->getRHS()->IgnoreParenCasts();
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS);
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!BRHS)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DeclRefExpr *DR;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getLHS()->IgnoreParenCasts())))
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (DR->getDecl() == VD)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return true;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getRHS()->IgnoreParenCasts())))
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (DR->getDecl() == VD)
12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        return true;
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void ObserveStmt(Stmt* S,
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           const LiveVariables::AnalysisDataTy& AD,
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           const LiveVariables::ValTy& Live) {
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Skip statements in macros.
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (S->getLocStart().isMacroID())
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!B->isAssignmentOp()) return; // Skip non-assignments.
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()))
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // Special case: check for assigning null to a pointer.
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          //  This is a common form of defensive programming.
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          QualType T = VD->getType();
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (T->isPointerType() || T->isObjCObjectPointerType()) {
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (B->getRHS()->isNullPointerConstant(Ctx,
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              Expr::NPC_ValueDependentIsNull))
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              return;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          Expr* RHS = B->getRHS()->IgnoreParenCasts();
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // Special case: self-assignments.  These are often used to shut up
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          //  "unused variable" compiler warnings.
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (DeclRefExpr* RhsDR = dyn_cast<DeclRefExpr>(RHS))
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (VD == dyn_cast<VarDecl>(RhsDR->getDecl()))
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              return;
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // Otherwise, issue a warning.
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          DeadStoreKind dsk = Parents.isConsumedExpr(B)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              ? Enclosing
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              : (isIncrement(VD,B) ? DeadIncrement : Standard);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          CheckVarDecl(VD, DR, B->getRHS(), dsk, AD, Live);
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else if (UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!U->isIncrementOp())
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Handle: ++x within a subexpression.  The solution is not warn
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      //  about preincrements to dead variables when the preincrement occurs
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      //  as a subexpression.  This can lead to false negatives, e.g. "(++x);"
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      //  A generalized dead code checker should find such issues.
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (U->isPrefix() && Parents.isConsumedExpr(U))
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Expr *Ex = U->getSubExpr()->IgnoreParenCasts();
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(Ex))
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        CheckDeclRef(DR, U, DeadIncrement, AD, Live);
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Iterate through the decls.  Warn if any initializers are complex
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // expressions that are not live (never used).
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           DI != DE; ++DI) {
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        VarDecl* V = dyn_cast<VarDecl>(*DI);
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!V)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          continue;
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (V->hasLocalStorage()) {
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // Reference types confuse the dead stores checker.  Skip them
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // for now.
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (V->getType()->getAs<ReferenceType>())
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return;
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (Expr* E = V->getInit()) {
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // Don't warn on C++ objects (yet) until we can show that their
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // constructors/destructors don't have side effects.
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (isa<CXXConstructExpr>(E))
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              return;
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (isa<ExprWithCleanups>(E))
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              return;
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // A dead initialization is a variable that is dead after it
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // is initialized.  We don't flag warnings for those variables
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // marked 'unused'.
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (!Live(V, AD) && V->getAttr<UnusedAttr>() == 0) {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              // Special case: check for initializations with constants.
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              //
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              //  e.g. : int x = 0;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              //
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              // If x is EVER assigned a new value later, don't issue
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              // a warning.  This is because such initialization can be
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              // due to defensive programming.
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              if (E->isConstantInitializer(Ctx, false))
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                return;
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              if (DeclRefExpr *DRE=dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  // Special case: check for initialization from constant
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  //  variables.
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  //
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  //  e.g. extern const int MyConstant;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  //       int x = MyConstant;
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  //
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  if (VD->hasGlobalStorage() &&
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      VD->getType().isConstQualified())
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    return;
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  // Special case: check for initialization from scalar
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  //  parameters.  This is often a form of defensive
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  //  programming.  Non-scalars are still an error since
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  //  because it more likely represents an actual algorithmic
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  //  bug.
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  if (isa<ParmVarDecl>(VD) && VD->getType()->isScalarType())
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    return;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                }
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              Report(V, DeadInit, V->getLocation(), E->getSourceRange());
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // end anonymous namespace
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===//
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Driver function to invoke the Dead-Stores checker on a CFG.
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===//
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class FindEscaped : public CFGRecStmtDeclVisitor<FindEscaped>{
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CFG *cfg;
26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)public:
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FindEscaped(CFG *c) : cfg(c) {}
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CFG& getCFG() { return *cfg; }
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  llvm::SmallPtrSet<VarDecl*, 20> Escaped;
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void VisitUnaryOperator(UnaryOperator* U) {
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Check for '&'.  Any VarDecl whose value has its address-taken we
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // treat as escaped.
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Expr* E = U->getSubExpr()->IgnoreParenCasts();
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (U->getOpcode() == UO_AddrOf)
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E))
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) {
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          Escaped.insert(VD);
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          return;
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Visit(E);
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // end anonymous namespace
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ento::CheckDeadStores(CFG &cfg, LiveVariables &L, ParentMap &pmap,
28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            BugReporter& BR) {
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FindEscaped FS(&cfg);
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FS.getCFG().VisitBlockStmts(FS);
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeadStoreObs A(BR.getContext(), BR, pmap, FS.Escaped);
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  L.runOnAllBlocks(cfg, &A);
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch