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