UninitializedValues.cpp revision d049b40ef411eee12a735233dbe04fdc42c67e1a
16f34213f8d6ae8c77685b53664527e39bfaaca3bTed Kremenek//==- UninitializedValues.cpp - Find Uninitialized Values -------*- C++ --*-==// 2610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// 3610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// The LLVM Compiler Infrastructure 4610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// 5610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// This file is distributed under the University of Illinois Open Source 6610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// License. See LICENSE.TXT for details. 7610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// 8610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//===----------------------------------------------------------------------===// 9610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// 10610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// This file implements uninitialized values analysis for source-level CFGs. 11610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// 12610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//===----------------------------------------------------------------------===// 13610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 14558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith#include "clang/AST/ASTContext.h" 152fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/AST/Attr.h" 16610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek#include "clang/AST/Decl.h" 17d049b40ef411eee12a735233dbe04fdc42c67e1aJordan Rose#include "clang/AST/StmtVisitor.h" 18c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek#include "clang/Analysis/Analyses/PostOrderCFGView.h" 196f34213f8d6ae8c77685b53664527e39bfaaca3bTed Kremenek#include "clang/Analysis/Analyses/UninitializedValues.h" 202fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/Analysis/AnalysisContext.h" 212fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/Analysis/CFG.h" 2225c1d57fc906e895535fb5c7e6dde80219f353b5Ted Kremenek#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h" 232fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/ADT/DenseMap.h" 242fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/ADT/Optional.h" 252fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/ADT/PackedVector.h" 262fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/ADT/SmallBitVector.h" 272fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/ADT/SmallVector.h" 28b2c60b04a597cc5ba4154837cf8e0a155a376fd7Argyrios Kyrtzidis#include "llvm/Support/SaveAndRestore.h" 292fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include <utility> 30610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 31610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekusing namespace clang; 32610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 33558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith#define DEBUG_LOGGING 0 34558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith 3540900ee8f3072d05456134b57c0fad85a6bb21a6Ted Kremenekstatic bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) { 361cbc31515e9b979f55178ffd4587e8671f7ebbfaTed Kremenek if (vd->isLocalVarDecl() && !vd->hasGlobalStorage() && 37a21612f95792c1ea8b4362f0861f0c724c39388eTed Kremenek !vd->isExceptionVariable() && 381cbc31515e9b979f55178ffd4587e8671f7ebbfaTed Kremenek vd->getDeclContext() == dc) { 391cbc31515e9b979f55178ffd4587e8671f7ebbfaTed Kremenek QualType ty = vd->getType(); 401cbc31515e9b979f55178ffd4587e8671f7ebbfaTed Kremenek return ty->isScalarType() || ty->isVectorType(); 411cbc31515e9b979f55178ffd4587e8671f7ebbfaTed Kremenek } 421cbc31515e9b979f55178ffd4587e8671f7ebbfaTed Kremenek return false; 43c104e53639de4424b83955acfadc977773b5883dTed Kremenek} 44c104e53639de4424b83955acfadc977773b5883dTed Kremenek 45610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//------------------------------------------------------------------------====// 46136f8f24b0b6c0e57aaa4375d280d72dc5492615Ted Kremenek// DeclToIndex: a mapping from Decls we track to value indices. 47610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//====------------------------------------------------------------------------// 48610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 49610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremeneknamespace { 50136f8f24b0b6c0e57aaa4375d280d72dc5492615Ted Kremenekclass DeclToIndex { 51610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek llvm::DenseMap<const VarDecl *, unsigned> map; 52610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekpublic: 53136f8f24b0b6c0e57aaa4375d280d72dc5492615Ted Kremenek DeclToIndex() {} 54610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 55610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek /// Compute the actual mapping from declarations to bits. 56610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek void computeMap(const DeclContext &dc); 57610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 58610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek /// Return the number of declarations in the map. 59610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek unsigned size() const { return map.size(); } 60610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 61610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek /// Returns the bit vector index for a given declaration. 62dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie Optional<unsigned> getValueIndex(const VarDecl *d) const; 63610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek}; 64610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 65610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 66136f8f24b0b6c0e57aaa4375d280d72dc5492615Ted Kremenekvoid DeclToIndex::computeMap(const DeclContext &dc) { 67610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek unsigned count = 0; 68610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek DeclContext::specific_decl_iterator<VarDecl> I(dc.decls_begin()), 69610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek E(dc.decls_end()); 70610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek for ( ; I != E; ++I) { 71581deb3da481053c4993c7600f97acf7768caac5David Blaikie const VarDecl *vd = *I; 7240900ee8f3072d05456134b57c0fad85a6bb21a6Ted Kremenek if (isTrackedVar(vd, &dc)) 73610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek map[vd] = count++; 74610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 75610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 76610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 77dc84cd5efdd3430efb22546b4ac656aa0540b210David BlaikieOptional<unsigned> DeclToIndex::getValueIndex(const VarDecl *d) const { 78b831c673621c5587642343cace9def134916a17bTed Kremenek llvm::DenseMap<const VarDecl *, unsigned>::const_iterator I = map.find(d); 79610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek if (I == map.end()) 8066874fb18afbffb8b2ca05576851a64534be3352David Blaikie return None; 81610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek return I->second; 82610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 83610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 84610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//------------------------------------------------------------------------====// 85610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// CFGBlockValues: dataflow values for CFG blocks. 86610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//====------------------------------------------------------------------------// 87610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 88f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek// These values are defined in such a way that a merge can be done using 89f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek// a bitwise OR. 90f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenekenum Value { Unknown = 0x0, /* 00 */ 91f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek Initialized = 0x1, /* 01 */ 92f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek Uninitialized = 0x2, /* 10 */ 93f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek MayUninitialized = 0x3 /* 11 */ }; 94f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek 95f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenekstatic bool isUninitialized(const Value v) { 96f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek return v >= Uninitialized; 97f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek} 98f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenekstatic bool isAlwaysUninit(const Value v) { 99f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek return v == Uninitialized; 100f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek} 101afb10c4bda2ac2c268fa7e6c11141584f57de119Ted Kremenek 102da57f3eeab7b7f7f6e6788956f0a0d9adf196a7dBenjamin Kramernamespace { 103afb10c4bda2ac2c268fa7e6c11141584f57de119Ted Kremenek 104da3d76b4cfbb5ebeb79e03a0abeabd403fe9260aBenjamin Kramertypedef llvm::PackedVector<Value, 2, llvm::SmallBitVector> ValueVector; 10513bd4236ab8297350be388ab442b4c42eb8fe437Ted Kremenek 106610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekclass CFGBlockValues { 107610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek const CFG &cfg; 108da3d76b4cfbb5ebeb79e03a0abeabd403fe9260aBenjamin Kramer SmallVector<ValueVector, 8> vals; 109136f8f24b0b6c0e57aaa4375d280d72dc5492615Ted Kremenek ValueVector scratch; 1104ddb3871307376d27d0f276c9da0ecce0384f01fTed Kremenek DeclToIndex declToIndex; 111610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekpublic: 112610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek CFGBlockValues(const CFG &cfg); 113eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek 114d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek unsigned getNumEntries() const { return declToIndex.size(); } 115d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek 116610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek void computeSetOfDeclarations(const DeclContext &dc); 117eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek ValueVector &getValueVector(const CFGBlock *block) { 118da3d76b4cfbb5ebeb79e03a0abeabd403fe9260aBenjamin Kramer return vals[block->getBlockID()]; 119eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek } 12013bd4236ab8297350be388ab442b4c42eb8fe437Ted Kremenek 121a9e8b9e3e90fcfe10a04624a89c39b63c32614d1Richard Smith void setAllScratchValues(Value V); 122136f8f24b0b6c0e57aaa4375d280d72dc5492615Ted Kremenek void mergeIntoScratch(ValueVector const &source, bool isFirst); 123136f8f24b0b6c0e57aaa4375d280d72dc5492615Ted Kremenek bool updateValueVectorWithScratch(const CFGBlock *block); 124610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 125610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek bool hasNoDeclarations() const { 1264ddb3871307376d27d0f276c9da0ecce0384f01fTed Kremenek return declToIndex.size() == 0; 127610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 128e0e29332c89da22b6890929b97e6f568c917d85fTed Kremenek 129610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek void resetScratch(); 13013bd4236ab8297350be388ab442b4c42eb8fe437Ted Kremenek 131136f8f24b0b6c0e57aaa4375d280d72dc5492615Ted Kremenek ValueVector::reference operator[](const VarDecl *vd); 1322815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 1332815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Value getValue(const CFGBlock *block, const CFGBlock *dstBlock, 1342815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const VarDecl *vd) { 135dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie const Optional<unsigned> &idx = declToIndex.getValueIndex(vd); 1362815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith assert(idx.hasValue()); 137eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek return getValueVector(block)[idx.getValue()]; 1382815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 139610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek}; 140da57f3eeab7b7f7f6e6788956f0a0d9adf196a7dBenjamin Kramer} // end anonymous namespace 141610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 142eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed KremenekCFGBlockValues::CFGBlockValues(const CFG &c) : cfg(c), vals(0) {} 143610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 144610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekvoid CFGBlockValues::computeSetOfDeclarations(const DeclContext &dc) { 1454ddb3871307376d27d0f276c9da0ecce0384f01fTed Kremenek declToIndex.computeMap(dc); 146eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek unsigned decls = declToIndex.size(); 147eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek scratch.resize(decls); 148eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek unsigned n = cfg.getNumBlockIDs(); 149eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek if (!n) 150eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek return; 151eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek vals.resize(n); 152eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek for (unsigned i = 0; i < n; ++i) 153da3d76b4cfbb5ebeb79e03a0abeabd403fe9260aBenjamin Kramer vals[i].resize(decls); 15413bd4236ab8297350be388ab442b4c42eb8fe437Ted Kremenek} 15513bd4236ab8297350be388ab442b4c42eb8fe437Ted Kremenek 156558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith#if DEBUG_LOGGING 157136f8f24b0b6c0e57aaa4375d280d72dc5492615Ted Kremenekstatic void printVector(const CFGBlock *block, ValueVector &bv, 1589fcbceed43e5610fdff43defe533934733453ae2Ted Kremenek unsigned num) { 1599fcbceed43e5610fdff43defe533934733453ae2Ted Kremenek llvm::errs() << block->getBlockID() << " :"; 1609fcbceed43e5610fdff43defe533934733453ae2Ted Kremenek for (unsigned i = 0; i < bv.size(); ++i) { 1619fcbceed43e5610fdff43defe533934733453ae2Ted Kremenek llvm::errs() << ' ' << bv[i]; 1629fcbceed43e5610fdff43defe533934733453ae2Ted Kremenek } 1639fcbceed43e5610fdff43defe533934733453ae2Ted Kremenek llvm::errs() << " : " << num << '\n'; 1649fcbceed43e5610fdff43defe533934733453ae2Ted Kremenek} 1659fcbceed43e5610fdff43defe533934733453ae2Ted Kremenek#endif 166610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 167a9e8b9e3e90fcfe10a04624a89c39b63c32614d1Richard Smithvoid CFGBlockValues::setAllScratchValues(Value V) { 168a9e8b9e3e90fcfe10a04624a89c39b63c32614d1Richard Smith for (unsigned I = 0, E = scratch.size(); I != E; ++I) 169a9e8b9e3e90fcfe10a04624a89c39b63c32614d1Richard Smith scratch[I] = V; 170a9e8b9e3e90fcfe10a04624a89c39b63c32614d1Richard Smith} 171a9e8b9e3e90fcfe10a04624a89c39b63c32614d1Richard Smith 172c5f740ecdbc21d5ba08f97b89cc05c9d4f230fdaTed Kremenekvoid CFGBlockValues::mergeIntoScratch(ValueVector const &source, 173c5f740ecdbc21d5ba08f97b89cc05c9d4f230fdaTed Kremenek bool isFirst) { 174c5f740ecdbc21d5ba08f97b89cc05c9d4f230fdaTed Kremenek if (isFirst) 175c5f740ecdbc21d5ba08f97b89cc05c9d4f230fdaTed Kremenek scratch = source; 176c5f740ecdbc21d5ba08f97b89cc05c9d4f230fdaTed Kremenek else 177c5f740ecdbc21d5ba08f97b89cc05c9d4f230fdaTed Kremenek scratch |= source; 178c5f740ecdbc21d5ba08f97b89cc05c9d4f230fdaTed Kremenek} 179c5f740ecdbc21d5ba08f97b89cc05c9d4f230fdaTed Kremenek 180136f8f24b0b6c0e57aaa4375d280d72dc5492615Ted Kremenekbool CFGBlockValues::updateValueVectorWithScratch(const CFGBlock *block) { 181eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek ValueVector &dst = getValueVector(block); 182610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek bool changed = (dst != scratch); 183610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek if (changed) 184610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek dst = scratch; 185558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith#if DEBUG_LOGGING 1869fcbceed43e5610fdff43defe533934733453ae2Ted Kremenek printVector(block, scratch, 0); 1879fcbceed43e5610fdff43defe533934733453ae2Ted Kremenek#endif 18813bd4236ab8297350be388ab442b4c42eb8fe437Ted Kremenek return changed; 18913bd4236ab8297350be388ab442b4c42eb8fe437Ted Kremenek} 19013bd4236ab8297350be388ab442b4c42eb8fe437Ted Kremenek 191610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekvoid CFGBlockValues::resetScratch() { 192610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek scratch.reset(); 193610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 194610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 195136f8f24b0b6c0e57aaa4375d280d72dc5492615Ted KremenekValueVector::reference CFGBlockValues::operator[](const VarDecl *vd) { 196dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie const Optional<unsigned> &idx = declToIndex.getValueIndex(vd); 197610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek assert(idx.hasValue()); 198610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek return scratch[idx.getValue()]; 199610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 200610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 201610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//------------------------------------------------------------------------====// 202610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// Worklist: worklist for dataflow analysis. 203610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//====------------------------------------------------------------------------// 204610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 205610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremeneknamespace { 206610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekclass DataflowWorklist { 207c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek PostOrderCFGView::iterator PO_I, PO_E; 2085f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<const CFGBlock *, 20> worklist; 209496398d523de712ac1084c53a397ca3987fe43dbTed Kremenek llvm::BitVector enqueuedBlocks; 210610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekpublic: 211c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek DataflowWorklist(const CFG &cfg, PostOrderCFGView &view) 212c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek : PO_I(view.begin()), PO_E(view.end()), 213c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek enqueuedBlocks(cfg.getNumBlockIDs(), true) { 214c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek // Treat the first block as already analyzed. 215c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek if (PO_I != PO_E) { 216c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek assert(*PO_I == &cfg.getEntry()); 217c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek enqueuedBlocks[(*PO_I)->getBlockID()] = false; 218c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek ++PO_I; 219c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek } 220c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek } 221610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 222610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek void enqueueSuccessors(const CFGBlock *block); 223610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek const CFGBlock *dequeue(); 224610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek}; 225610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 226610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 227610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekvoid DataflowWorklist::enqueueSuccessors(const clang::CFGBlock *block) { 228610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek for (CFGBlock::const_succ_iterator I = block->succ_begin(), 229610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek E = block->succ_end(); I != E; ++I) { 2308052050c8ebfcfbbce8afed57fefc8c95fb9a333Chandler Carruth const CFGBlock *Successor = *I; 2318052050c8ebfcfbbce8afed57fefc8c95fb9a333Chandler Carruth if (!Successor || enqueuedBlocks[Successor->getBlockID()]) 2328052050c8ebfcfbbce8afed57fefc8c95fb9a333Chandler Carruth continue; 2338052050c8ebfcfbbce8afed57fefc8c95fb9a333Chandler Carruth worklist.push_back(Successor); 2348052050c8ebfcfbbce8afed57fefc8c95fb9a333Chandler Carruth enqueuedBlocks[Successor->getBlockID()] = true; 235610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 236610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 237610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 238610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekconst CFGBlock *DataflowWorklist::dequeue() { 239c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek const CFGBlock *B = 0; 240c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek 241c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek // First dequeue from the worklist. This can represent 242c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek // updates along backedges that we want propagated as quickly as possible. 243c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek if (!worklist.empty()) { 244c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek B = worklist.back(); 245c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek worklist.pop_back(); 246c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek } 247c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek // Next dequeue from the initial reverse post order. This is the 248c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek // theoretical ideal in the presence of no back edges. 249c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek else if (PO_I != PO_E) { 250c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek B = *PO_I; 251c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek ++PO_I; 252c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek } 253c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek else { 254610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek return 0; 255c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek } 256c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek 257c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek assert(enqueuedBlocks[B->getBlockID()] == true); 258c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek enqueuedBlocks[B->getBlockID()] = false; 259c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek return B; 260610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 261610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 262610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//------------------------------------------------------------------------====// 2639532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith// Classification of DeclRefExprs as use or initialization. 264610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//====------------------------------------------------------------------------// 265610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 266610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremeneknamespace { 267610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekclass FindVarResult { 268610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek const VarDecl *vd; 269610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek const DeclRefExpr *dr; 270610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekpublic: 2719532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith FindVarResult(const VarDecl *vd, const DeclRefExpr *dr) : vd(vd), dr(dr) {} 2729532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 273610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek const DeclRefExpr *getDeclRefExpr() const { return dr; } 274610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek const VarDecl *getDecl() const { return vd; } 275610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek}; 2769532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 2779532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithstatic const Expr *stripCasts(ASTContext &C, const Expr *Ex) { 2789532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith while (Ex) { 2799532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith Ex = Ex->IgnoreParenNoopCasts(C); 2809532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (const CastExpr *CE = dyn_cast<CastExpr>(Ex)) { 2819532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (CE->getCastKind() == CK_LValueBitCast) { 2829532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith Ex = CE->getSubExpr(); 2839532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith continue; 2849532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith } 2859532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith } 2869532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith break; 2879532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith } 2889532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith return Ex; 2899532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith} 2909532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 2919532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith/// If E is an expression comprising a reference to a single variable, find that 2929532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith/// variable. 2939532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithstatic FindVarResult findVar(const Expr *E, const DeclContext *DC) { 2949532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (const DeclRefExpr *DRE = 2959532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith dyn_cast<DeclRefExpr>(stripCasts(DC->getParentASTContext(), E))) 2969532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) 2979532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (isTrackedVar(VD, DC)) 2989532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith return FindVarResult(VD, DRE); 2999532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith return FindVarResult(0, 0); 3009532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith} 3019532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 3029532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith/// \brief Classify each DeclRefExpr as an initialization or a use. Any 3039532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith/// DeclRefExpr which isn't explicitly classified will be assumed to have 3049532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith/// escaped the analysis and will be treated as an initialization. 3059532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithclass ClassifyRefs : public StmtVisitor<ClassifyRefs> { 3069532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithpublic: 3079532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith enum Class { 3089532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith Init, 3099532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith Use, 3109532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith SelfInit, 3119532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith Ignore 3129532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith }; 3139532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 3149532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithprivate: 3159532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith const DeclContext *DC; 3169532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith llvm::DenseMap<const DeclRefExpr*, Class> Classification; 3179532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 3189532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith bool isTrackedVar(const VarDecl *VD) const { 3199532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith return ::isTrackedVar(VD, DC); 3209532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith } 3219532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 3229532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith void classify(const Expr *E, Class C); 3239532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 3249532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithpublic: 3259532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith ClassifyRefs(AnalysisDeclContext &AC) : DC(cast<DeclContext>(AC.getDecl())) {} 3269532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 3279532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith void VisitDeclStmt(DeclStmt *DS); 3289532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith void VisitUnaryOperator(UnaryOperator *UO); 3299532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith void VisitBinaryOperator(BinaryOperator *BO); 3309532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith void VisitCallExpr(CallExpr *CE); 3319532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith void VisitCastExpr(CastExpr *CE); 3329532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 3339532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith void operator()(Stmt *S) { Visit(S); } 3349532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 3359532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith Class get(const DeclRefExpr *DRE) const { 3369532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith llvm::DenseMap<const DeclRefExpr*, Class>::const_iterator I 3379532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith = Classification.find(DRE); 3389532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (I != Classification.end()) 3399532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith return I->second; 3409532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 3419532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()); 3429532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (!VD || !isTrackedVar(VD)) 3439532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith return Ignore; 3449532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 3459532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith return Init; 3469532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith } 3479532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith}; 3489532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith} 3499532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 3509532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithstatic const DeclRefExpr *getSelfInitExpr(VarDecl *VD) { 3519532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (Expr *Init = VD->getInit()) { 3529532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith const DeclRefExpr *DRE 3539532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith = dyn_cast<DeclRefExpr>(stripCasts(VD->getASTContext(), Init)); 3549532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (DRE && DRE->getDecl() == VD) 3559532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith return DRE; 3569532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith } 3579532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith return 0; 3589532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith} 3599532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 3609532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithvoid ClassifyRefs::classify(const Expr *E, Class C) { 36177fd3c0d7837040bb84c1617a6a423f833e784feTed Kremenek // The result of a ?: could also be an lvalue. 36277fd3c0d7837040bb84c1617a6a423f833e784feTed Kremenek E = E->IgnoreParens(); 36377fd3c0d7837040bb84c1617a6a423f833e784feTed Kremenek if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { 36477fd3c0d7837040bb84c1617a6a423f833e784feTed Kremenek const Expr *TrueExpr = CO->getTrueExpr(); 36577fd3c0d7837040bb84c1617a6a423f833e784feTed Kremenek if (!isa<OpaqueValueExpr>(TrueExpr)) 36677fd3c0d7837040bb84c1617a6a423f833e784feTed Kremenek classify(TrueExpr, C); 36777fd3c0d7837040bb84c1617a6a423f833e784feTed Kremenek classify(CO->getFalseExpr(), C); 36877fd3c0d7837040bb84c1617a6a423f833e784feTed Kremenek return; 36977fd3c0d7837040bb84c1617a6a423f833e784feTed Kremenek } 37077fd3c0d7837040bb84c1617a6a423f833e784feTed Kremenek 3719532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith FindVarResult Var = findVar(E, DC); 3729532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (const DeclRefExpr *DRE = Var.getDeclRefExpr()) 3739532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith Classification[DRE] = std::max(Classification[DRE], C); 3749532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith} 3759532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 3769532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithvoid ClassifyRefs::VisitDeclStmt(DeclStmt *DS) { 3779532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); 3789532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith DI != DE; ++DI) { 3799532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith VarDecl *VD = dyn_cast<VarDecl>(*DI); 3809532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (VD && isTrackedVar(VD)) 3819532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (const DeclRefExpr *DRE = getSelfInitExpr(VD)) 3829532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith Classification[DRE] = SelfInit; 3839532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith } 3849532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith} 3859532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 3869532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithvoid ClassifyRefs::VisitBinaryOperator(BinaryOperator *BO) { 3879532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // Ignore the evaluation of a DeclRefExpr on the LHS of an assignment. If this 3889532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // is not a compound-assignment, we will treat it as initializing the variable 3899532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // when TransferFunctions visits it. A compound-assignment does not affect 3909532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // whether a variable is uninitialized, and there's no point counting it as a 3919532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // use. 3926cfa78f6bd4e7d5e23366a0907f8f8792366bc4cRichard Smith if (BO->isCompoundAssignmentOp()) 3936cfa78f6bd4e7d5e23366a0907f8f8792366bc4cRichard Smith classify(BO->getLHS(), Use); 3946cfa78f6bd4e7d5e23366a0907f8f8792366bc4cRichard Smith else if (BO->getOpcode() == BO_Assign) 3959532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith classify(BO->getLHS(), Ignore); 3969532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith} 3979532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 3989532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithvoid ClassifyRefs::VisitUnaryOperator(UnaryOperator *UO) { 3999532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // Increment and decrement are uses despite there being no lvalue-to-rvalue 4009532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // conversion. 4019532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (UO->isIncrementDecrementOp()) 4029532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith classify(UO->getSubExpr(), Use); 4039532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith} 4049532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 4059532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithvoid ClassifyRefs::VisitCallExpr(CallExpr *CE) { 4069532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // If a value is passed by const reference to a function, we should not assume 4079532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // that it is initialized by the call, and we conservatively do not assume 4089532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // that it is used. 4099532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end(); 4109532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith I != E; ++I) 4119532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if ((*I)->getType().isConstQualified() && (*I)->isGLValue()) 4129532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith classify(*I, Ignore); 4139532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith} 4149532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 4159532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithvoid ClassifyRefs::VisitCastExpr(CastExpr *CE) { 4169532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (CE->getCastKind() == CK_LValueToRValue) 4179532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith classify(CE->getSubExpr(), Use); 4189532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith else if (CStyleCastExpr *CSE = dyn_cast<CStyleCastExpr>(CE)) { 4199532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (CSE->getType()->isVoidType()) { 4209532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // Squelch any detected load of an uninitialized value if 4219532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // we cast it to void. 4229532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // e.g. (void) x; 4239532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith classify(CSE->getSubExpr(), Ignore); 4249532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith } 4259532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith } 4269532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith} 4279532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 4289532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith//------------------------------------------------------------------------====// 4299532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith// Transfer function for uninitialized values analysis. 4309532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith//====------------------------------------------------------------------------// 4319532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 4329532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithnamespace { 4330c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenekclass TransferFunctions : public StmtVisitor<TransferFunctions> { 434610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek CFGBlockValues &vals; 435610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek const CFG &cfg; 4362815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const CFGBlock *block; 4371d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek AnalysisDeclContext ∾ 4389532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith const ClassifyRefs &classification; 43925c1d57fc906e895535fb5c7e6dde80219f353b5Ted Kremenek ObjCNoReturn objCNoRet; 440eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek UninitVariablesHandler &handler; 4419532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 442610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekpublic: 443610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek TransferFunctions(CFGBlockValues &vals, const CFG &cfg, 4442815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const CFGBlock *block, AnalysisDeclContext &ac, 4459532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith const ClassifyRefs &classification, 446eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek UninitVariablesHandler &handler) 4479532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith : vals(vals), cfg(cfg), block(block), ac(ac), 44825c1d57fc906e895535fb5c7e6dde80219f353b5Ted Kremenek classification(classification), objCNoRet(ac.getASTContext()), 44925c1d57fc906e895535fb5c7e6dde80219f353b5Ted Kremenek handler(handler) {} 4509532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 451818918855d84e3db1af5a0807070d4995ca2cf75Richard Smith void reportUse(const Expr *ex, const VarDecl *vd); 452a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenek 45325c1d57fc906e895535fb5c7e6dde80219f353b5Ted Kremenek void VisitBinaryOperator(BinaryOperator *bo); 454a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenek void VisitBlockExpr(BlockExpr *be); 455a9e8b9e3e90fcfe10a04624a89c39b63c32614d1Richard Smith void VisitCallExpr(CallExpr *ce); 456c21fed361c11f13db345cba69101578578d8fb79Ted Kremenek void VisitDeclRefExpr(DeclRefExpr *dr); 45725c1d57fc906e895535fb5c7e6dde80219f353b5Ted Kremenek void VisitDeclStmt(DeclStmt *ds); 45825c1d57fc906e895535fb5c7e6dde80219f353b5Ted Kremenek void VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS); 45925c1d57fc906e895535fb5c7e6dde80219f353b5Ted Kremenek void VisitObjCMessageExpr(ObjCMessageExpr *ME); 4602815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 46140900ee8f3072d05456134b57c0fad85a6bb21a6Ted Kremenek bool isTrackedVar(const VarDecl *vd) { 46240900ee8f3072d05456134b57c0fad85a6bb21a6Ted Kremenek return ::isTrackedVar(vd, cast<DeclContext>(ac.getDecl())); 46340900ee8f3072d05456134b57c0fad85a6bb21a6Ted Kremenek } 4642815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 4659532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith FindVarResult findVar(const Expr *ex) { 4669532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith return ::findVar(ex, cast<DeclContext>(ac.getDecl())); 4679532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith } 4689532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 4692815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith UninitUse getUninitUse(const Expr *ex, const VarDecl *vd, Value v) { 4702815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith UninitUse Use(ex, isAlwaysUninit(v)); 4712815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 4722815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith assert(isUninitialized(v)); 4732815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (Use.getKind() == UninitUse::Always) 4742815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith return Use; 4752815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 4762815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // If an edge which leads unconditionally to this use did not initialize 4772815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // the variable, we can say something stronger than 'may be uninitialized': 4782815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // we can say 'either it's used uninitialized or you have dead code'. 4792815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // 4802815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // We track the number of successors of a node which have been visited, and 4812815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // visit a node once we have visited all of its successors. Only edges where 4822815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // the variable might still be uninitialized are followed. Since a variable 4832815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // can't transfer from being initialized to being uninitialized, this will 4842815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // trace out the subgraph which inevitably leads to the use and does not 4852815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // initialize the variable. We do not want to skip past loops, since their 4862815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // non-termination might be correlated with the initialization condition. 4872815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // 4882815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // For example: 4892815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // 4902815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // void f(bool a, bool b) { 4912815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // block1: int n; 4922815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // if (a) { 4932815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // block2: if (b) 4942815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // block3: n = 1; 4952815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // block4: } else if (b) { 4962815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // block5: while (!a) { 4972815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // block6: do_work(&a); 4982815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // n = 2; 4992815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // } 5002815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // } 5012815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // block7: if (a) 5022815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // block8: g(); 5032815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // block9: return n; 5042815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // } 5052815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // 5062815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // Starting from the maybe-uninitialized use in block 9: 5072815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // * Block 7 is not visited because we have only visited one of its two 5082815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // successors. 5092815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // * Block 8 is visited because we've visited its only successor. 5102815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // From block 8: 5112815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // * Block 7 is visited because we've now visited both of its successors. 5122815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // From block 7: 5132815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // * Blocks 1, 2, 4, 5, and 6 are not visited because we didn't visit all 5142815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // of their successors (we didn't visit 4, 3, 5, 6, and 5, respectively). 5152815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // * Block 3 is not visited because it initializes 'n'. 5162815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // Now the algorithm terminates, having visited blocks 7 and 8, and having 5172815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // found the frontier is blocks 2, 4, and 5. 5182815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // 5192815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // 'n' is definitely uninitialized for two edges into block 7 (from blocks 2 5202815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // and 4), so we report that any time either of those edges is taken (in 5212815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // each case when 'b == false'), 'n' is used uninitialized. 522cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallVector<const CFGBlock*, 32> Queue; 523cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallVector<unsigned, 32> SuccsVisited(cfg.getNumBlockIDs(), 0); 5242815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Queue.push_back(block); 5252815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // Specify that we've already visited all successors of the starting block. 5262815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // This has the dual purpose of ensuring we never add it to the queue, and 5272815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // of marking it as not being a candidate element of the frontier. 5282815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith SuccsVisited[block->getBlockID()] = block->succ_size(); 5292815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith while (!Queue.empty()) { 5302815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const CFGBlock *B = Queue.back(); 5312815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Queue.pop_back(); 5322815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith for (CFGBlock::const_pred_iterator I = B->pred_begin(), E = B->pred_end(); 5332815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith I != E; ++I) { 5342815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const CFGBlock *Pred = *I; 5352815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (vals.getValue(Pred, B, vd) == Initialized) 5362815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // This block initializes the variable. 5372815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith continue; 5382815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 539558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith unsigned &SV = SuccsVisited[Pred->getBlockID()]; 540558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith if (!SV) { 541558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith // When visiting the first successor of a block, mark all NULL 542558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith // successors as having been visited. 543558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith for (CFGBlock::const_succ_iterator SI = Pred->succ_begin(), 544558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith SE = Pred->succ_end(); 545558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith SI != SE; ++SI) 546558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith if (!*SI) 547558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith ++SV; 548558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith } 549558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith 550558e8872b364b43ab9f201dd6b2df9a5b74b0542Richard Smith if (++SV == Pred->succ_size()) 5512815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // All paths from this block lead to the use and don't initialize the 5522815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // variable. 5532815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Queue.push_back(Pred); 5542815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 5552815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 5562815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 5572815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // Scan the frontier, looking for blocks where the variable was 5582815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // uninitialized. 5592815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) { 5602815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const CFGBlock *Block = *BI; 5612815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith unsigned BlockID = Block->getBlockID(); 5622815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const Stmt *Term = Block->getTerminator(); 5632815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (SuccsVisited[BlockID] && SuccsVisited[BlockID] < Block->succ_size() && 5642815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Term) { 5652815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // This block inevitably leads to the use. If we have an edge from here 5662815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // to a post-dominator block, and the variable is uninitialized on that 5672815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // edge, we have found a bug. 5682815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith for (CFGBlock::const_succ_iterator I = Block->succ_begin(), 5692815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith E = Block->succ_end(); I != E; ++I) { 5702815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const CFGBlock *Succ = *I; 5712815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (Succ && SuccsVisited[Succ->getBlockID()] >= Succ->succ_size() && 5722815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith vals.getValue(Block, Succ, vd) == Uninitialized) { 5732815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // Switch cases are a special case: report the label to the caller 5742815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // as the 'terminator', not the switch statement itself. Suppress 5752815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // situations where no label matched: we can't be sure that's 5762815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // possible. 5772815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (isa<SwitchStmt>(Term)) { 5782815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const Stmt *Label = Succ->getLabel(); 5792815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (!Label || !isa<SwitchCase>(Label)) 5802815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // Might not be possible. 5812815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith continue; 5822815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith UninitUse::Branch Branch; 5832815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Branch.Terminator = Label; 5842815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Branch.Output = 0; // Ignored. 5852815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Use.addUninitBranch(Branch); 5862815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } else { 5872815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith UninitUse::Branch Branch; 5882815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Branch.Terminator = Term; 5892815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Branch.Output = I - Block->succ_begin(); 5902815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Use.addUninitBranch(Branch); 5912815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 5922815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 5932815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 5942815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 5952815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 5962815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 5972815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith return Use; 5982815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 599610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek}; 600610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 601610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 602818918855d84e3db1af5a0807070d4995ca2cf75Richard Smithvoid TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd) { 603818918855d84e3db1af5a0807070d4995ca2cf75Richard Smith Value v = vals[vd]; 604818918855d84e3db1af5a0807070d4995ca2cf75Richard Smith if (isUninitialized(v)) 605eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek handler.handleUseOfUninitVariable(vd, getUninitUse(ex, vd, v)); 606610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 607610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 6089532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithvoid TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS) { 6091ea800c4ca76d5bb41aa8a1e0a6c7628b9fff28dTed Kremenek // This represents an initialization of the 'element' value. 6109532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (DeclStmt *DS = dyn_cast<DeclStmt>(FS->getElement())) { 6119532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); 6129532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (isTrackedVar(VD)) 6139532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith vals[VD] = Initialized; 6141ea800c4ca76d5bb41aa8a1e0a6c7628b9fff28dTed Kremenek } 6151ea800c4ca76d5bb41aa8a1e0a6c7628b9fff28dTed Kremenek} 6161ea800c4ca76d5bb41aa8a1e0a6c7628b9fff28dTed Kremenek 617a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenekvoid TransferFunctions::VisitBlockExpr(BlockExpr *be) { 618bc8b44c4ee7f9c4c3ad296369e72feda61bdb580Ted Kremenek const BlockDecl *bd = be->getBlockDecl(); 619bc8b44c4ee7f9c4c3ad296369e72feda61bdb580Ted Kremenek for (BlockDecl::capture_const_iterator i = bd->capture_begin(), 620bc8b44c4ee7f9c4c3ad296369e72feda61bdb580Ted Kremenek e = bd->capture_end() ; i != e; ++i) { 621bc8b44c4ee7f9c4c3ad296369e72feda61bdb580Ted Kremenek const VarDecl *vd = i->getVariable(); 622bc8b44c4ee7f9c4c3ad296369e72feda61bdb580Ted Kremenek if (!isTrackedVar(vd)) 623bc8b44c4ee7f9c4c3ad296369e72feda61bdb580Ted Kremenek continue; 624bc8b44c4ee7f9c4c3ad296369e72feda61bdb580Ted Kremenek if (i->isByRef()) { 625bc8b44c4ee7f9c4c3ad296369e72feda61bdb580Ted Kremenek vals[vd] = Initialized; 626bc8b44c4ee7f9c4c3ad296369e72feda61bdb580Ted Kremenek continue; 627bc8b44c4ee7f9c4c3ad296369e72feda61bdb580Ted Kremenek } 628818918855d84e3db1af5a0807070d4995ca2cf75Richard Smith reportUse(be, vd); 629a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenek } 630a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenek} 631a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenek 632a9e8b9e3e90fcfe10a04624a89c39b63c32614d1Richard Smithvoid TransferFunctions::VisitCallExpr(CallExpr *ce) { 63344ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek if (Decl *Callee = ce->getCalleeDecl()) { 63444ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek if (Callee->hasAttr<ReturnsTwiceAttr>()) { 63544ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek // After a call to a function like setjmp or vfork, any variable which is 63644ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek // initialized anywhere within this function may now be initialized. For 63744ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek // now, just assume such a call initializes all variables. FIXME: Only 63844ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek // mark variables as initialized if they have an initializer which is 63944ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek // reachable from here. 64044ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek vals.setAllScratchValues(Initialized); 64144ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek } 64244ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek else if (Callee->hasAttr<AnalyzerNoReturnAttr>()) { 64344ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek // Functions labeled like "analyzer_noreturn" are often used to denote 64444ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek // "panic" functions that in special debug situations can still return, 64544ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek // but for the most part should not be treated as returning. This is a 64644ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek // useful annotation borrowed from the static analyzer that is useful for 64744ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek // suppressing branch-specific false positives when we call one of these 64844ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek // functions but keep pretending the path continues (when in reality the 64944ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek // user doesn't care). 65044ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek vals.setAllScratchValues(Unknown); 65144ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek } 65244ca53f34deb5efe9fc6f246781f66f1ed83eabcTed Kremenek } 653a9e8b9e3e90fcfe10a04624a89c39b63c32614d1Richard Smith} 654a9e8b9e3e90fcfe10a04624a89c39b63c32614d1Richard Smith 6550c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenekvoid TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) { 6569532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith switch (classification.get(dr)) { 6579532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith case ClassifyRefs::Ignore: 6589532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith break; 6599532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith case ClassifyRefs::Use: 6609532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith reportUse(dr, cast<VarDecl>(dr->getDecl())); 6619532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith break; 6629532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith case ClassifyRefs::Init: 6639532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith vals[cast<VarDecl>(dr->getDecl())] = Initialized; 6649532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith break; 6659532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith case ClassifyRefs::SelfInit: 666eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek handler.handleSelfInit(cast<VarDecl>(dr->getDecl())); 6679532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith break; 668610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 669610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 670610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 6719532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithvoid TransferFunctions::VisitBinaryOperator(BinaryOperator *BO) { 6729532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (BO->getOpcode() == BO_Assign) { 6739532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith FindVarResult Var = findVar(BO->getLHS()); 6749532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (const VarDecl *VD = Var.getDecl()) 6759532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith vals[VD] = Initialized; 676610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 677610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 678610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 6799532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smithvoid TransferFunctions::VisitDeclStmt(DeclStmt *DS) { 6809532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); 6819532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith DI != DE; ++DI) { 6829532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith VarDecl *VD = dyn_cast<VarDecl>(*DI); 6839532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (VD && isTrackedVar(VD)) { 6849532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith if (getSelfInitExpr(VD)) { 6859532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // If the initializer consists solely of a reference to itself, we 6869532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // explicitly mark the variable as uninitialized. This allows code 6879532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // like the following: 6889532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // 6899532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // int x = x; 6909532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // 6919532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // to deliberately leave a variable uninitialized. Different analysis 6929532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // clients can detect this pattern and adjust their reporting 6939532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // appropriately, but we need to continue to analyze subsequent uses 6949532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // of the variable. 6959532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith vals[VD] = Uninitialized; 6969532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith } else if (VD->getInit()) { 6979532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // Treat the new variable as initialized. 6989532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith vals[VD] = Initialized; 6999532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith } else { 7009532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // No initializer: the variable is now uninitialized. This matters 7019532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // for cases like: 7029532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // while (...) { 7039532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // int n; 7049532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // use(n); 7059532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // n = 0; 7069532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // } 7079532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // FIXME: Mark the variable as uninitialized whenever its scope is 7089532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // left, since its scope could be re-entered by a jump over the 7099532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // declaration. 7109532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith vals[VD] = Uninitialized; 7110c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek } 712dd0f7942c5415ce146dcc02d57fc503c683f8625Ted Kremenek } 713dd0f7942c5415ce146dcc02d57fc503c683f8625Ted Kremenek } 714610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 715610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 71625c1d57fc906e895535fb5c7e6dde80219f353b5Ted Kremenekvoid TransferFunctions::VisitObjCMessageExpr(ObjCMessageExpr *ME) { 71725c1d57fc906e895535fb5c7e6dde80219f353b5Ted Kremenek // If the Objective-C message expression is an implicit no-return that 71825c1d57fc906e895535fb5c7e6dde80219f353b5Ted Kremenek // is not modeled in the CFG, set the tracked dataflow values to Unknown. 71925c1d57fc906e895535fb5c7e6dde80219f353b5Ted Kremenek if (objCNoRet.isImplicitNoReturn(ME)) { 72025c1d57fc906e895535fb5c7e6dde80219f353b5Ted Kremenek vals.setAllScratchValues(Unknown); 72125c1d57fc906e895535fb5c7e6dde80219f353b5Ted Kremenek } 72225c1d57fc906e895535fb5c7e6dde80219f353b5Ted Kremenek} 72325c1d57fc906e895535fb5c7e6dde80219f353b5Ted Kremenek 724610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//------------------------------------------------------------------------====// 725610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// High-level "driver" logic for uninitialized values analysis. 726610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//====------------------------------------------------------------------------// 727610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 72813bd4236ab8297350be388ab442b4c42eb8fe437Ted Kremenekstatic bool runOnBlock(const CFGBlock *block, const CFG &cfg, 7291d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek AnalysisDeclContext &ac, CFGBlockValues &vals, 7309532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith const ClassifyRefs &classification, 731f8adeefa9e9882bff402e092024dd457f8574673Ted Kremenek llvm::BitVector &wasAnalyzed, 732eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek UninitVariablesHandler &handler) { 733f8adeefa9e9882bff402e092024dd457f8574673Ted Kremenek wasAnalyzed[block->getBlockID()] = true; 734610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek vals.resetScratch(); 735eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek // Merge in values of predecessor blocks. 736610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek bool isFirst = true; 737610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek for (CFGBlock::const_pred_iterator I = block->pred_begin(), 738610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek E = block->pred_end(); I != E; ++I) { 7396f27542da8843b5c1c579b86e342385bcc43d5f0Ted Kremenek const CFGBlock *pred = *I; 7406f27542da8843b5c1c579b86e342385bcc43d5f0Ted Kremenek if (wasAnalyzed[pred->getBlockID()]) { 741eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek vals.mergeIntoScratch(vals.getValueVector(pred), isFirst); 7426f27542da8843b5c1c579b86e342385bcc43d5f0Ted Kremenek isFirst = false; 7436f27542da8843b5c1c579b86e342385bcc43d5f0Ted Kremenek } 744610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 745610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek // Apply the transfer function. 7469532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith TransferFunctions tf(vals, cfg, block, ac, classification, handler); 747610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek for (CFGBlock::const_iterator I = block->begin(), E = block->end(); 748610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek I != E; ++I) { 749b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (Optional<CFGStmt> cs = I->getAs<CFGStmt>()) 750b07805485c603be3d8011f72611465324c9e664bDavid Blaikie tf.Visit(const_cast<Stmt*>(cs->getStmt())); 751610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 752136f8f24b0b6c0e57aaa4375d280d72dc5492615Ted Kremenek return vals.updateValueVectorWithScratch(block); 753610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 754610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 755eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek/// PruneBlocksHandler is a special UninitVariablesHandler that is used 756eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek/// to detect when a CFGBlock has any *potential* use of an uninitialized 757eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek/// variable. It is mainly used to prune out work during the final 758eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek/// reporting pass. 759eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremeneknamespace { 760eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenekstruct PruneBlocksHandler : public UninitVariablesHandler { 761eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek PruneBlocksHandler(unsigned numBlocks) 762eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek : hadUse(numBlocks, false), hadAnyUse(false), 763eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek currentBlock(0) {} 764eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek 765eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek virtual ~PruneBlocksHandler() {} 766eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek 767eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek /// Records if a CFGBlock had a potential use of an uninitialized variable. 768eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek llvm::BitVector hadUse; 769eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek 770eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek /// Records if any CFGBlock had a potential use of an uninitialized variable. 771eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek bool hadAnyUse; 772eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek 773eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek /// The current block to scribble use information. 774eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek unsigned currentBlock; 775eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek 776eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek virtual void handleUseOfUninitVariable(const VarDecl *vd, 777eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek const UninitUse &use) { 778eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek hadUse[currentBlock] = true; 779eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek hadAnyUse = true; 780eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek } 781eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek 782eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek /// Called when the uninitialized variable analysis detects the 783eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek /// idiom 'int x = x'. All other uses of 'x' within the initializer 784eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek /// are handled by handleUseOfUninitVariable. 785eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek virtual void handleSelfInit(const VarDecl *vd) { 786eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek hadUse[currentBlock] = true; 787eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek hadAnyUse = true; 788eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek } 789eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek}; 790eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek} 791eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek 7925d98994c7749312a43ce6adf45537979a98e7afdChandler Carruthvoid clang::runUninitializedVariablesAnalysis( 7935d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth const DeclContext &dc, 7945d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth const CFG &cfg, 7951d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek AnalysisDeclContext &ac, 7965d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth UninitVariablesHandler &handler, 7975d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth UninitVariablesAnalysisStats &stats) { 798610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek CFGBlockValues vals(cfg); 799610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek vals.computeSetOfDeclarations(dc); 800610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek if (vals.hasNoDeclarations()) 801610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek return; 802d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek 8035d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth stats.NumVariablesAnalyzed = vals.getNumEntries(); 8045d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 8059532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith // Precompute which expressions are uses and which are initializations. 8069532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith ClassifyRefs classification(ac); 8079532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith cfg.VisitBlockStmts(classification); 8089532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith 809d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek // Mark all variables uninitialized at the entry. 810d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek const CFGBlock &entry = cfg.getEntry(); 811eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek ValueVector &vec = vals.getValueVector(&entry); 812eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek const unsigned n = vals.getNumEntries(); 813eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek for (unsigned j = 0; j < n ; ++j) { 814eee18c38b6dd29c0e6982f5565fcbc3f76d1bf4dTed Kremenek vec[j] = Uninitialized; 815d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek } 816d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek 817d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek // Proceed with the workist. 818c1602581f7a4eab486489f09647d724ce35d3f23Ted Kremenek DataflowWorklist worklist(cfg, *ac.getAnalysis<PostOrderCFGView>()); 819496398d523de712ac1084c53a397ca3987fe43dbTed Kremenek llvm::BitVector previouslyVisited(cfg.getNumBlockIDs()); 820610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek worklist.enqueueSuccessors(&cfg.getEntry()); 821f8adeefa9e9882bff402e092024dd457f8574673Ted Kremenek llvm::BitVector wasAnalyzed(cfg.getNumBlockIDs(), false); 8226f27542da8843b5c1c579b86e342385bcc43d5f0Ted Kremenek wasAnalyzed[cfg.getEntry().getBlockID()] = true; 823eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek PruneBlocksHandler PBH(cfg.getNumBlockIDs()); 824610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 825610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek while (const CFGBlock *block = worklist.dequeue()) { 826eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek PBH.currentBlock = block->getBlockID(); 827eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek 828610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek // Did the block change? 8299532e0d89ca2afa556f032aa9377f6ec1d3eaa3eRichard Smith bool changed = runOnBlock(block, cfg, ac, vals, 830eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek classification, wasAnalyzed, PBH); 8315d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++stats.NumBlockVisits; 832610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek if (changed || !previouslyVisited[block->getBlockID()]) 833610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek worklist.enqueueSuccessors(block); 834610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek previouslyVisited[block->getBlockID()] = true; 835610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 836eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek 837eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek if (!PBH.hadAnyUse) 838eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek return; 839eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek 84067d472c19310c06efd5cb87c60b8489abf507233Enea Zaffanella // Run through the blocks one more time, and report uninitialized variables. 841610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) { 8426f27542da8843b5c1c579b86e342385bcc43d5f0Ted Kremenek const CFGBlock *block = *BI; 843eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek if (PBH.hadUse[block->getBlockID()]) { 844eba76a4379997f66f8114eb7e63206a5932b1be8Ted Kremenek runOnBlock(block, cfg, ac, vals, classification, wasAnalyzed, handler); 8455d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++stats.NumBlockVisits; 8465d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } 847610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 848610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 849610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 850610068c8cd2321f90e147b12cf794e1f840b6405Ted KremenekUninitVariablesHandler::~UninitVariablesHandler() {} 851