156b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek//==- DeadStoresChecker.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 157dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis#include "ClangSACheckers.h" 16ce1cab9fc0b4aec9cdef1b30a14e4ccdca3ac5f1Ted Kremenek#include "clang/AST/ASTContext.h" 172fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/AST/Attr.h" 181a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek#include "clang/AST/ParentMap.h" 192827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek#include "clang/AST/RecursiveASTVisitor.h" 2019948ac84f145b9ea576db2faefda1927c249e44Ted Kremenek#include "clang/Analysis/Analyses/LiveVariables.h" 2119948ac84f145b9ea576db2faefda1927c249e44Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 2219948ac84f145b9ea576db2faefda1927c249e44Ted Kremenek#include "clang/StaticAnalyzer/Core/Checker.h" 2319948ac84f145b9ea576db2faefda1927c249e44Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 2419948ac84f145b9ea576db2faefda1927c249e44Ted Kremenek#include "llvm/ADT/BitVector.h" 258fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h" 262827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek#include "llvm/Support/SaveAndRestore.h" 271ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek 281ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenekusing namespace clang; 299ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 301ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek 312827f5af018c515986ffb1779ec2e7246988f150Ted Kremeneknamespace { 322827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek 332827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek/// A simple visitor to record what VarDecls occur in EH-handling code. 342827f5af018c515986ffb1779ec2e7246988f150Ted Kremenekclass EHCodeVisitor : public RecursiveASTVisitor<EHCodeVisitor> { 352827f5af018c515986ffb1779ec2e7246988f150Ted Kremenekpublic: 362827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek bool inEH; 372827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek llvm::DenseSet<const VarDecl *> &S; 382827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek 392827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek bool TraverseObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { 402827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek SaveAndRestore<bool> inFinally(inEH, true); 412827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek return ::RecursiveASTVisitor<EHCodeVisitor>::TraverseObjCAtFinallyStmt(S); 422827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek } 432827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek 442827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek bool TraverseObjCAtCatchStmt(ObjCAtCatchStmt *S) { 452827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek SaveAndRestore<bool> inCatch(inEH, true); 462827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek return ::RecursiveASTVisitor<EHCodeVisitor>::TraverseObjCAtCatchStmt(S); 472827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek } 482827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek 492827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek bool TraverseCXXCatchStmt(CXXCatchStmt *S) { 502827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek SaveAndRestore<bool> inCatch(inEH, true); 512827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek return TraverseStmt(S->getHandlerBlock()); 522827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek } 532827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek 542827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek bool VisitDeclRefExpr(DeclRefExpr *DR) { 552827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek if (inEH) 562827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek if (const VarDecl *D = dyn_cast<VarDecl>(DR->getDecl())) 572827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek S.insert(D); 582827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek return true; 592827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek } 602827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek 612827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek EHCodeVisitor(llvm::DenseSet<const VarDecl *> &S) : 622827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek inEH(false), S(S) {} 632827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek}; 641a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek 65848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek// FIXME: Eventually migrate into its own file, and have it managed by 66848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek// AnalysisManager. 67848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenekclass ReachableCode { 68848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek const CFG &cfg; 69848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek llvm::BitVector reachable; 70848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenekpublic: 71848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek ReachableCode(const CFG &cfg) 72848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek : cfg(cfg), reachable(cfg.getNumBlockIDs(), false) {} 73848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek 74848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek void computeReachableBlocks(); 75848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek 76848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek bool isReachable(const CFGBlock *block) const { 77848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek return reachable[block->getBlockID()]; 78848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek } 79848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek}; 80848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek} 81848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek 82848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenekvoid ReachableCode::computeReachableBlocks() { 83848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek if (!cfg.getNumBlockIDs()) 84848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek return; 85848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek 865f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<const CFGBlock*, 10> worklist; 87848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek worklist.push_back(&cfg.getEntry()); 88344472ebeded2fca2ed5013b9e87f81d09bfa908Robert Wilhelm 89848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek while (!worklist.empty()) { 90344472ebeded2fca2ed5013b9e87f81d09bfa908Robert Wilhelm const CFGBlock *block = worklist.pop_back_val(); 91848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek llvm::BitVector::reference isReachable = reachable[block->getBlockID()]; 92848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek if (isReachable) 93848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek continue; 94848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek isReachable = true; 95848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek for (CFGBlock::const_succ_iterator i = block->succ_begin(), 96848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek e = block->succ_end(); i != e; ++i) 97848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek if (const CFGBlock *succ = *i) 98848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek worklist.push_back(succ); 99848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek } 100848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek} 101848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek 1029ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaksstatic const Expr * 1039ed6d8068f767819951bc4eebf6f4912087c442aAnna ZaksLookThroughTransitiveAssignmentsAndCommaOperators(const Expr *Ex) { 104bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek while (Ex) { 105bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek const BinaryOperator *BO = 106bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek dyn_cast<BinaryOperator>(Ex->IgnoreParenCasts()); 107bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek if (!BO) 108bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek break; 109bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek if (BO->getOpcode() == BO_Assign) { 110bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek Ex = BO->getRHS(); 111bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek continue; 112bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek } 1139ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaks if (BO->getOpcode() == BO_Comma) { 1149ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaks Ex = BO->getRHS(); 1159ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaks continue; 1169ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaks } 117bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek break; 118bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek } 119bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek return Ex; 120bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek} 121bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek 122848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremeneknamespace { 123882998923889a2fcce9b49696506c499e22cf38fTed Kremenekclass DeadStoreObs : public LiveVariables::Observer { 124848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek const CFG &cfg; 125c0508f9fe37a3afb1ccad39879348272545e55dbChris Lattner ASTContext &Ctx; 1268f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek BugReporter& BR; 127651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const CheckerBase *Checker; 1281d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek AnalysisDeclContext* AC; 1291a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek ParentMap& Parents; 130882998923889a2fcce9b49696506c499e22cf38fTed Kremenek llvm::SmallPtrSet<const VarDecl*, 20> Escaped; 131651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<ReachableCode> reachableCode; 132848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek const CFGBlock *currentBlock; 133651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<llvm::DenseSet<const VarDecl *>> InEH; 1341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1352cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit }; 1361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1371ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenekpublic: 138651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DeadStoreObs(const CFG &cfg, ASTContext &ctx, BugReporter &br, 139651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const CheckerBase *checker, AnalysisDeclContext *ac, 140651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ParentMap &parents, 141651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::SmallPtrSet<const VarDecl *, 20> &escaped) 142651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines : cfg(cfg), Ctx(ctx), BR(br), Checker(checker), AC(ac), Parents(parents), 1436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Escaped(escaped), currentBlock(nullptr) {} 1441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 145fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek virtual ~DeadStoreObs() {} 146b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek 1472827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek bool isLive(const LiveVariables::LivenessValues &Live, const VarDecl *D) { 1482827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek if (Live.isLive(D)) 1492827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek return true; 1502827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek // Lazily construct the set that records which VarDecls are in 1512827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek // EH code. 1522827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek if (!InEH.get()) { 1532827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek InEH.reset(new llvm::DenseSet<const VarDecl *>()); 1542827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek EHCodeVisitor V(*InEH.get()); 1552827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek V.TraverseStmt(AC->getBody()); 1562827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek } 1572827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek // Treat all VarDecls that occur in EH code as being "always live" 1582827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek // when considering to suppress dead stores. Frequently stores 1592827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek // are followed by reads in EH code, but we don't have the ability 1602827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek // to analyze that yet. 1612827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek return InEH->count(D); 1622827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek } 1632827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek 1649c378f705405d37f49795d5e915989de774fe11fTed Kremenek void Report(const VarDecl *V, DeadStoreKind dsk, 165590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation L, SourceRange R) { 166f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek if (Escaped.count(V)) 167f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek return; 168848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek 169848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek // Compute reachable blocks within the CFG for trivial cases 170848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek // where a bogus dead store can be reported because itself is unreachable. 171848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek if (!reachableCode.get()) { 172848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek reachableCode.reset(new ReachableCode(cfg)); 173848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek reachableCode->computeReachableBlocks(); 174848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek } 175848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek 176848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek if (!reachableCode->isReachable(currentBlock)) 177848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek return; 1788f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek 179f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<64> buf; 1807df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose llvm::raw_svector_ostream os(buf); 1816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const char *BugType = nullptr; 1821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1832cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek switch (dsk) { 1842cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek case DeadInit: 185efc620c4eb14d2ff59e3ec0714602997ffeddfd7Ted Kremenek BugType = "Dead initialization"; 186b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer os << "Value stored to '" << *V 1877df1234c2e62b2a23dc4417e527f941c20ebe858Jordy Rose << "' during its initialization is never read"; 1882cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek break; 1891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1902cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek case DeadIncrement: 191efc620c4eb14d2ff59e3ec0714602997ffeddfd7Ted Kremenek BugType = "Dead increment"; 1922cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek case Standard: 193efc620c4eb14d2ff59e3ec0714602997ffeddfd7Ted Kremenek if (!BugType) BugType = "Dead assignment"; 194b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer os << "Value stored to '" << *V << "' is never read"; 1952cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek break; 1961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1972cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek case Enclosing: 19856b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek // Don't report issues in this case, e.g.: "if (x = foo())", 19956b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek // where 'x' is unused later. We have yet to see a case where 20056b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek // this is a real bug. 20156b1f71156db11b9c8234ca621c29213a73218e0Ted Kremenek return; 202f9c2a5d1b49b60962b613a1dfffa23831ca298a2Ted Kremenek } 2031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BR.EmitBasicReport(AC->getDecl(), Checker, BugType, "Dead store", os.str(), 205651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines L, R); 2061a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek } 2071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2089c378f705405d37f49795d5e915989de774fe11fTed Kremenek void CheckVarDecl(const VarDecl *VD, const Expr *Ex, const Expr *Val, 2092cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek DeadStoreKind dsk, 210882998923889a2fcce9b49696506c499e22cf38fTed Kremenek const LiveVariables::LivenessValues &Live) { 2111a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek 212852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (!VD->hasLocalStorage()) 213852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return; 214852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek // Reference types confuse the dead stores checker. Skip them 215852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek // for now. 216852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (VD->getType()->getAs<ReferenceType>()) 217852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return; 218852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek 2192827f5af018c515986ffb1779ec2e7246988f150Ted Kremenek if (!isLive(Live, VD) && 220651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines !(VD->hasAttr<UnusedAttr>() || VD->hasAttr<BlocksAttr>() || 221651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines VD->hasAttr<ObjCPreciseLifetimeAttr>())) { 222590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks 223590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation ExLoc = 224590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation::createBegin(Ex, BR.getSourceManager(), AC); 225590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks Report(VD, dsk, ExLoc, Val->getSourceRange()); 226590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks } 2273eb817e5095d25e7bf4a8df9ed3f9b13bed6f298Ted Kremenek } 2281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2299c378f705405d37f49795d5e915989de774fe11fTed Kremenek void CheckDeclRef(const DeclRefExpr *DR, const Expr *Val, DeadStoreKind dsk, 230882998923889a2fcce9b49696506c499e22cf38fTed Kremenek const LiveVariables::LivenessValues& Live) { 2319c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) 232882998923889a2fcce9b49696506c499e22cf38fTed Kremenek CheckVarDecl(VD, DR, Val, dsk, Live); 2332cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek } 2341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2359c378f705405d37f49795d5e915989de774fe11fTed Kremenek bool isIncrement(VarDecl *VD, const BinaryOperator* B) { 2362cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek if (B->isCompoundAssignmentOp()) 2372cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek return true; 2381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2399c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Expr *RHS = B->getRHS()->IgnoreParenCasts(); 240882998923889a2fcce9b49696506c499e22cf38fTed Kremenek const BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS); 2411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2422cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek if (!BRHS) 2432cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek return false; 2441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 245882998923889a2fcce9b49696506c499e22cf38fTed Kremenek const DeclRefExpr *DR; 2461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2472cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek if ((DR = dyn_cast<DeclRefExpr>(BRHS->getLHS()->IgnoreParenCasts()))) 2482cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek if (DR->getDecl() == VD) 2492cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek return true; 2501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2512cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek if ((DR = dyn_cast<DeclRefExpr>(BRHS->getRHS()->IgnoreParenCasts()))) 2522cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek if (DR->getDecl() == VD) 2532cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek return true; 2541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2552cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek return false; 256a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek } 2571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 258651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void observeStmt(const Stmt *S, const CFGBlock *block, 259651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const LiveVariables::LivenessValues &Live) override { 2601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 261848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek currentBlock = block; 262848ec83483ca4ba52ed72c7e29ebc330f8c87252Ted Kremenek 2631c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek // Skip statements in macros. 2641c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek if (S->getLocStart().isMacroID()) 2651c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek return; 2661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 267f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek // Only cover dead stores from regular assignments. ++/-- dead stores 268f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek // have never flagged a real bug. 269882998923889a2fcce9b49696506c499e22cf38fTed Kremenek if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { 270fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek if (!B->isAssignmentOp()) return; // Skip non-assignments. 2711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2729c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(B->getLHS())) 2731a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 274e12691c2a2109016df12b2cbf54d51a921e6b618Ted Kremenek // Special case: check for assigning null to a pointer. 2751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // This is a common form of defensive programming. 2769ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaks const Expr *RHS = 2779ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaks LookThroughTransitiveAssignmentsAndCommaOperators(B->getRHS()); 2789ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaks RHS = RHS->IgnoreParenCasts(); 279bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek 280891322002b5f5886d812f6e8df12174fb2d8e73bTed Kremenek QualType T = VD->getType(); 281891322002b5f5886d812f6e8df12174fb2d8e73bTed Kremenek if (T->isPointerType() || T->isObjCObjectPointerType()) { 282bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek if (RHS->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNull)) 28393fab7c94008d9e2b1e4ce15784544c6710945feTed Kremenek return; 284e12691c2a2109016df12b2cbf54d51a921e6b618Ted Kremenek } 28593fab7c94008d9e2b1e4ce15784544c6710945feTed Kremenek 2863b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek // Special case: self-assignments. These are often used to shut up 2873b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek // "unused variable" compiler warnings. 288bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek if (const DeclRefExpr *RhsDR = dyn_cast<DeclRefExpr>(RHS)) 2893b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek if (VD == dyn_cast<VarDecl>(RhsDR->getDecl())) 2903b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek return; 2911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2923b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek // Otherwise, issue a warning. 293b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek DeadStoreKind dsk = Parents.isConsumedExpr(B) 2941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ? Enclosing 2957f5fce7200fdbf03f7d70134a57271e584fcb766Ted Kremenek : (isIncrement(VD,B) ? DeadIncrement : Standard); 2961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 297882998923889a2fcce9b49696506c499e22cf38fTed Kremenek CheckVarDecl(VD, DR, B->getRHS(), dsk, Live); 2981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 2991ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek } 300882998923889a2fcce9b49696506c499e22cf38fTed Kremenek else if (const UnaryOperator* U = dyn_cast<UnaryOperator>(S)) { 301f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek if (!U->isIncrementOp() || U->isPrefix()) 302a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek return; 3031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 304882998923889a2fcce9b49696506c499e22cf38fTed Kremenek const Stmt *parent = Parents.getParentIgnoreParenCasts(U); 305f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek if (!parent || !isa<ReturnStmt>(parent)) 306380277e46ec1d2d9abedcddf357ceea935cbe576Ted Kremenek return; 307b0f36323d9d8392075274b95816e2241f99ddb0dTed Kremenek 308882998923889a2fcce9b49696506c499e22cf38fTed Kremenek const Expr *Ex = U->getSubExpr()->IgnoreParenCasts(); 3091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3109c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) 311882998923889a2fcce9b49696506c499e22cf38fTed Kremenek CheckDeclRef(DR, U, DeadIncrement, Live); 3121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 3139c378f705405d37f49795d5e915989de774fe11fTed Kremenek else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) 314fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek // Iterate through the decls. Warn if any initializers are complex 315fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek // expressions that are not live (never used). 316651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *DI : DS->decls()) { 317651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const auto *V = dyn_cast<VarDecl>(DI); 318fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek 319fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek if (!V) 320fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek continue; 321852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek 322852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (V->hasLocalStorage()) { 323852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek // Reference types confuse the dead stores checker. Skip them 324852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek // for now. 325852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (V->getType()->getAs<ReferenceType>()) 326852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return; 327852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek 328bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek if (const Expr *E = V->getInit()) { 329bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek while (const ExprWithCleanups *exprClean = 330bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek dyn_cast<ExprWithCleanups>(E)) 331f85e193739c953358c865005855253af4f68a497John McCall E = exprClean->getSubExpr(); 332f85e193739c953358c865005855253af4f68a497John McCall 333bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek // Look through transitive assignments, e.g.: 334bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek // int x = y = 0; 3359ed6d8068f767819951bc4eebf6f4912087c442aAnna Zaks E = LookThroughTransitiveAssignmentsAndCommaOperators(E); 336bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek 33743f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek // Don't warn on C++ objects (yet) until we can show that their 33843f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek // constructors/destructors don't have side effects. 33943f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek if (isa<CXXConstructExpr>(E)) 34043f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek return; 341604d939ac15d1398761df313679673d30bb10f27Ted Kremenek 342fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek // A dead initialization is a variable that is dead after it 343fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek // is initialized. We don't flag warnings for those variables 344651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // marked 'unused' or 'objc_precise_lifetime'. 345651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!isLive(Live, V) && 346651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines !V->hasAttr<UnusedAttr>() && 347651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines !V->hasAttr<ObjCPreciseLifetimeAttr>()) { 348c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek // Special case: check for initializations with constants. 349c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek // 350c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek // e.g. : int x = 0; 351c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek // 352c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek // If x is EVER assigned a new value later, don't issue 353c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek // a warning. This is because such initialization can be 354c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek // due to defensive programming. 3550e35b4ecee380c2b4c33d75da6bc2fb6f6bc7df3Richard Smith if (E->isEvaluatable(Ctx)) 356d3098ee64c069a3eff4d2d0a5d655d968c7b5dd2Ted Kremenek return; 3571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 358bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek if (const DeclRefExpr *DRE = 359bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek dyn_cast<DeclRefExpr>(E->IgnoreParenCasts())) 360bb811cab1bfa91074f1992b154fcb0c288e6eda3Ted Kremenek if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) { 361ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek // Special case: check for initialization from constant 362ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek // variables. 363ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek // 364ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek // e.g. extern const int MyConstant; 365ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek // int x = MyConstant; 366ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek // 367d3098ee64c069a3eff4d2d0a5d655d968c7b5dd2Ted Kremenek if (VD->hasGlobalStorage() && 368ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek VD->getType().isConstQualified()) 369ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek return; 370ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek // Special case: check for initialization from scalar 371ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek // parameters. This is often a form of defensive 372ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek // programming. Non-scalars are still an error since 373ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek // because it more likely represents an actual algorithmic 374ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek // bug. 375ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek if (isa<ParmVarDecl>(VD) && VD->getType()->isScalarType()) 376ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek return; 377ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek } 3781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 379590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation Loc = 380590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation::create(V, BR.getSourceManager()); 381590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks Report(V, DeadInit, Loc, E->getSourceRange()); 382ce1cab9fc0b4aec9cdef1b30a14e4ccdca3ac5f1Ted Kremenek } 383fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek } 384852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek } 385fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek } 3861ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek } 3871ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek}; 3881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3891ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek} // end anonymous namespace 3901ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek 391d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek//===----------------------------------------------------------------------===// 392e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek// Driver function to invoke the Dead-Stores checker on a CFG. 393e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek//===----------------------------------------------------------------------===// 394e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek 395f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremeneknamespace { 396d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Roseclass FindEscaped { 397f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenekpublic: 398882998923889a2fcce9b49696506c499e22cf38fTed Kremenek llvm::SmallPtrSet<const VarDecl*, 20> Escaped; 399f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek 400d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose void operator()(const Stmt *S) { 401d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose // Check for '&'. Any VarDecl whose address has been taken we treat as 402d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose // escaped. 403d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose // FIXME: What about references? 404d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose const UnaryOperator *U = dyn_cast<UnaryOperator>(S); 405d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose if (!U) 406d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose return; 407d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose if (U->getOpcode() != UO_AddrOf) 408d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose return; 409d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose 410d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose const Expr *E = U->getSubExpr()->IgnoreParenCasts(); 411d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) 412d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) 413d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose Escaped.insert(VD); 414f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek } 415f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek}; 416f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek} // end anonymous namespace 4171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 418f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek 4197dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 4207dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis// DeadStoresChecker 4217dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 4227dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis 4237dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidisnamespace { 424ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass DeadStoresChecker : public Checker<check::ASTCodeBody> { 4257dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidispublic: 4267dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 4277dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis BugReporter &BR) const { 428724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek 429724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek // Don't do anything for template instantiations. 430724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek // Proving that code in a template instantiation is "dead" 431724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek // means proving that it is dead in all instantiations. 432724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek // This same problem exists with -Wunreachable-code. 433724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 434724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek if (FD->isTemplateInstantiation()) 435724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek return; 436724cfee8b506ffef6f55e556a3329a7403ef7198Ted Kremenek 437a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek if (LiveVariables *L = mgr.getAnalysis<LiveVariables>(D)) { 4387dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis CFG &cfg = *mgr.getCFG(D); 4391d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D); 4407dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis ParentMap &pmap = mgr.getParentMap(D); 441d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose FindEscaped FS; 442d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose cfg.VisitBlockStmts(FS); 443651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DeadStoreObs A(cfg, BR.getContext(), BR, this, AC, pmap, FS.Escaped); 444882998923889a2fcce9b49696506c499e22cf38fTed Kremenek L->runOnAllBlocks(A); 4457dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis } 4467dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis } 4477dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis}; 4487dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis} 4497dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis 4507dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidisvoid ento::registerDeadStoresChecker(CheckerManager &mgr) { 4517dd445ec20e704846cfbdb132e56539280d71311Argyrios Kyrtzidis mgr.registerChecker<DeadStoresChecker>(); 452d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek} 453