1 //==- DeadStoresChecker.cpp - Check for stores to dead variables -*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines a DeadStores, a flow-sensitive checker that looks for
11 // stores to variables that are no longer live.
13 //===----------------------------------------------------------------------===//
15 #include "ClangSACheckers.h"
16 #include "clang/StaticAnalyzer/Core/Checker.h"
17 #include "clang/Analysis/Analyses/LiveVariables.h"
18 #include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
19 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
20 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
21 #include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
22 #include "clang/Basic/Diagnostic.h"
23 #include "clang/AST/ASTContext.h"
24 #include "clang/AST/ParentMap.h"
25 #include "llvm/ADT/SmallPtrSet.h"
27 using namespace clang;
32 // FIXME: Eventually migrate into its own file, and have it managed by
36 llvm::BitVector reachable;
38 ReachableCode(const CFG &cfg)
39 : cfg(cfg), reachable(cfg.getNumBlockIDs(), false) {}
41 void computeReachableBlocks();
43 bool isReachable(const CFGBlock *block) const {
44 return reachable[block->getBlockID()];
49 void ReachableCode::computeReachableBlocks() {
50 if (!cfg.getNumBlockIDs())
53 llvm::SmallVector<const CFGBlock*, 10> worklist;
54 worklist.push_back(&cfg.getEntry());
56 while (!worklist.empty()) {
57 const CFGBlock *block = worklist.back();
59 llvm::BitVector::reference isReachable = reachable[block->getBlockID()];
63 for (CFGBlock::const_succ_iterator i = block->succ_begin(),
64 e = block->succ_end(); i != e; ++i)
65 if (const CFGBlock *succ = *i)
66 worklist.push_back(succ);
71 class DeadStoreObs : public LiveVariables::ObserverTy {
76 llvm::SmallPtrSet<VarDecl*, 20> Escaped;
77 llvm::OwningPtr<ReachableCode> reachableCode;
78 const CFGBlock *currentBlock;
80 enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit };
83 DeadStoreObs(const CFG &cfg, ASTContext &ctx,
84 BugReporter& br, ParentMap& parents,
85 llvm::SmallPtrSet<VarDecl*, 20> &escaped)
86 : cfg(cfg), Ctx(ctx), BR(br), Parents(parents),
87 Escaped(escaped), currentBlock(0) {}
89 virtual ~DeadStoreObs() {}
91 void Report(VarDecl* V, DeadStoreKind dsk, SourceLocation L, SourceRange R) {
95 // Compute reachable blocks within the CFG for trivial cases
96 // where a bogus dead store can be reported because itself is unreachable.
97 if (!reachableCode.get()) {
98 reachableCode.reset(new ReachableCode(cfg));
99 reachableCode->computeReachableBlocks();
102 if (!reachableCode->isReachable(currentBlock))
105 const std::string &name = V->getNameAsString();
107 const char* BugType = 0;
112 assert(false && "Impossible dead store type.");
115 BugType = "Dead initialization";
116 msg = "Value stored to '" + name +
117 "' during its initialization is never read";
121 BugType = "Dead increment";
123 if (!BugType) BugType = "Dead assignment";
124 msg = "Value stored to '" + name + "' is never read";
128 // Don't report issues in this case, e.g.: "if (x = foo())",
129 // where 'x' is unused later. We have yet to see a case where
130 // this is a real bug.
134 BR.EmitBasicReport(BugType, "Dead store", msg, L, R);
137 void CheckVarDecl(VarDecl* VD, Expr* Ex, Expr* Val,
139 const LiveVariables::AnalysisDataTy& AD,
140 const LiveVariables::ValTy& Live) {
142 if (!VD->hasLocalStorage())
144 // Reference types confuse the dead stores checker. Skip them
146 if (VD->getType()->getAs<ReferenceType>())
150 !(VD->getAttr<UnusedAttr>() || VD->getAttr<BlocksAttr>()))
151 Report(VD, dsk, Ex->getSourceRange().getBegin(),
152 Val->getSourceRange());
155 void CheckDeclRef(DeclRefExpr* DR, Expr* Val, DeadStoreKind dsk,
156 const LiveVariables::AnalysisDataTy& AD,
157 const LiveVariables::ValTy& Live) {
158 if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()))
159 CheckVarDecl(VD, DR, Val, dsk, AD, Live);
162 bool isIncrement(VarDecl* VD, BinaryOperator* B) {
163 if (B->isCompoundAssignmentOp())
166 Expr* RHS = B->getRHS()->IgnoreParenCasts();
167 BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS);
174 if ((DR = dyn_cast<DeclRefExpr>(BRHS->getLHS()->IgnoreParenCasts())))
175 if (DR->getDecl() == VD)
178 if ((DR = dyn_cast<DeclRefExpr>(BRHS->getRHS()->IgnoreParenCasts())))
179 if (DR->getDecl() == VD)
185 virtual void ObserveStmt(Stmt* S, const CFGBlock *block,
186 const LiveVariables::AnalysisDataTy& AD,
187 const LiveVariables::ValTy& Live) {
189 currentBlock = block;
191 // Skip statements in macros.
192 if (S->getLocStart().isMacroID())
195 // Only cover dead stores from regular assignments. ++/-- dead stores
196 // have never flagged a real bug.
197 if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
198 if (!B->isAssignmentOp()) return; // Skip non-assignments.
200 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()))
201 if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
202 // Special case: check for assigning null to a pointer.
203 // This is a common form of defensive programming.
204 QualType T = VD->getType();
205 if (T->isPointerType() || T->isObjCObjectPointerType()) {
206 if (B->getRHS()->isNullPointerConstant(Ctx,
207 Expr::NPC_ValueDependentIsNull))
211 Expr* RHS = B->getRHS()->IgnoreParenCasts();
212 // Special case: self-assignments. These are often used to shut up
213 // "unused variable" compiler warnings.
214 if (DeclRefExpr* RhsDR = dyn_cast<DeclRefExpr>(RHS))
215 if (VD == dyn_cast<VarDecl>(RhsDR->getDecl()))
218 // Otherwise, issue a warning.
219 DeadStoreKind dsk = Parents.isConsumedExpr(B)
221 : (isIncrement(VD,B) ? DeadIncrement : Standard);
223 CheckVarDecl(VD, DR, B->getRHS(), dsk, AD, Live);
226 else if (UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
227 if (!U->isIncrementOp() || U->isPrefix())
230 Stmt *parent = Parents.getParentIgnoreParenCasts(U);
231 if (!parent || !isa<ReturnStmt>(parent))
234 Expr *Ex = U->getSubExpr()->IgnoreParenCasts();
236 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(Ex))
237 CheckDeclRef(DR, U, DeadIncrement, AD, Live);
239 else if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
240 // Iterate through the decls. Warn if any initializers are complex
241 // expressions that are not live (never used).
242 for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
245 VarDecl* V = dyn_cast<VarDecl>(*DI);
250 if (V->hasLocalStorage()) {
251 // Reference types confuse the dead stores checker. Skip them
253 if (V->getType()->getAs<ReferenceType>())
256 if (Expr* E = V->getInit()) {
257 while (ExprWithCleanups *exprClean = dyn_cast<ExprWithCleanups>(E))
258 E = exprClean->getSubExpr();
260 // Don't warn on C++ objects (yet) until we can show that their
261 // constructors/destructors don't have side effects.
262 if (isa<CXXConstructExpr>(E))
265 // A dead initialization is a variable that is dead after it
266 // is initialized. We don't flag warnings for those variables
268 if (!Live(V, AD) && V->getAttr<UnusedAttr>() == 0) {
269 // Special case: check for initializations with constants.
273 // If x is EVER assigned a new value later, don't issue
274 // a warning. This is because such initialization can be
275 // due to defensive programming.
276 if (E->isConstantInitializer(Ctx, false))
279 if (DeclRefExpr *DRE=dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
280 if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
281 // Special case: check for initialization from constant
284 // e.g. extern const int MyConstant;
285 // int x = MyConstant;
287 if (VD->hasGlobalStorage() &&
288 VD->getType().isConstQualified())
290 // Special case: check for initialization from scalar
291 // parameters. This is often a form of defensive
292 // programming. Non-scalars are still an error since
293 // because it more likely represents an actual algorithmic
295 if (isa<ParmVarDecl>(VD) && VD->getType()->isScalarType())
299 Report(V, DeadInit, V->getLocation(), E->getSourceRange());
307 } // end anonymous namespace
309 //===----------------------------------------------------------------------===//
310 // Driver function to invoke the Dead-Stores checker on a CFG.
311 //===----------------------------------------------------------------------===//
314 class FindEscaped : public CFGRecStmtDeclVisitor<FindEscaped>{
317 FindEscaped(CFG *c) : cfg(c) {}
319 CFG& getCFG() { return *cfg; }
321 llvm::SmallPtrSet<VarDecl*, 20> Escaped;
323 void VisitUnaryOperator(UnaryOperator* U) {
324 // Check for '&'. Any VarDecl whose value has its address-taken we
326 Expr* E = U->getSubExpr()->IgnoreParenCasts();
327 if (U->getOpcode() == UO_AddrOf)
328 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E))
329 if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) {
336 } // end anonymous namespace
339 //===----------------------------------------------------------------------===//
341 //===----------------------------------------------------------------------===//
344 class DeadStoresChecker : public Checker<check::ASTCodeBody> {
346 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
347 BugReporter &BR) const {
348 if (LiveVariables *L = mgr.getLiveVariables(D)) {
349 CFG &cfg = *mgr.getCFG(D);
350 ParentMap &pmap = mgr.getParentMap(D);
351 FindEscaped FS(&cfg);
352 FS.getCFG().VisitBlockStmts(FS);
353 DeadStoreObs A(cfg, BR.getContext(), BR, pmap, FS.Escaped);
354 L->runOnAllBlocks(cfg, &A);
360 void ento::registerDeadStoresChecker(CheckerManager &mgr) {
361 mgr.registerChecker<DeadStoresChecker>();