blob: 3dde41f2272ee5bac3a5939737ac2d57f2da7fc0 [file] [log] [blame]
Ted Kremenek6f342132011-03-15 03:17:07 +00001//==- UninitializedValues.cpp - Find Uninitialized Values -------*- C++ --*-==//
Ted Kremenek610068c2011-01-15 02:58:47 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements uninitialized values analysis for source-level CFGs.
11//
12//===----------------------------------------------------------------------===//
13
Ted Kremenek13bd4232011-01-20 17:37:17 +000014#include <utility>
Ted Kremenek610068c2011-01-15 02:58:47 +000015#include "llvm/ADT/Optional.h"
16#include "llvm/ADT/SmallVector.h"
17#include "llvm/ADT/BitVector.h"
18#include "llvm/ADT/DenseMap.h"
19#include "clang/AST/Decl.h"
20#include "clang/Analysis/CFG.h"
Ted Kremeneka8c17a52011-01-25 19:13:48 +000021#include "clang/Analysis/AnalysisContext.h"
Ted Kremenek610068c2011-01-15 02:58:47 +000022#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
Ted Kremenek6f342132011-03-15 03:17:07 +000023#include "clang/Analysis/Analyses/UninitializedValues.h"
Ted Kremenekc21fed32011-01-18 21:18:58 +000024#include "clang/Analysis/Support/SaveAndRestore.h"
Ted Kremenek610068c2011-01-15 02:58:47 +000025
26using namespace clang;
27
Ted Kremenek40900ee2011-01-27 02:29:34 +000028static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) {
Ted Kremenek1cbc3152011-03-17 03:06:11 +000029 if (vd->isLocalVarDecl() && !vd->hasGlobalStorage() &&
30 vd->getDeclContext() == dc) {
31 QualType ty = vd->getType();
32 return ty->isScalarType() || ty->isVectorType();
33 }
34 return false;
Ted Kremenekc104e532011-01-18 04:53:25 +000035}
36
Ted Kremenek610068c2011-01-15 02:58:47 +000037//------------------------------------------------------------------------====//
Ted Kremenek136f8f22011-03-15 04:57:27 +000038// DeclToIndex: a mapping from Decls we track to value indices.
Ted Kremenek610068c2011-01-15 02:58:47 +000039//====------------------------------------------------------------------------//
40
41namespace {
Ted Kremenek136f8f22011-03-15 04:57:27 +000042class DeclToIndex {
Ted Kremenek610068c2011-01-15 02:58:47 +000043 llvm::DenseMap<const VarDecl *, unsigned> map;
44public:
Ted Kremenek136f8f22011-03-15 04:57:27 +000045 DeclToIndex() {}
Ted Kremenek610068c2011-01-15 02:58:47 +000046
47 /// Compute the actual mapping from declarations to bits.
48 void computeMap(const DeclContext &dc);
49
50 /// Return the number of declarations in the map.
51 unsigned size() const { return map.size(); }
52
53 /// Returns the bit vector index for a given declaration.
Ted Kremenekb831c672011-03-29 01:40:00 +000054 llvm::Optional<unsigned> getValueIndex(const VarDecl *d) const;
Ted Kremenek610068c2011-01-15 02:58:47 +000055};
56}
57
Ted Kremenek136f8f22011-03-15 04:57:27 +000058void DeclToIndex::computeMap(const DeclContext &dc) {
Ted Kremenek610068c2011-01-15 02:58:47 +000059 unsigned count = 0;
60 DeclContext::specific_decl_iterator<VarDecl> I(dc.decls_begin()),
61 E(dc.decls_end());
62 for ( ; I != E; ++I) {
63 const VarDecl *vd = *I;
Ted Kremenek40900ee2011-01-27 02:29:34 +000064 if (isTrackedVar(vd, &dc))
Ted Kremenek610068c2011-01-15 02:58:47 +000065 map[vd] = count++;
66 }
67}
68
Ted Kremenekb831c672011-03-29 01:40:00 +000069llvm::Optional<unsigned> DeclToIndex::getValueIndex(const VarDecl *d) const {
70 llvm::DenseMap<const VarDecl *, unsigned>::const_iterator I = map.find(d);
Ted Kremenek610068c2011-01-15 02:58:47 +000071 if (I == map.end())
72 return llvm::Optional<unsigned>();
73 return I->second;
74}
75
76//------------------------------------------------------------------------====//
77// CFGBlockValues: dataflow values for CFG blocks.
78//====------------------------------------------------------------------------//
79
Ted Kremenekf7bafc72011-03-15 04:57:38 +000080// These values are defined in such a way that a merge can be done using
81// a bitwise OR.
82enum Value { Unknown = 0x0, /* 00 */
83 Initialized = 0x1, /* 01 */
84 Uninitialized = 0x2, /* 10 */
85 MayUninitialized = 0x3 /* 11 */ };
86
87static bool isUninitialized(const Value v) {
88 return v >= Uninitialized;
89}
90static bool isAlwaysUninit(const Value v) {
91 return v == Uninitialized;
92}
Ted Kremenekafb10c42011-03-15 04:57:29 +000093
Benjamin Kramerda57f3e2011-03-26 12:38:21 +000094namespace {
Ted Kremenekafb10c42011-03-15 04:57:29 +000095class ValueVector {
96 llvm::BitVector vec;
97public:
98 ValueVector() {}
Ted Kremenekf7bafc72011-03-15 04:57:38 +000099 ValueVector(unsigned size) : vec(size << 1) {}
100 void resize(unsigned n) { vec.resize(n << 1); }
Ted Kremenekafb10c42011-03-15 04:57:29 +0000101 void merge(const ValueVector &rhs) { vec |= rhs.vec; }
102 bool operator!=(const ValueVector &rhs) const { return vec != rhs.vec; }
Ted Kremenekafb10c42011-03-15 04:57:29 +0000103 void reset() { vec.reset(); }
Ted Kremenek496398d2011-03-15 04:57:32 +0000104
105 class reference {
106 ValueVector &vv;
107 const unsigned idx;
108
109 reference(); // Undefined
110 public:
111 reference(ValueVector &vv, unsigned idx) : vv(vv), idx(idx) {}
112 ~reference() {}
113
114 reference &operator=(Value v) {
Ted Kremenekf7bafc72011-03-15 04:57:38 +0000115 vv.vec[idx << 1] = (((unsigned) v) & 0x1) ? true : false;
116 vv.vec[(idx << 1) | 1] = (((unsigned) v) & 0x2) ? true : false;
Ted Kremenek496398d2011-03-15 04:57:32 +0000117 return *this;
118 }
Ted Kremenekf7bafc72011-03-15 04:57:38 +0000119 operator Value() {
120 unsigned x = (vv.vec[idx << 1] ? 1 : 0) | (vv.vec[(idx << 1) | 1] ? 2 :0);
121 return (Value) x;
122 }
Ted Kremenek496398d2011-03-15 04:57:32 +0000123 };
124
125 reference operator[](unsigned idx) { return reference(*this, idx); }
Ted Kremenekafb10c42011-03-15 04:57:29 +0000126};
127
Ted Kremenek136f8f22011-03-15 04:57:27 +0000128typedef std::pair<ValueVector *, ValueVector *> BVPair;
Ted Kremenek13bd4232011-01-20 17:37:17 +0000129
Ted Kremenek610068c2011-01-15 02:58:47 +0000130class CFGBlockValues {
131 const CFG &cfg;
Ted Kremenek13bd4232011-01-20 17:37:17 +0000132 BVPair *vals;
Ted Kremenek136f8f22011-03-15 04:57:27 +0000133 ValueVector scratch;
Ted Kremenek4ddb3872011-03-15 05:30:12 +0000134 DeclToIndex declToIndex;
Ted Kremenek13bd4232011-01-20 17:37:17 +0000135
Ted Kremenek136f8f22011-03-15 04:57:27 +0000136 ValueVector &lazyCreate(ValueVector *&bv);
Ted Kremenek610068c2011-01-15 02:58:47 +0000137public:
138 CFGBlockValues(const CFG &cfg);
139 ~CFGBlockValues();
140
Ted Kremenekd40066b2011-04-04 23:29:12 +0000141 unsigned getNumEntries() const { return declToIndex.size(); }
142
Ted Kremenek610068c2011-01-15 02:58:47 +0000143 void computeSetOfDeclarations(const DeclContext &dc);
Ted Kremenek136f8f22011-03-15 04:57:27 +0000144 ValueVector &getValueVector(const CFGBlock *block,
Ted Kremenek13bd4232011-01-20 17:37:17 +0000145 const CFGBlock *dstBlock);
146
Ted Kremenek136f8f22011-03-15 04:57:27 +0000147 BVPair &getValueVectors(const CFGBlock *block, bool shouldLazyCreate);
Ted Kremenek13bd4232011-01-20 17:37:17 +0000148
Ted Kremenek136f8f22011-03-15 04:57:27 +0000149 void mergeIntoScratch(ValueVector const &source, bool isFirst);
150 bool updateValueVectorWithScratch(const CFGBlock *block);
151 bool updateValueVectors(const CFGBlock *block, const BVPair &newVals);
Ted Kremenek610068c2011-01-15 02:58:47 +0000152
153 bool hasNoDeclarations() const {
Ted Kremenek4ddb3872011-03-15 05:30:12 +0000154 return declToIndex.size() == 0;
Ted Kremenek610068c2011-01-15 02:58:47 +0000155 }
156
Ted Kremenekb831c672011-03-29 01:40:00 +0000157 bool hasEntry(const VarDecl *vd) const {
158 return declToIndex.getValueIndex(vd).hasValue();
159 }
160
Ted Kremenekf8adeef2011-04-04 20:30:58 +0000161 bool hasValues(const CFGBlock *block);
162
Ted Kremenek610068c2011-01-15 02:58:47 +0000163 void resetScratch();
Ted Kremenek136f8f22011-03-15 04:57:27 +0000164 ValueVector &getScratch() { return scratch; }
Ted Kremenek13bd4232011-01-20 17:37:17 +0000165
Ted Kremenek136f8f22011-03-15 04:57:27 +0000166 ValueVector::reference operator[](const VarDecl *vd);
Ted Kremenek610068c2011-01-15 02:58:47 +0000167};
Benjamin Kramerda57f3e2011-03-26 12:38:21 +0000168} // end anonymous namespace
Ted Kremenek610068c2011-01-15 02:58:47 +0000169
170CFGBlockValues::CFGBlockValues(const CFG &c) : cfg(c), vals(0) {
171 unsigned n = cfg.getNumBlockIDs();
172 if (!n)
173 return;
Ted Kremenek136f8f22011-03-15 04:57:27 +0000174 vals = new std::pair<ValueVector*, ValueVector*>[n];
Francois Pichet2d78c372011-01-15 13:27:47 +0000175 memset(vals, 0, sizeof(*vals) * n);
Ted Kremenek610068c2011-01-15 02:58:47 +0000176}
177
178CFGBlockValues::~CFGBlockValues() {
179 unsigned n = cfg.getNumBlockIDs();
180 if (n == 0)
181 return;
Ted Kremenek13bd4232011-01-20 17:37:17 +0000182 for (unsigned i = 0; i < n; ++i) {
183 delete vals[i].first;
184 delete vals[i].second;
185 }
Ted Kremenek610068c2011-01-15 02:58:47 +0000186 delete [] vals;
187}
188
189void CFGBlockValues::computeSetOfDeclarations(const DeclContext &dc) {
Ted Kremenek4ddb3872011-03-15 05:30:12 +0000190 declToIndex.computeMap(dc);
191 scratch.resize(declToIndex.size());
Ted Kremenek610068c2011-01-15 02:58:47 +0000192}
193
Ted Kremenek136f8f22011-03-15 04:57:27 +0000194ValueVector &CFGBlockValues::lazyCreate(ValueVector *&bv) {
Ted Kremenek13bd4232011-01-20 17:37:17 +0000195 if (!bv)
Ted Kremenek4ddb3872011-03-15 05:30:12 +0000196 bv = new ValueVector(declToIndex.size());
Ted Kremenek610068c2011-01-15 02:58:47 +0000197 return *bv;
198}
199
Ted Kremenek13bd4232011-01-20 17:37:17 +0000200/// This function pattern matches for a '&&' or '||' that appears at
201/// the beginning of a CFGBlock that also (1) has a terminator and
202/// (2) has no other elements. If such an expression is found, it is returned.
203static BinaryOperator *getLogicalOperatorInChain(const CFGBlock *block) {
204 if (block->empty())
205 return 0;
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000206
Ted Kremenek3c0349e2011-03-01 03:15:10 +0000207 const CFGStmt *cstmt = block->front().getAs<CFGStmt>();
Ted Kremenek76709bf2011-03-15 05:22:28 +0000208 if (!cstmt)
209 return 0;
210
Ted Kremenek3c0349e2011-03-01 03:15:10 +0000211 BinaryOperator *b = llvm::dyn_cast_or_null<BinaryOperator>(cstmt->getStmt());
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000212
213 if (!b || !b->isLogicalOp())
Ted Kremenek13bd4232011-01-20 17:37:17 +0000214 return 0;
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000215
216 if (block->pred_size() == 2 &&
217 ((block->succ_size() == 2 && block->getTerminatorCondition() == b) ||
218 block->size() == 1))
219 return b;
220
221 return 0;
Ted Kremenek13bd4232011-01-20 17:37:17 +0000222}
223
Ted Kremenek136f8f22011-03-15 04:57:27 +0000224ValueVector &CFGBlockValues::getValueVector(const CFGBlock *block,
225 const CFGBlock *dstBlock) {
Ted Kremenek13bd4232011-01-20 17:37:17 +0000226 unsigned idx = block->getBlockID();
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000227 if (dstBlock && getLogicalOperatorInChain(block)) {
228 if (*block->succ_begin() == dstBlock)
229 return lazyCreate(vals[idx].first);
230 assert(*(block->succ_begin()+1) == dstBlock);
231 return lazyCreate(vals[idx].second);
Ted Kremenek13bd4232011-01-20 17:37:17 +0000232 }
233
234 assert(vals[idx].second == 0);
235 return lazyCreate(vals[idx].first);
236}
237
Ted Kremenekf8adeef2011-04-04 20:30:58 +0000238bool CFGBlockValues::hasValues(const CFGBlock *block) {
239 unsigned idx = block->getBlockID();
240 return vals[idx].second != 0;
241}
242
Ted Kremenek136f8f22011-03-15 04:57:27 +0000243BVPair &CFGBlockValues::getValueVectors(const clang::CFGBlock *block,
244 bool shouldLazyCreate) {
Ted Kremenek13bd4232011-01-20 17:37:17 +0000245 unsigned idx = block->getBlockID();
246 lazyCreate(vals[idx].first);
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000247 if (shouldLazyCreate)
248 lazyCreate(vals[idx].second);
Ted Kremenek13bd4232011-01-20 17:37:17 +0000249 return vals[idx];
250}
251
Ted Kremenek136f8f22011-03-15 04:57:27 +0000252void CFGBlockValues::mergeIntoScratch(ValueVector const &source,
Ted Kremenek610068c2011-01-15 02:58:47 +0000253 bool isFirst) {
254 if (isFirst)
255 scratch = source;
256 else
Ted Kremenekafb10c42011-03-15 04:57:29 +0000257 scratch.merge(source);
Ted Kremenek610068c2011-01-15 02:58:47 +0000258}
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000259#if 0
Ted Kremenek136f8f22011-03-15 04:57:27 +0000260static void printVector(const CFGBlock *block, ValueVector &bv,
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000261 unsigned num) {
262
263 llvm::errs() << block->getBlockID() << " :";
264 for (unsigned i = 0; i < bv.size(); ++i) {
265 llvm::errs() << ' ' << bv[i];
266 }
267 llvm::errs() << " : " << num << '\n';
268}
269#endif
Ted Kremenek610068c2011-01-15 02:58:47 +0000270
Ted Kremenek136f8f22011-03-15 04:57:27 +0000271bool CFGBlockValues::updateValueVectorWithScratch(const CFGBlock *block) {
272 ValueVector &dst = getValueVector(block, 0);
Ted Kremenek610068c2011-01-15 02:58:47 +0000273 bool changed = (dst != scratch);
274 if (changed)
275 dst = scratch;
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000276#if 0
277 printVector(block, scratch, 0);
278#endif
Ted Kremenek13bd4232011-01-20 17:37:17 +0000279 return changed;
280}
281
Ted Kremenek136f8f22011-03-15 04:57:27 +0000282bool CFGBlockValues::updateValueVectors(const CFGBlock *block,
Ted Kremenek13bd4232011-01-20 17:37:17 +0000283 const BVPair &newVals) {
Ted Kremenek136f8f22011-03-15 04:57:27 +0000284 BVPair &vals = getValueVectors(block, true);
Ted Kremenek13bd4232011-01-20 17:37:17 +0000285 bool changed = *newVals.first != *vals.first ||
286 *newVals.second != *vals.second;
287 *vals.first = *newVals.first;
288 *vals.second = *newVals.second;
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000289#if 0
290 printVector(block, *vals.first, 1);
291 printVector(block, *vals.second, 2);
292#endif
Ted Kremenek610068c2011-01-15 02:58:47 +0000293 return changed;
294}
295
296void CFGBlockValues::resetScratch() {
297 scratch.reset();
298}
299
Ted Kremenek136f8f22011-03-15 04:57:27 +0000300ValueVector::reference CFGBlockValues::operator[](const VarDecl *vd) {
Ted Kremenek4ddb3872011-03-15 05:30:12 +0000301 const llvm::Optional<unsigned> &idx = declToIndex.getValueIndex(vd);
Ted Kremenek610068c2011-01-15 02:58:47 +0000302 assert(idx.hasValue());
303 return scratch[idx.getValue()];
304}
305
306//------------------------------------------------------------------------====//
307// Worklist: worklist for dataflow analysis.
308//====------------------------------------------------------------------------//
309
310namespace {
311class DataflowWorklist {
312 llvm::SmallVector<const CFGBlock *, 20> worklist;
Ted Kremenek496398d2011-03-15 04:57:32 +0000313 llvm::BitVector enqueuedBlocks;
Ted Kremenek610068c2011-01-15 02:58:47 +0000314public:
315 DataflowWorklist(const CFG &cfg) : enqueuedBlocks(cfg.getNumBlockIDs()) {}
316
317 void enqueue(const CFGBlock *block);
318 void enqueueSuccessors(const CFGBlock *block);
319 const CFGBlock *dequeue();
320
321};
322}
323
324void DataflowWorklist::enqueue(const CFGBlock *block) {
Ted Kremenekc104e532011-01-18 04:53:25 +0000325 if (!block)
326 return;
Ted Kremenek610068c2011-01-15 02:58:47 +0000327 unsigned idx = block->getBlockID();
328 if (enqueuedBlocks[idx])
329 return;
330 worklist.push_back(block);
331 enqueuedBlocks[idx] = true;
332}
333
334void DataflowWorklist::enqueueSuccessors(const clang::CFGBlock *block) {
335 for (CFGBlock::const_succ_iterator I = block->succ_begin(),
336 E = block->succ_end(); I != E; ++I) {
337 enqueue(*I);
338 }
339}
340
341const CFGBlock *DataflowWorklist::dequeue() {
342 if (worklist.empty())
343 return 0;
344 const CFGBlock *b = worklist.back();
345 worklist.pop_back();
346 enqueuedBlocks[b->getBlockID()] = false;
347 return b;
348}
349
350//------------------------------------------------------------------------====//
351// Transfer function for uninitialized values analysis.
352//====------------------------------------------------------------------------//
353
Ted Kremenek610068c2011-01-15 02:58:47 +0000354namespace {
355class FindVarResult {
356 const VarDecl *vd;
357 const DeclRefExpr *dr;
358public:
359 FindVarResult(VarDecl *vd, DeclRefExpr *dr) : vd(vd), dr(dr) {}
360
361 const DeclRefExpr *getDeclRefExpr() const { return dr; }
362 const VarDecl *getDecl() const { return vd; }
363};
364
365class TransferFunctions : public CFGRecStmtVisitor<TransferFunctions> {
366 CFGBlockValues &vals;
367 const CFG &cfg;
Ted Kremeneka8c17a52011-01-25 19:13:48 +0000368 AnalysisContext &ac;
Ted Kremenek610068c2011-01-15 02:58:47 +0000369 UninitVariablesHandler *handler;
Ted Kremenekc21fed32011-01-18 21:18:58 +0000370 const DeclRefExpr *currentDR;
Ted Kremenekdd0f7942011-01-26 04:49:43 +0000371 const Expr *currentVoidCast;
Ted Kremeneka8c17a52011-01-25 19:13:48 +0000372 const bool flagBlockUses;
Ted Kremenek610068c2011-01-15 02:58:47 +0000373public:
374 TransferFunctions(CFGBlockValues &vals, const CFG &cfg,
Ted Kremeneka8c17a52011-01-25 19:13:48 +0000375 AnalysisContext &ac,
376 UninitVariablesHandler *handler,
377 bool flagBlockUses)
378 : vals(vals), cfg(cfg), ac(ac), handler(handler), currentDR(0),
Ted Kremenekdd0f7942011-01-26 04:49:43 +0000379 currentVoidCast(0), flagBlockUses(flagBlockUses) {}
Ted Kremenek610068c2011-01-15 02:58:47 +0000380
381 const CFG &getCFG() { return cfg; }
Ted Kremenekf7bafc72011-03-15 04:57:38 +0000382 void reportUninit(const DeclRefExpr *ex, const VarDecl *vd,
383 bool isAlwaysUninit);
Ted Kremeneka8c17a52011-01-25 19:13:48 +0000384
385 void VisitBlockExpr(BlockExpr *be);
Ted Kremenek610068c2011-01-15 02:58:47 +0000386 void VisitDeclStmt(DeclStmt *ds);
Ted Kremenekc21fed32011-01-18 21:18:58 +0000387 void VisitDeclRefExpr(DeclRefExpr *dr);
Ted Kremenek610068c2011-01-15 02:58:47 +0000388 void VisitUnaryOperator(UnaryOperator *uo);
389 void VisitBinaryOperator(BinaryOperator *bo);
390 void VisitCastExpr(CastExpr *ce);
Peter Collingbournef4e3cfb2011-03-11 19:24:49 +0000391 void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *se);
Ted Kremenek1ea800c2011-01-27 02:01:31 +0000392 void BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt *fs);
Ted Kremenek40900ee2011-01-27 02:29:34 +0000393
394 bool isTrackedVar(const VarDecl *vd) {
Ted Kremenekb831c672011-03-29 01:40:00 +0000395#if 1
396 // FIXME: This is a temporary workaround to deal with the fact
397 // that DeclContext's do not always contain all of their variables!
398 return vals.hasEntry(vd);
399#else
Ted Kremenek40900ee2011-01-27 02:29:34 +0000400 return ::isTrackedVar(vd, cast<DeclContext>(ac.getDecl()));
Ted Kremenekb831c672011-03-29 01:40:00 +0000401#endif
Ted Kremenek40900ee2011-01-27 02:29:34 +0000402 }
403
404 FindVarResult findBlockVarDecl(Expr *ex);
Ted Kremenek610068c2011-01-15 02:58:47 +0000405};
406}
407
408void TransferFunctions::reportUninit(const DeclRefExpr *ex,
Ted Kremenekf7bafc72011-03-15 04:57:38 +0000409 const VarDecl *vd, bool isAlwaysUnit) {
410 if (handler) handler->handleUseOfUninitVariable(ex, vd, isAlwaysUnit);
Ted Kremenek610068c2011-01-15 02:58:47 +0000411}
412
Ted Kremenek40900ee2011-01-27 02:29:34 +0000413FindVarResult TransferFunctions::findBlockVarDecl(Expr* ex) {
Ted Kremenek1ea800c2011-01-27 02:01:31 +0000414 if (DeclRefExpr* dr = dyn_cast<DeclRefExpr>(ex->IgnoreParenCasts()))
415 if (VarDecl *vd = dyn_cast<VarDecl>(dr->getDecl()))
416 if (isTrackedVar(vd))
Ted Kremenek40900ee2011-01-27 02:29:34 +0000417 return FindVarResult(vd, dr);
Ted Kremenek1ea800c2011-01-27 02:01:31 +0000418 return FindVarResult(0, 0);
419}
420
421void TransferFunctions::BlockStmt_VisitObjCForCollectionStmt(
422 ObjCForCollectionStmt *fs) {
423
424 Visit(fs->getCollection());
425
426 // This represents an initialization of the 'element' value.
427 Stmt *element = fs->getElement();
428 const VarDecl* vd = 0;
429
430 if (DeclStmt* ds = dyn_cast<DeclStmt>(element)) {
431 vd = cast<VarDecl>(ds->getSingleDecl());
432 if (!isTrackedVar(vd))
433 vd = 0;
434 }
435 else {
436 // Initialize the value of the reference variable.
437 const FindVarResult &res = findBlockVarDecl(cast<Expr>(element));
438 vd = res.getDecl();
439 if (!vd) {
440 Visit(element);
441 return;
442 }
443 }
444
445 if (vd)
446 vals[vd] = Initialized;
447}
448
Ted Kremeneka8c17a52011-01-25 19:13:48 +0000449void TransferFunctions::VisitBlockExpr(BlockExpr *be) {
450 if (!flagBlockUses || !handler)
451 return;
Ted Kremenekbc8b44c2011-03-31 22:32:41 +0000452 const BlockDecl *bd = be->getBlockDecl();
453 for (BlockDecl::capture_const_iterator i = bd->capture_begin(),
454 e = bd->capture_end() ; i != e; ++i) {
455 const VarDecl *vd = i->getVariable();
456 if (!vd->hasLocalStorage())
Ted Kremeneka8c17a52011-01-25 19:13:48 +0000457 continue;
Ted Kremenekbc8b44c2011-03-31 22:32:41 +0000458 if (!isTrackedVar(vd))
459 continue;
460 if (i->isByRef()) {
461 vals[vd] = Initialized;
462 continue;
463 }
Ted Kremenekf7bafc72011-03-15 04:57:38 +0000464 Value v = vals[vd];
465 if (isUninitialized(v))
466 handler->handleUseOfUninitVariable(be, vd, isAlwaysUninit(v));
Ted Kremeneka8c17a52011-01-25 19:13:48 +0000467 }
468}
469
Ted Kremenek610068c2011-01-15 02:58:47 +0000470void TransferFunctions::VisitDeclStmt(DeclStmt *ds) {
471 for (DeclStmt::decl_iterator DI = ds->decl_begin(), DE = ds->decl_end();
472 DI != DE; ++DI) {
473 if (VarDecl *vd = dyn_cast<VarDecl>(*DI)) {
Ted Kremenek4dccb902011-01-18 05:00:42 +0000474 if (isTrackedVar(vd)) {
Ted Kremenek610068c2011-01-15 02:58:47 +0000475 if (Stmt *init = vd->getInit()) {
Ted Kremenek610068c2011-01-15 02:58:47 +0000476 Visit(init);
Ted Kremenekc104e532011-01-18 04:53:25 +0000477 vals[vd] = Initialized;
Ted Kremenek610068c2011-01-15 02:58:47 +0000478 }
Ted Kremenek4dccb902011-01-18 05:00:42 +0000479 }
Ted Kremenekc21fed32011-01-18 21:18:58 +0000480 else if (Stmt *init = vd->getInit()) {
481 Visit(init);
482 }
Ted Kremenek610068c2011-01-15 02:58:47 +0000483 }
484 }
485}
486
Ted Kremenekc21fed32011-01-18 21:18:58 +0000487void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) {
488 // We assume that DeclRefExprs wrapped in an lvalue-to-rvalue cast
489 // cannot be block-level expressions. Therefore, we determine if
490 // a DeclRefExpr is involved in a "load" by comparing it to the current
491 // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr.
492 // If a DeclRefExpr is not involved in a load, we are essentially computing
493 // its address, either for assignment to a reference or via the '&' operator.
494 // In such cases, treat the variable as being initialized, since this
495 // analysis isn't powerful enough to do alias tracking.
496 if (dr != currentDR)
497 if (const VarDecl *vd = dyn_cast<VarDecl>(dr->getDecl()))
498 if (isTrackedVar(vd))
499 vals[vd] = Initialized;
500}
501
Ted Kremenek610068c2011-01-15 02:58:47 +0000502void TransferFunctions::VisitBinaryOperator(clang::BinaryOperator *bo) {
Ted Kremenek610068c2011-01-15 02:58:47 +0000503 if (bo->isAssignmentOp()) {
504 const FindVarResult &res = findBlockVarDecl(bo->getLHS());
505 if (const VarDecl* vd = res.getDecl()) {
Ted Kremenekc21fed32011-01-18 21:18:58 +0000506 // We assume that DeclRefExprs wrapped in a BinaryOperator "assignment"
507 // cannot be block-level expressions. Therefore, we determine if
508 // a DeclRefExpr is involved in a "load" by comparing it to the current
509 // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr.
510 SaveAndRestore<const DeclRefExpr*> lastDR(currentDR,
511 res.getDeclRefExpr());
512 Visit(bo->getRHS());
513 Visit(bo->getLHS());
514
Ted Kremenek496398d2011-03-15 04:57:32 +0000515 ValueVector::reference val = vals[vd];
Ted Kremenekf7bafc72011-03-15 04:57:38 +0000516 if (isUninitialized(val)) {
Ted Kremenek610068c2011-01-15 02:58:47 +0000517 if (bo->getOpcode() != BO_Assign)
Ted Kremenekf7bafc72011-03-15 04:57:38 +0000518 reportUninit(res.getDeclRefExpr(), vd, isAlwaysUninit(val));
Ted Kremenek496398d2011-03-15 04:57:32 +0000519 val = Initialized;
Ted Kremenek610068c2011-01-15 02:58:47 +0000520 }
Ted Kremenekc21fed32011-01-18 21:18:58 +0000521 return;
Ted Kremenek610068c2011-01-15 02:58:47 +0000522 }
523 }
Ted Kremenekc21fed32011-01-18 21:18:58 +0000524 Visit(bo->getRHS());
525 Visit(bo->getLHS());
Ted Kremenek610068c2011-01-15 02:58:47 +0000526}
527
528void TransferFunctions::VisitUnaryOperator(clang::UnaryOperator *uo) {
Ted Kremenek610068c2011-01-15 02:58:47 +0000529 switch (uo->getOpcode()) {
Ted Kremenek610068c2011-01-15 02:58:47 +0000530 case clang::UO_PostDec:
531 case clang::UO_PostInc:
532 case clang::UO_PreDec:
533 case clang::UO_PreInc: {
534 const FindVarResult &res = findBlockVarDecl(uo->getSubExpr());
535 if (const VarDecl *vd = res.getDecl()) {
Ted Kremenekc21fed32011-01-18 21:18:58 +0000536 // We assume that DeclRefExprs wrapped in a unary operator ++/--
537 // cannot be block-level expressions. Therefore, we determine if
538 // a DeclRefExpr is involved in a "load" by comparing it to the current
539 // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr.
540 SaveAndRestore<const DeclRefExpr*> lastDR(currentDR,
541 res.getDeclRefExpr());
542 Visit(uo->getSubExpr());
543
Ted Kremenekf7bafc72011-03-15 04:57:38 +0000544 ValueVector::reference val = vals[vd];
545 if (isUninitialized(val)) {
546 reportUninit(res.getDeclRefExpr(), vd, isAlwaysUninit(val));
547 // Don't cascade warnings.
548 val = Initialized;
Ted Kremenek610068c2011-01-15 02:58:47 +0000549 }
Ted Kremenekc21fed32011-01-18 21:18:58 +0000550 return;
Ted Kremenek610068c2011-01-15 02:58:47 +0000551 }
552 break;
553 }
554 default:
555 break;
556 }
Ted Kremenekc21fed32011-01-18 21:18:58 +0000557 Visit(uo->getSubExpr());
Ted Kremenek610068c2011-01-15 02:58:47 +0000558}
559
560void TransferFunctions::VisitCastExpr(clang::CastExpr *ce) {
Ted Kremenek610068c2011-01-15 02:58:47 +0000561 if (ce->getCastKind() == CK_LValueToRValue) {
562 const FindVarResult &res = findBlockVarDecl(ce->getSubExpr());
Ted Kremenekc21fed32011-01-18 21:18:58 +0000563 if (const VarDecl *vd = res.getDecl()) {
564 // We assume that DeclRefExprs wrapped in an lvalue-to-rvalue cast
565 // cannot be block-level expressions. Therefore, we determine if
566 // a DeclRefExpr is involved in a "load" by comparing it to the current
567 // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr.
568 // Here we update 'currentDR' to be the one associated with this
569 // lvalue-to-rvalue cast. Then, when we analyze the DeclRefExpr, we
570 // will know that we are not computing its lvalue for other purposes
571 // than to perform a load.
572 SaveAndRestore<const DeclRefExpr*> lastDR(currentDR,
573 res.getDeclRefExpr());
574 Visit(ce->getSubExpr());
Ted Kremenekf7bafc72011-03-15 04:57:38 +0000575 if (currentVoidCast != ce) {
576 Value val = vals[vd];
577 if (isUninitialized(val)) {
578 reportUninit(res.getDeclRefExpr(), vd, isAlwaysUninit(val));
579 // Don't cascade warnings.
580 vals[vd] = Initialized;
581 }
Ted Kremenekc21fed32011-01-18 21:18:58 +0000582 }
583 return;
584 }
Ted Kremenekdd0f7942011-01-26 04:49:43 +0000585 }
586 else if (CStyleCastExpr *cse = dyn_cast<CStyleCastExpr>(ce)) {
587 if (cse->getType()->isVoidType()) {
588 // e.g. (void) x;
589 SaveAndRestore<const Expr *>
590 lastVoidCast(currentVoidCast, cse->getSubExpr()->IgnoreParens());
591 Visit(cse->getSubExpr());
592 return;
593 }
594 }
Ted Kremenekc21fed32011-01-18 21:18:58 +0000595 Visit(ce->getSubExpr());
Ted Kremenek610068c2011-01-15 02:58:47 +0000596}
597
Peter Collingbournef4e3cfb2011-03-11 19:24:49 +0000598void TransferFunctions::VisitUnaryExprOrTypeTraitExpr(
599 UnaryExprOrTypeTraitExpr *se) {
600 if (se->getKind() == UETT_SizeOf) {
Ted Kremenek96608032011-01-23 17:53:04 +0000601 if (se->getType()->isConstantSizeType())
602 return;
603 // Handle VLAs.
604 Visit(se->getArgumentExpr());
605 }
606}
607
Ted Kremenek610068c2011-01-15 02:58:47 +0000608//------------------------------------------------------------------------====//
609// High-level "driver" logic for uninitialized values analysis.
610//====------------------------------------------------------------------------//
611
Ted Kremenek13bd4232011-01-20 17:37:17 +0000612static bool runOnBlock(const CFGBlock *block, const CFG &cfg,
Ted Kremeneka8c17a52011-01-25 19:13:48 +0000613 AnalysisContext &ac, CFGBlockValues &vals,
Ted Kremenekf8adeef2011-04-04 20:30:58 +0000614 llvm::BitVector &wasAnalyzed,
Ted Kremeneka8c17a52011-01-25 19:13:48 +0000615 UninitVariablesHandler *handler = 0,
616 bool flagBlockUses = false) {
Ted Kremenek13bd4232011-01-20 17:37:17 +0000617
Ted Kremenekf8adeef2011-04-04 20:30:58 +0000618 wasAnalyzed[block->getBlockID()] = true;
619
Ted Kremenek13bd4232011-01-20 17:37:17 +0000620 if (const BinaryOperator *b = getLogicalOperatorInChain(block)) {
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000621 CFGBlock::const_pred_iterator itr = block->pred_begin();
Ted Kremenek136f8f22011-03-15 04:57:27 +0000622 BVPair vA = vals.getValueVectors(*itr, false);
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000623 ++itr;
Ted Kremenek136f8f22011-03-15 04:57:27 +0000624 BVPair vB = vals.getValueVectors(*itr, false);
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000625
626 BVPair valsAB;
627
628 if (b->getOpcode() == BO_LAnd) {
629 // Merge the 'F' bits from the first and second.
630 vals.mergeIntoScratch(*(vA.second ? vA.second : vA.first), true);
631 vals.mergeIntoScratch(*(vB.second ? vB.second : vB.first), false);
632 valsAB.first = vA.first;
Ted Kremenek2d4bed12011-01-20 21:25:31 +0000633 valsAB.second = &vals.getScratch();
Ted Kremenek13bd4232011-01-20 17:37:17 +0000634 }
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000635 else {
636 // Merge the 'T' bits from the first and second.
637 assert(b->getOpcode() == BO_LOr);
638 vals.mergeIntoScratch(*vA.first, true);
639 vals.mergeIntoScratch(*vB.first, false);
640 valsAB.first = &vals.getScratch();
641 valsAB.second = vA.second ? vA.second : vA.first;
642 }
Ted Kremenek136f8f22011-03-15 04:57:27 +0000643 return vals.updateValueVectors(block, valsAB);
Ted Kremenek13bd4232011-01-20 17:37:17 +0000644 }
645
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000646 // Default behavior: merge in values of predecessor blocks.
Ted Kremenek610068c2011-01-15 02:58:47 +0000647 vals.resetScratch();
648 bool isFirst = true;
649 for (CFGBlock::const_pred_iterator I = block->pred_begin(),
650 E = block->pred_end(); I != E; ++I) {
Ted Kremenek136f8f22011-03-15 04:57:27 +0000651 vals.mergeIntoScratch(vals.getValueVector(*I, block), isFirst);
Ted Kremenek610068c2011-01-15 02:58:47 +0000652 isFirst = false;
653 }
654 // Apply the transfer function.
Ted Kremeneka8c17a52011-01-25 19:13:48 +0000655 TransferFunctions tf(vals, cfg, ac, handler, flagBlockUses);
Ted Kremenek610068c2011-01-15 02:58:47 +0000656 for (CFGBlock::const_iterator I = block->begin(), E = block->end();
657 I != E; ++I) {
658 if (const CFGStmt *cs = dyn_cast<CFGStmt>(&*I)) {
659 tf.BlockStmt_Visit(cs->getStmt());
660 }
661 }
Ted Kremenek136f8f22011-03-15 04:57:27 +0000662 return vals.updateValueVectorWithScratch(block);
Ted Kremenek610068c2011-01-15 02:58:47 +0000663}
664
665void clang::runUninitializedVariablesAnalysis(const DeclContext &dc,
666 const CFG &cfg,
Ted Kremeneka8c17a52011-01-25 19:13:48 +0000667 AnalysisContext &ac,
Ted Kremenek610068c2011-01-15 02:58:47 +0000668 UninitVariablesHandler &handler) {
669 CFGBlockValues vals(cfg);
670 vals.computeSetOfDeclarations(dc);
671 if (vals.hasNoDeclarations())
672 return;
Ted Kremenekd40066b2011-04-04 23:29:12 +0000673
674 // Mark all variables uninitialized at the entry.
675 const CFGBlock &entry = cfg.getEntry();
676 for (CFGBlock::const_succ_iterator i = entry.succ_begin(),
677 e = entry.succ_end(); i != e; ++i) {
678 if (const CFGBlock *succ = *i) {
679 ValueVector &vec = vals.getValueVector(&entry, succ);
680 const unsigned n = vals.getNumEntries();
681 for (unsigned j = 0; j < n ; ++j) {
682 vec[j] = Uninitialized;
683 }
684 }
685 }
686
687 // Proceed with the workist.
Ted Kremenek610068c2011-01-15 02:58:47 +0000688 DataflowWorklist worklist(cfg);
Ted Kremenek496398d2011-03-15 04:57:32 +0000689 llvm::BitVector previouslyVisited(cfg.getNumBlockIDs());
Ted Kremenek610068c2011-01-15 02:58:47 +0000690 worklist.enqueueSuccessors(&cfg.getEntry());
Ted Kremenekf8adeef2011-04-04 20:30:58 +0000691 llvm::BitVector wasAnalyzed(cfg.getNumBlockIDs(), false);
Ted Kremenek610068c2011-01-15 02:58:47 +0000692
693 while (const CFGBlock *block = worklist.dequeue()) {
Ted Kremenek610068c2011-01-15 02:58:47 +0000694 // Did the block change?
Ted Kremenekf8adeef2011-04-04 20:30:58 +0000695 bool changed = runOnBlock(block, cfg, ac, vals, wasAnalyzed);
Ted Kremenek610068c2011-01-15 02:58:47 +0000696 if (changed || !previouslyVisited[block->getBlockID()])
697 worklist.enqueueSuccessors(block);
698 previouslyVisited[block->getBlockID()] = true;
699 }
700
701 // Run through the blocks one more time, and report uninitialized variabes.
702 for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) {
Ted Kremenekf8adeef2011-04-04 20:30:58 +0000703 if (wasAnalyzed[(*BI)->getBlockID()])
704 runOnBlock(*BI, cfg, ac, vals, wasAnalyzed, &handler,
705 /* flagBlockUses */ true);
Ted Kremenek610068c2011-01-15 02:58:47 +0000706 }
707}
708
709UninitVariablesHandler::~UninitVariablesHandler() {}
710