blob: 062857d86eedde61e6e33f20b06fc5f4a054b273 [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)) {
Chandler Carruthb88fb022011-04-05 21:36:30 +0000475 if (Expr *init = vd->getInit()) {
Ted Kremenek610068c2011-01-15 02:58:47 +0000476 Visit(init);
Chandler Carruthb88fb022011-04-05 21:36:30 +0000477
478 // If the initializer consists solely of a reference to itself, we
479 // explicitly mark the variable as uninitialized. This allows code
480 // like the following:
481 //
482 // int x = x;
483 //
484 // to deliberately leave a variable uninitialized. Different analysis
485 // clients can detect this pattern and adjust their reporting
486 // appropriately, but we need to continue to analyze subsequent uses
487 // of the variable.
488 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(init->IgnoreParenImpCasts());
489 vals[vd] = (DRE && DRE->getDecl() == vd) ? Uninitialized
490 : Initialized;
Ted Kremenek610068c2011-01-15 02:58:47 +0000491 }
Chandler Carruthb88fb022011-04-05 21:36:30 +0000492 } else if (Stmt *init = vd->getInit()) {
Ted Kremenekc21fed32011-01-18 21:18:58 +0000493 Visit(init);
494 }
Ted Kremenek610068c2011-01-15 02:58:47 +0000495 }
496 }
497}
498
Ted Kremenekc21fed32011-01-18 21:18:58 +0000499void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) {
500 // We assume that DeclRefExprs wrapped in an lvalue-to-rvalue cast
501 // cannot be block-level expressions. Therefore, we determine if
502 // a DeclRefExpr is involved in a "load" by comparing it to the current
503 // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr.
504 // If a DeclRefExpr is not involved in a load, we are essentially computing
505 // its address, either for assignment to a reference or via the '&' operator.
506 // In such cases, treat the variable as being initialized, since this
507 // analysis isn't powerful enough to do alias tracking.
508 if (dr != currentDR)
509 if (const VarDecl *vd = dyn_cast<VarDecl>(dr->getDecl()))
510 if (isTrackedVar(vd))
511 vals[vd] = Initialized;
512}
513
Ted Kremenek610068c2011-01-15 02:58:47 +0000514void TransferFunctions::VisitBinaryOperator(clang::BinaryOperator *bo) {
Ted Kremenek610068c2011-01-15 02:58:47 +0000515 if (bo->isAssignmentOp()) {
516 const FindVarResult &res = findBlockVarDecl(bo->getLHS());
517 if (const VarDecl* vd = res.getDecl()) {
Ted Kremenekc21fed32011-01-18 21:18:58 +0000518 // We assume that DeclRefExprs wrapped in a BinaryOperator "assignment"
519 // cannot be block-level expressions. Therefore, we determine if
520 // a DeclRefExpr is involved in a "load" by comparing it to the current
521 // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr.
522 SaveAndRestore<const DeclRefExpr*> lastDR(currentDR,
523 res.getDeclRefExpr());
524 Visit(bo->getRHS());
525 Visit(bo->getLHS());
526
Ted Kremenek496398d2011-03-15 04:57:32 +0000527 ValueVector::reference val = vals[vd];
Ted Kremenekf7bafc72011-03-15 04:57:38 +0000528 if (isUninitialized(val)) {
Ted Kremenek610068c2011-01-15 02:58:47 +0000529 if (bo->getOpcode() != BO_Assign)
Ted Kremenekf7bafc72011-03-15 04:57:38 +0000530 reportUninit(res.getDeclRefExpr(), vd, isAlwaysUninit(val));
Ted Kremenek496398d2011-03-15 04:57:32 +0000531 val = Initialized;
Ted Kremenek610068c2011-01-15 02:58:47 +0000532 }
Ted Kremenekc21fed32011-01-18 21:18:58 +0000533 return;
Ted Kremenek610068c2011-01-15 02:58:47 +0000534 }
535 }
Ted Kremenekc21fed32011-01-18 21:18:58 +0000536 Visit(bo->getRHS());
537 Visit(bo->getLHS());
Ted Kremenek610068c2011-01-15 02:58:47 +0000538}
539
540void TransferFunctions::VisitUnaryOperator(clang::UnaryOperator *uo) {
Ted Kremenek610068c2011-01-15 02:58:47 +0000541 switch (uo->getOpcode()) {
Ted Kremenek610068c2011-01-15 02:58:47 +0000542 case clang::UO_PostDec:
543 case clang::UO_PostInc:
544 case clang::UO_PreDec:
545 case clang::UO_PreInc: {
546 const FindVarResult &res = findBlockVarDecl(uo->getSubExpr());
547 if (const VarDecl *vd = res.getDecl()) {
Ted Kremenekc21fed32011-01-18 21:18:58 +0000548 // We assume that DeclRefExprs wrapped in a unary operator ++/--
549 // cannot be block-level expressions. Therefore, we determine if
550 // a DeclRefExpr is involved in a "load" by comparing it to the current
551 // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr.
552 SaveAndRestore<const DeclRefExpr*> lastDR(currentDR,
553 res.getDeclRefExpr());
554 Visit(uo->getSubExpr());
555
Ted Kremenekf7bafc72011-03-15 04:57:38 +0000556 ValueVector::reference val = vals[vd];
557 if (isUninitialized(val)) {
558 reportUninit(res.getDeclRefExpr(), vd, isAlwaysUninit(val));
559 // Don't cascade warnings.
560 val = Initialized;
Ted Kremenek610068c2011-01-15 02:58:47 +0000561 }
Ted Kremenekc21fed32011-01-18 21:18:58 +0000562 return;
Ted Kremenek610068c2011-01-15 02:58:47 +0000563 }
564 break;
565 }
566 default:
567 break;
568 }
Ted Kremenekc21fed32011-01-18 21:18:58 +0000569 Visit(uo->getSubExpr());
Ted Kremenek610068c2011-01-15 02:58:47 +0000570}
571
572void TransferFunctions::VisitCastExpr(clang::CastExpr *ce) {
Ted Kremenek610068c2011-01-15 02:58:47 +0000573 if (ce->getCastKind() == CK_LValueToRValue) {
574 const FindVarResult &res = findBlockVarDecl(ce->getSubExpr());
Ted Kremenekc21fed32011-01-18 21:18:58 +0000575 if (const VarDecl *vd = res.getDecl()) {
576 // We assume that DeclRefExprs wrapped in an lvalue-to-rvalue cast
577 // cannot be block-level expressions. Therefore, we determine if
578 // a DeclRefExpr is involved in a "load" by comparing it to the current
579 // DeclRefExpr found when analyzing the last lvalue-to-rvalue CastExpr.
580 // Here we update 'currentDR' to be the one associated with this
581 // lvalue-to-rvalue cast. Then, when we analyze the DeclRefExpr, we
582 // will know that we are not computing its lvalue for other purposes
583 // than to perform a load.
584 SaveAndRestore<const DeclRefExpr*> lastDR(currentDR,
585 res.getDeclRefExpr());
586 Visit(ce->getSubExpr());
Ted Kremenekf7bafc72011-03-15 04:57:38 +0000587 if (currentVoidCast != ce) {
588 Value val = vals[vd];
589 if (isUninitialized(val)) {
590 reportUninit(res.getDeclRefExpr(), vd, isAlwaysUninit(val));
591 // Don't cascade warnings.
592 vals[vd] = Initialized;
593 }
Ted Kremenekc21fed32011-01-18 21:18:58 +0000594 }
595 return;
596 }
Ted Kremenekdd0f7942011-01-26 04:49:43 +0000597 }
598 else if (CStyleCastExpr *cse = dyn_cast<CStyleCastExpr>(ce)) {
599 if (cse->getType()->isVoidType()) {
600 // e.g. (void) x;
601 SaveAndRestore<const Expr *>
602 lastVoidCast(currentVoidCast, cse->getSubExpr()->IgnoreParens());
603 Visit(cse->getSubExpr());
604 return;
605 }
606 }
Ted Kremenekc21fed32011-01-18 21:18:58 +0000607 Visit(ce->getSubExpr());
Ted Kremenek610068c2011-01-15 02:58:47 +0000608}
609
Peter Collingbournef4e3cfb2011-03-11 19:24:49 +0000610void TransferFunctions::VisitUnaryExprOrTypeTraitExpr(
611 UnaryExprOrTypeTraitExpr *se) {
612 if (se->getKind() == UETT_SizeOf) {
Ted Kremenek96608032011-01-23 17:53:04 +0000613 if (se->getType()->isConstantSizeType())
614 return;
615 // Handle VLAs.
616 Visit(se->getArgumentExpr());
617 }
618}
619
Ted Kremenek610068c2011-01-15 02:58:47 +0000620//------------------------------------------------------------------------====//
621// High-level "driver" logic for uninitialized values analysis.
622//====------------------------------------------------------------------------//
623
Ted Kremenek13bd4232011-01-20 17:37:17 +0000624static bool runOnBlock(const CFGBlock *block, const CFG &cfg,
Ted Kremeneka8c17a52011-01-25 19:13:48 +0000625 AnalysisContext &ac, CFGBlockValues &vals,
Ted Kremenekf8adeef2011-04-04 20:30:58 +0000626 llvm::BitVector &wasAnalyzed,
Ted Kremeneka8c17a52011-01-25 19:13:48 +0000627 UninitVariablesHandler *handler = 0,
628 bool flagBlockUses = false) {
Ted Kremenek13bd4232011-01-20 17:37:17 +0000629
Ted Kremenekf8adeef2011-04-04 20:30:58 +0000630 wasAnalyzed[block->getBlockID()] = true;
631
Ted Kremenek13bd4232011-01-20 17:37:17 +0000632 if (const BinaryOperator *b = getLogicalOperatorInChain(block)) {
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000633 CFGBlock::const_pred_iterator itr = block->pred_begin();
Ted Kremenek136f8f22011-03-15 04:57:27 +0000634 BVPair vA = vals.getValueVectors(*itr, false);
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000635 ++itr;
Ted Kremenek136f8f22011-03-15 04:57:27 +0000636 BVPair vB = vals.getValueVectors(*itr, false);
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000637
638 BVPair valsAB;
639
640 if (b->getOpcode() == BO_LAnd) {
641 // Merge the 'F' bits from the first and second.
642 vals.mergeIntoScratch(*(vA.second ? vA.second : vA.first), true);
643 vals.mergeIntoScratch(*(vB.second ? vB.second : vB.first), false);
644 valsAB.first = vA.first;
Ted Kremenek2d4bed12011-01-20 21:25:31 +0000645 valsAB.second = &vals.getScratch();
Ted Kremenek13bd4232011-01-20 17:37:17 +0000646 }
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000647 else {
648 // Merge the 'T' bits from the first and second.
649 assert(b->getOpcode() == BO_LOr);
650 vals.mergeIntoScratch(*vA.first, true);
651 vals.mergeIntoScratch(*vB.first, false);
652 valsAB.first = &vals.getScratch();
653 valsAB.second = vA.second ? vA.second : vA.first;
654 }
Ted Kremenek136f8f22011-03-15 04:57:27 +0000655 return vals.updateValueVectors(block, valsAB);
Ted Kremenek13bd4232011-01-20 17:37:17 +0000656 }
657
Ted Kremenek9fcbcee2011-02-01 17:43:18 +0000658 // Default behavior: merge in values of predecessor blocks.
Ted Kremenek610068c2011-01-15 02:58:47 +0000659 vals.resetScratch();
660 bool isFirst = true;
661 for (CFGBlock::const_pred_iterator I = block->pred_begin(),
662 E = block->pred_end(); I != E; ++I) {
Ted Kremenek136f8f22011-03-15 04:57:27 +0000663 vals.mergeIntoScratch(vals.getValueVector(*I, block), isFirst);
Ted Kremenek610068c2011-01-15 02:58:47 +0000664 isFirst = false;
665 }
666 // Apply the transfer function.
Ted Kremeneka8c17a52011-01-25 19:13:48 +0000667 TransferFunctions tf(vals, cfg, ac, handler, flagBlockUses);
Ted Kremenek610068c2011-01-15 02:58:47 +0000668 for (CFGBlock::const_iterator I = block->begin(), E = block->end();
669 I != E; ++I) {
670 if (const CFGStmt *cs = dyn_cast<CFGStmt>(&*I)) {
671 tf.BlockStmt_Visit(cs->getStmt());
672 }
673 }
Ted Kremenek136f8f22011-03-15 04:57:27 +0000674 return vals.updateValueVectorWithScratch(block);
Ted Kremenek610068c2011-01-15 02:58:47 +0000675}
676
677void clang::runUninitializedVariablesAnalysis(const DeclContext &dc,
678 const CFG &cfg,
Ted Kremeneka8c17a52011-01-25 19:13:48 +0000679 AnalysisContext &ac,
Ted Kremenek610068c2011-01-15 02:58:47 +0000680 UninitVariablesHandler &handler) {
681 CFGBlockValues vals(cfg);
682 vals.computeSetOfDeclarations(dc);
683 if (vals.hasNoDeclarations())
684 return;
Ted Kremenekd40066b2011-04-04 23:29:12 +0000685
686 // Mark all variables uninitialized at the entry.
687 const CFGBlock &entry = cfg.getEntry();
688 for (CFGBlock::const_succ_iterator i = entry.succ_begin(),
689 e = entry.succ_end(); i != e; ++i) {
690 if (const CFGBlock *succ = *i) {
691 ValueVector &vec = vals.getValueVector(&entry, succ);
692 const unsigned n = vals.getNumEntries();
693 for (unsigned j = 0; j < n ; ++j) {
694 vec[j] = Uninitialized;
695 }
696 }
697 }
698
699 // Proceed with the workist.
Ted Kremenek610068c2011-01-15 02:58:47 +0000700 DataflowWorklist worklist(cfg);
Ted Kremenek496398d2011-03-15 04:57:32 +0000701 llvm::BitVector previouslyVisited(cfg.getNumBlockIDs());
Ted Kremenek610068c2011-01-15 02:58:47 +0000702 worklist.enqueueSuccessors(&cfg.getEntry());
Ted Kremenekf8adeef2011-04-04 20:30:58 +0000703 llvm::BitVector wasAnalyzed(cfg.getNumBlockIDs(), false);
Ted Kremenek610068c2011-01-15 02:58:47 +0000704
705 while (const CFGBlock *block = worklist.dequeue()) {
Ted Kremenek610068c2011-01-15 02:58:47 +0000706 // Did the block change?
Ted Kremenekf8adeef2011-04-04 20:30:58 +0000707 bool changed = runOnBlock(block, cfg, ac, vals, wasAnalyzed);
Ted Kremenek610068c2011-01-15 02:58:47 +0000708 if (changed || !previouslyVisited[block->getBlockID()])
709 worklist.enqueueSuccessors(block);
710 previouslyVisited[block->getBlockID()] = true;
711 }
712
713 // Run through the blocks one more time, and report uninitialized variabes.
714 for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) {
Ted Kremenekf8adeef2011-04-04 20:30:58 +0000715 if (wasAnalyzed[(*BI)->getBlockID()])
716 runOnBlock(*BI, cfg, ac, vals, wasAnalyzed, &handler,
717 /* flagBlockUses */ true);
Ted Kremenek610068c2011-01-15 02:58:47 +0000718 }
719}
720
721UninitVariablesHandler::~UninitVariablesHandler() {}
722