DeadStoresChecker.cpp revision 561d3abc881033776ece385a01a510e1cbc1fa92
16e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//==- DeadStoresChecker.cpp - Check for stores to dead variables -*- C++ -*-==// 26e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// 36e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// The LLVM Compiler Infrastructure 46e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// 56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 66e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// License. See LICENSE.TXT for details. 76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// 86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//===----------------------------------------------------------------------===// 96e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// 106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// This file defines a DeadStores, a flow-sensitive checker that looks for 116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// stores to variables that are no longer live. 126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// 136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//===----------------------------------------------------------------------===// 146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ClangSACheckers.h" 166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/Checker.h" 176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/Analysis/Analyses/LiveVariables.h" 186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h" 196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h" 226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/Basic/Diagnostic.h" 236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/AST/ASTContext.h" 246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "clang/AST/ParentMap.h" 256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "llvm/ADT/SmallPtrSet.h" 266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)using namespace clang; 286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)using namespace ento; 296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace { 316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// FIXME: Eventually migrate into its own file, and have it managed by 336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// AnalysisManager. 346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class ReachableCode { 356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const CFG &cfg; 366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) llvm::BitVector reachable; 376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)public: 386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ReachableCode(const CFG &cfg) 396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) : cfg(cfg), reachable(cfg.getNumBlockIDs(), false) {} 406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void computeReachableBlocks(); 426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool isReachable(const CFGBlock *block) const { 446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return reachable[block->getBlockID()]; 456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}; 476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ReachableCode::computeReachableBlocks() { 506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!cfg.getNumBlockIDs()) 516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SmallVector<const CFGBlock*, 10> worklist; 546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) worklist.push_back(&cfg.getEntry()); 556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) while (!worklist.empty()) { 576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const CFGBlock *block = worklist.back(); 586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) worklist.pop_back(); 596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) llvm::BitVector::reference isReachable = reachable[block->getBlockID()]; 606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (isReachable) 616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) continue; 626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) isReachable = true; 636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (CFGBlock::const_succ_iterator i = block->succ_begin(), 646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) e = block->succ_end(); i != e; ++i) 656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (const CFGBlock *succ = *i) 666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) worklist.push_back(succ); 676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace { 716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class DeadStoreObs : public LiveVariables::Observer { 726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const CFG &cfg; 736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ASTContext &Ctx; 746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BugReporter& BR; 756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) AnalysisDeclContext* AC; 766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ParentMap& Parents; 776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) llvm::SmallPtrSet<const VarDecl*, 20> Escaped; 786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) llvm::OwningPtr<ReachableCode> reachableCode; 796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const CFGBlock *currentBlock; 806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit }; 826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)public: 846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DeadStoreObs(const CFG &cfg, ASTContext &ctx, 856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BugReporter& br, AnalysisDeclContext* ac, ParentMap& parents, 866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) llvm::SmallPtrSet<const VarDecl*, 20> &escaped) 876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) : cfg(cfg), Ctx(ctx), BR(br), AC(ac), Parents(parents), 886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Escaped(escaped), currentBlock(0) {} 896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) virtual ~DeadStoreObs() {} 916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void Report(const VarDecl *V, DeadStoreKind dsk, 936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) PathDiagnosticLocation L, SourceRange R) { 946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (Escaped.count(V)) 956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Compute reachable blocks within the CFG for trivial cases 986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // where a bogus dead store can be reported because itself is unreachable. 996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!reachableCode.get()) { 1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) reachableCode.reset(new ReachableCode(cfg)); 1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) reachableCode->computeReachableBlocks(); 1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!reachableCode->isReachable(currentBlock)) 1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) llvm::SmallString<64> buf; 1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) llvm::raw_svector_ostream os(buf); 1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const char *BugType = 0; 1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) switch (dsk) { 1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DeadInit: 1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BugType = "Dead initialization"; 1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) os << "Value stored to '" << *V 1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) << "' during its initialization is never read"; 1166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case DeadIncrement: 1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BugType = "Dead increment"; 1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case Standard: 1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!BugType) BugType = "Dead assignment"; 1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) os << "Value stored to '" << *V << "' is never read"; 1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case Enclosing: 1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Don't report issues in this case, e.g.: "if (x = foo())", 1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // where 'x' is unused later. We have yet to see a case where 1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // this is a real bug. 1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BR.EmitBasicReport(BugType, "Dead store", os.str(), L, R); 1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void CheckVarDecl(const VarDecl *VD, const Expr *Ex, const Expr *Val, 1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DeadStoreKind dsk, 1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const LiveVariables::LivenessValues &Live) { 1386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!VD->hasLocalStorage()) 1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Reference types confuse the dead stores checker. Skip them 1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // for now. 1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (VD->getType()->getAs<ReferenceType>()) 1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!Live.isLive(VD) && 1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) !(VD->getAttr<UnusedAttr>() || VD->getAttr<BlocksAttr>())) { 1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) PathDiagnosticLocation ExLoc = 1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) PathDiagnosticLocation::createBegin(Ex, BR.getSourceManager(), AC); 1516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Report(VD, dsk, ExLoc, Val->getSourceRange()); 1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void CheckDeclRef(const DeclRefExpr *DR, const Expr *Val, DeadStoreKind dsk, 1566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const LiveVariables::LivenessValues& Live) { 1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) 1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CheckVarDecl(VD, DR, Val, dsk, Live); 1596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool isIncrement(VarDecl *VD, const BinaryOperator* B) { 1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (B->isCompoundAssignmentOp()) 1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return true; 1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const Expr *RHS = B->getRHS()->IgnoreParenCasts(); 1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS); 1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!BRHS) 1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return false; 1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const DeclRefExpr *DR; 1726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if ((DR = dyn_cast<DeclRefExpr>(BRHS->getLHS()->IgnoreParenCasts()))) 1746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (DR->getDecl() == VD) 1756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return true; 1766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if ((DR = dyn_cast<DeclRefExpr>(BRHS->getRHS()->IgnoreParenCasts()))) 1786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (DR->getDecl() == VD) 1796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return true; 1806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return false; 1826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) virtual void observeStmt(const Stmt *S, const CFGBlock *block, 1856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const LiveVariables::LivenessValues &Live) { 1866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) currentBlock = block; 1886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Skip statements in macros. 1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (S->getLocStart().isMacroID()) 1916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 1926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Only cover dead stores from regular assignments. ++/-- dead stores 1946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // have never flagged a real bug. 1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { 1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!B->isAssignmentOp()) return; // Skip non-assignments. 1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(B->getLHS())) 1996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 2006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Special case: check for assigning null to a pointer. 2016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // This is a common form of defensive programming. 2026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) QualType T = VD->getType(); 2036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (T->isPointerType() || T->isObjCObjectPointerType()) { 2046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (B->getRHS()->isNullPointerConstant(Ctx, 2056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Expr::NPC_ValueDependentIsNull)) 2066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Expr *RHS = B->getRHS()->IgnoreParenCasts(); 2106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Special case: self-assignments. These are often used to shut up 2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // "unused variable" compiler warnings. 2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (DeclRefExpr *RhsDR = dyn_cast<DeclRefExpr>(RHS)) 2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (VD == dyn_cast<VarDecl>(RhsDR->getDecl())) 2146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 2156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Otherwise, issue a warning. 2176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DeadStoreKind dsk = Parents.isConsumedExpr(B) 2186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ? Enclosing 2196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) : (isIncrement(VD,B) ? DeadIncrement : Standard); 2206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CheckVarDecl(VD, DR, B->getRHS(), dsk, Live); 2226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) else if (const UnaryOperator* U = dyn_cast<UnaryOperator>(S)) { 2256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!U->isIncrementOp() || U->isPrefix()) 2266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 2276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const Stmt *parent = Parents.getParentIgnoreParenCasts(U); 2296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!parent || !isa<ReturnStmt>(parent)) 2306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 2316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const Expr *Ex = U->getSubExpr()->IgnoreParenCasts(); 2336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) 2356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CheckDeclRef(DR, U, DeadIncrement, Live); 2366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) 2386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Iterate through the decls. Warn if any initializers are complex 2396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // expressions that are not live (never used). 2406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (DeclStmt::const_decl_iterator DI=DS->decl_begin(), DE=DS->decl_end(); 2416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DI != DE; ++DI) { 2426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VarDecl *V = dyn_cast<VarDecl>(*DI); 2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!V) 2466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) continue; 2476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (V->hasLocalStorage()) { 2496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Reference types confuse the dead stores checker. Skip them 2506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // for now. 2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (V->getType()->getAs<ReferenceType>()) 2526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 2536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (Expr *E = V->getInit()) { 2556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) while (ExprWithCleanups *exprClean = dyn_cast<ExprWithCleanups>(E)) 2566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) E = exprClean->getSubExpr(); 2576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Don't warn on C++ objects (yet) until we can show that their 2596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // constructors/destructors don't have side effects. 2606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (isa<CXXConstructExpr>(E)) 2616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 2626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // A dead initialization is a variable that is dead after it 2646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // is initialized. We don't flag warnings for those variables 2656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // marked 'unused'. 2666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!Live.isLive(V) && V->getAttr<UnusedAttr>() == 0) { 2676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Special case: check for initializations with constants. 2686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // 2696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // e.g. : int x = 0; 2706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // 2716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // If x is EVER assigned a new value later, don't issue 2726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // a warning. This is because such initialization can be 2736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // due to defensive programming. 2746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (E->isEvaluatable(Ctx)) 2756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 2766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (DeclRefExpr *DRE=dyn_cast<DeclRefExpr>(E->IgnoreParenCasts())) 2786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) { 2796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Special case: check for initialization from constant 2806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // variables. 2816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // 2826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // e.g. extern const int MyConstant; 2836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // int x = MyConstant; 2846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // 2856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (VD->hasGlobalStorage() && 2866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VD->getType().isConstQualified()) 2876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 2886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Special case: check for initialization from scalar 2896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // parameters. This is often a form of defensive 2906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // programming. Non-scalars are still an error since 2916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // because it more likely represents an actual algorithmic 2926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // bug. 2936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (isa<ParmVarDecl>(VD) && VD->getType()->isScalarType()) 2946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 2956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) PathDiagnosticLocation Loc = 2986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) PathDiagnosticLocation::create(V, BR.getSourceManager()); 2996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Report(V, DeadInit, Loc, E->getSourceRange()); 3006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}; 3066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} // end anonymous namespace 3086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//===----------------------------------------------------------------------===// 3106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Driver function to invoke the Dead-Stores checker on a CFG. 3116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//===----------------------------------------------------------------------===// 3126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace { 3146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class FindEscaped : public CFGRecStmtDeclVisitor<FindEscaped>{ 3156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CFG *cfg; 3166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)public: 3176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) FindEscaped(CFG *c) : cfg(c) {} 3186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CFG& getCFG() { return *cfg; } 3206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) llvm::SmallPtrSet<const VarDecl*, 20> Escaped; 3226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void VisitUnaryOperator(UnaryOperator* U) { 3246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Check for '&'. Any VarDecl whose value has its address-taken we 3256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // treat as escaped. 3266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Expr *E = U->getSubExpr()->IgnoreParenCasts(); 3276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (U->getOpcode() == UO_AddrOf) 3286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) 3296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 3306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Escaped.insert(VD); 3316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 3326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Visit(E); 3346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}; 3366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} // end anonymous namespace 3376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//===----------------------------------------------------------------------===// 3406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// DeadStoresChecker 3416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)//===----------------------------------------------------------------------===// 3426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace { 3446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class DeadStoresChecker : public Checker<check::ASTCodeBody> { 3456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)public: 3466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 3476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BugReporter &BR) const { 3486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (LiveVariables *L = mgr.getAnalysis<LiveVariables>(D)) { 3496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CFG &cfg = *mgr.getCFG(D); 3506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D); 3516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ParentMap &pmap = mgr.getParentMap(D); 3526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) FindEscaped FS(&cfg); 3536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) FS.getCFG().VisitBlockStmts(FS); 3546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DeadStoreObs A(cfg, BR.getContext(), BR, AC, pmap, FS.Escaped); 3556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) L->runOnAllBlocks(A); 3566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}; 3596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 3606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ento::registerDeadStoresChecker(CheckerManager &mgr) { 3626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mgr.registerChecker<DeadStoresChecker>(); 3636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 3646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)