DeadStoresChecker.cpp revision 1a654b60ef40e84f3943cdb581795c4d4dae1e45
11ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//==- DeadStores.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
151ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek#include "clang/Analysis/LocalCheckers.h"
16cf6e41baf2b23b6b56f0f79fff5554b7745737acTed Kremenek#include "clang/Analysis/Analyses/LiveVariables.h"
17fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
18d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek#include "clang/Analysis/PathSensitive/BugReporter.h"
19d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek#include "clang/Analysis/PathSensitive/GRExprEngine.h"
201ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek#include "clang/Basic/Diagnostic.h"
21ce1cab9fc0b4aec9cdef1b30a14e4ccdca3ac5f1Ted Kremenek#include "clang/AST/ASTContext.h"
221a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek#include "clang/AST/ParentMap.h"
23c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenek#include "llvm/Support/Compiler.h"
241ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
251ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenekusing namespace clang;
261ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
271ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremeneknamespace {
281a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
29c2b51d8cf33bed92b68ee0a8e3c28411e43faffdTed Kremenekclass VISIBILITY_HIDDEN DeadStoreObs : public LiveVariables::ObserverTy {
30c0508f9fe37a3afb1ccad39879348272545e55dbChris Lattner  ASTContext &Ctx;
31c0508f9fe37a3afb1ccad39879348272545e55dbChris Lattner  Diagnostic &Diags;
32d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  DiagnosticClient &Client;
331a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek  ParentMap& Parents;
341a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
351ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenekpublic:
361a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek  DeadStoreObs(ASTContext &ctx, Diagnostic &diags, DiagnosticClient &client,
371a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek               ParentMap& parents)
381a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek    : Ctx(ctx), Diags(diags), Client(client), Parents(parents) {}
39d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
40fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek  virtual ~DeadStoreObs() {}
41fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek
421a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek  unsigned GetDiag(VarDecl* VD, bool inEnclosing = false) {
431a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek    std::string name(VD->getName());
441a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
451a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek    std::string msg = inEnclosing
461a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek      ? "Although the value stored to '" + name +
471a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek        "' is used in the enclosing expression, the value is never actually read"
481a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek        " from '" + name + "'"
491a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek      : "Value stored to '" + name + "' is never read";
50c07ba352b7604435e80269be23ace72a52bd04f1Ted Kremenek
511a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek    return Diags.getCustomDiagID(Diagnostic::Warning, msg.c_str());
521a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek  }
531a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
541a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek  void CheckVarDecl(VarDecl* VD, Expr* Ex, Expr* Val,
551a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek                    bool hasEnclosing,
561a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek                    const LiveVariables::AnalysisDataTy& AD,
571a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek                    const LiveVariables::ValTy& Live) {
581a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
591a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek    if (VD->hasLocalStorage() && !Live(VD, AD)) {
601a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek      SourceRange R = Val->getSourceRange();
611a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek      Diags.Report(&Client,
621a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek                   Ctx.getFullLoc(Ex->getSourceRange().getBegin()),
631a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek                   GetDiag(VD, hasEnclosing), 0, 0, &R, 1);
641a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek    }
653eb817e5095d25e7bf4a8df9ed3f9b13bed6f298Ted Kremenek  }
663eb817e5095d25e7bf4a8df9ed3f9b13bed6f298Ted Kremenek
67a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek  void CheckDeclRef(DeclRefExpr* DR, Expr* Val,
68a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek                    const LiveVariables::AnalysisDataTy& AD,
69a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek                    const LiveVariables::ValTy& Live) {
70a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek
71a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek    if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()))
721a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek      CheckVarDecl(VD, DR, Val, false, AD, Live);
73a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek  }
74a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek
75fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek  virtual void ObserveStmt(Stmt* S,
76fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek                           const LiveVariables::AnalysisDataTy& AD,
77fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek                           const LiveVariables::ValTy& Live) {
78ce1cab9fc0b4aec9cdef1b30a14e4ccdca3ac5f1Ted Kremenek
791c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek    // Skip statements in macros.
801c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek    if (S->getLocStart().isMacroID())
811c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek      return;
821c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek
831ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek    if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
84fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      if (!B->isAssignmentOp()) return; // Skip non-assignments.
851ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
86c0576ca6c6ba136e583985041bd324b0acc38f40Ted Kremenek      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()))
871a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek        if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
881a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
891a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek          // Special case: check for assigning null to a pointer.  This
901a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek          //  is a common form of defensive programming.
911a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek          // FIXME: Make this optional?
921a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
931a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek          Expr* Val = B->getRHS();
941a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek          llvm::APSInt Result(Ctx.getTypeSize(Val->getType()));
951a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
961a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek          if (VD->getType()->isPointerType() &&
971a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek              Val->IgnoreParenCasts()->isIntegerConstantExpr(Result, Ctx, 0))
981a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek            if (Result == 0)
991a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek              return;
1001a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
1011a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek          CheckVarDecl(VD, DR, Val, Parents.isSubExpr(B), AD, Live);
1021a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek        }
1031ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek    }
104a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek    else if (UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
105a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek      if (!U->isIncrementOp())
106a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek        return;
107a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek
108a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek      Expr *Ex = U->getSubExpr()->IgnoreParenCasts();
109a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek
110a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(Ex))
111a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek        CheckDeclRef(DR, U, AD, Live);
112a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek    }
113a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek    else if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
114fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      // Iterate through the decls.  Warn if any initializers are complex
115fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      // expressions that are not live (never used).
116c967c9d9011a9907e05a5c908ec0b7d2e7f3a11dTed Kremenek      for (ScopedDecl* SD = DS->getDecl(); SD; SD = SD->getNextDeclarator()) {
117c967c9d9011a9907e05a5c908ec0b7d2e7f3a11dTed Kremenek
118c967c9d9011a9907e05a5c908ec0b7d2e7f3a11dTed Kremenek        VarDecl* V = dyn_cast<VarDecl>(SD);
119c967c9d9011a9907e05a5c908ec0b7d2e7f3a11dTed Kremenek        if (!V) continue;
120c967c9d9011a9907e05a5c908ec0b7d2e7f3a11dTed Kremenek
121c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek        if (V->hasLocalStorage())
122c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek          if (Expr* E = V->getInit()) {
1239d7af51f0f253e555bff391f7409d5826f5184fbTed Kremenek            if (!Live(V, AD)) {
124c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // Special case: check for initializations with constants.
125c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              //
126c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              //  e.g. : int x = 0;
127c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              //
128c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // If x is EVER assigned a new value later, don't issue
129c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // a warning.  This is because such initialization can be
130c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // due to defensive programming.
131c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              if (!E->isConstantExpr(Ctx,NULL)) {
132c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek                // Flag a warning.
133c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek                SourceRange R = E->getSourceRange();
134d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek                Diags.Report(&Client,
135d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek                             Ctx.getFullLoc(V->getLocation()),
1363eb817e5095d25e7bf4a8df9ed3f9b13bed6f298Ted Kremenek                             GetDiag(V), 0, 0, &R, 1);
137c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              }
138ce1cab9fc0b4aec9cdef1b30a14e4ccdca3ac5f1Ted Kremenek            }
139fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek          }
140fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      }
1411ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek  }
1421ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek};
1431ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
1441ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek} // end anonymous namespace
1451ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
146d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek//===----------------------------------------------------------------------===//
147d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek// Driver function to invoke the Dead-Stores checker on a CFG.
148d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek//===----------------------------------------------------------------------===//
1491ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
1501a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenekvoid clang::CheckDeadStores(CFG& cfg, ASTContext &Ctx,
1511a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek                            ParentMap& Parents, Diagnostic &Diags) {
1527cb15939e08ea31f0fadcd24c974dbc9e4b61c01Ted Kremenek  LiveVariables L(cfg);
1531ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek  L.runOnCFG(cfg);
1541a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek  DeadStoreObs A(Ctx, Diags, Diags.getClient(), Parents);
1557cb15939e08ea31f0fadcd24c974dbc9e4b61c01Ted Kremenek  L.runOnAllBlocks(cfg, &A);
1561ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek}
1571ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
158d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek//===----------------------------------------------------------------------===//
159d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek// BugReporter-based invocation of the Dead-Stores checker.
160d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek//===----------------------------------------------------------------------===//
161d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
162d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremeneknamespace {
163d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
164d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenekclass VISIBILITY_HIDDEN DiagBugReport : public RangedBugReport {
165d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  std::list<std::string> Strs;
166d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  FullSourceLoc L;
167d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenekpublic:
16895cc1bae89ac68626d6f4d389e189ce1ef3aa7f6Ted Kremenek  DiagBugReport(BugType& D, FullSourceLoc l) :
169d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek    RangedBugReport(D, NULL), L(l) {}
170d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
171d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  virtual ~DiagBugReport() {}
172d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  virtual FullSourceLoc getLocation(SourceManager&) { return L; }
173d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
174d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  void addString(const std::string& s) { Strs.push_back(s); }
175d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
176d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  typedef std::list<std::string>::const_iterator str_iterator;
177d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  str_iterator str_begin() const { return Strs.begin(); }
178d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  str_iterator str_end() const { return Strs.end(); }
179d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek};
180d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
181d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenekclass VISIBILITY_HIDDEN DiagCollector : public DiagnosticClient {
182d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  std::list<DiagBugReport> Reports;
18395cc1bae89ac68626d6f4d389e189ce1ef3aa7f6Ted Kremenek  BugType& D;
184d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenekpublic:
185d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  DiagCollector(BugType& d) : D(d) {}
186d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
187d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  virtual ~DiagCollector() {}
188d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
189d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  virtual void HandleDiagnostic(Diagnostic &Diags,
190d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek                                Diagnostic::Level DiagLevel,
191d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek                                FullSourceLoc Pos,
192d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek                                diag::kind ID,
193d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek                                const std::string *Strs,
194d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek                                unsigned NumStrs,
195d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek                                const SourceRange *Ranges,
196d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek                                unsigned NumRanges) {
197d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
198d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek    // FIXME: Use a map from diag::kind to BugType, instead of having just
199d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek    //  one BugType.
200d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
201d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek    Reports.push_back(DiagBugReport(D, Pos));
202d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek    DiagBugReport& R = Reports.back();
203d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
204d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek    for ( ; NumRanges ; --NumRanges, ++Ranges)
205d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek      R.addRange(*Ranges);
206d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
207d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek    for ( ; NumStrs ; --NumStrs, ++Strs)
208d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek      R.addString(*Strs);
209d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  }
210d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
211d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  // Iterators.
212d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
213d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  typedef std::list<DiagBugReport>::iterator iterator;
214d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  iterator begin() { return Reports.begin(); }
215d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  iterator end() { return Reports.end(); }
216d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek};
217d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
21895cc1bae89ac68626d6f4d389e189ce1ef3aa7f6Ted Kremenekclass VISIBILITY_HIDDEN DeadStoresChecker : public BugTypeCacheLocation {
219d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenekpublic:
220d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  virtual const char* getName() const {
221d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek    return "dead store";
222d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  }
223d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
224d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  virtual const char* getDescription() const {
2251d5d1da8c3cb3e697d21d05e6dc7f08df8814a2cTed Kremenek    return "Value stored to variable is never subsequently read.";
226d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  }
227d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
228d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  virtual void EmitWarnings(BugReporter& BR) {
229d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
230d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek    // Run the dead store checker and collect the diagnostics.
231d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek    DiagCollector C(*this);
2321a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek    DeadStoreObs A(BR.getContext(), BR.getDiagnostic(), C, BR.getParentMap());
2331a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
2341a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek    GRExprEngine& Eng = BR.getEngine();
2351a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek    Eng.getLiveness().runOnAllBlocks(BR.getCFG(), &A);
236d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
237d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek    // Emit the bug reports.
238d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
239d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek    for (DiagCollector::iterator I = C.begin(), E = C.end(); I != E; ++I)
240d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek      BR.EmitWarning(*I);
241d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  }
242d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek};
243d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek} // end anonymous namespace
244d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek
245d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed KremenekBugType* clang::MakeDeadStoresChecker() {
246d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek  return new DeadStoresChecker();
247d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek}
248