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