1//==- UninitializedValues.cpp - Find Uninitialized Values -------*- C++ --*-==//
2//
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
14#include <utility>
15#include "llvm/ADT/Optional.h"
16#include "llvm/ADT/SmallVector.h"
17#include "llvm/ADT/PackedVector.h"
18#include "llvm/ADT/DenseMap.h"
19#include "clang/AST/ASTContext.h"
20#include "clang/AST/Decl.h"
21#include "clang/Analysis/CFG.h"
22#include "clang/Analysis/AnalysisContext.h"
23#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
24#include "clang/Analysis/Analyses/UninitializedValues.h"
25#include "llvm/Support/SaveAndRestore.h"
26
27using namespace clang;
28
29#define DEBUG_LOGGING 0
30
31static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) {
32  if (vd->isLocalVarDecl() && !vd->hasGlobalStorage() &&
33      !vd->isExceptionVariable() &&
34      vd->getDeclContext() == dc) {
35    QualType ty = vd->getType();
36    return ty->isScalarType() || ty->isVectorType();
37  }
38  return false;
39}
40
41//------------------------------------------------------------------------====//
42// DeclToIndex: a mapping from Decls we track to value indices.
43//====------------------------------------------------------------------------//
44
45namespace {
46class DeclToIndex {
47  llvm::DenseMap<const VarDecl *, unsigned> map;
48public:
49  DeclToIndex() {}
50
51  /// Compute the actual mapping from declarations to bits.
52  void computeMap(const DeclContext &dc);
53
54  /// Return the number of declarations in the map.
55  unsigned size() const { return map.size(); }
56
57  /// Returns the bit vector index for a given declaration.
58  llvm::Optional<unsigned> getValueIndex(const VarDecl *d) const;
59};
60}
61
62void DeclToIndex::computeMap(const DeclContext &dc) {
63  unsigned count = 0;
64  DeclContext::specific_decl_iterator<VarDecl> I(dc.decls_begin()),
65                                               E(dc.decls_end());
66  for ( ; I != E; ++I) {
67    const VarDecl *vd = *I;
68    if (isTrackedVar(vd, &dc))
69      map[vd] = count++;
70  }
71}
72
73llvm::Optional<unsigned> DeclToIndex::getValueIndex(const VarDecl *d) const {
74  llvm::DenseMap<const VarDecl *, unsigned>::const_iterator I = map.find(d);
75  if (I == map.end())
76    return llvm::Optional<unsigned>();
77  return I->second;
78}
79
80//------------------------------------------------------------------------====//
81// CFGBlockValues: dataflow values for CFG blocks.
82//====------------------------------------------------------------------------//
83
84// These values are defined in such a way that a merge can be done using
85// a bitwise OR.
86enum Value { Unknown = 0x0,         /* 00 */
87             Initialized = 0x1,     /* 01 */
88             Uninitialized = 0x2,   /* 10 */
89             MayUninitialized = 0x3 /* 11 */ };
90
91static bool isUninitialized(const Value v) {
92  return v >= Uninitialized;
93}
94static bool isAlwaysUninit(const Value v) {
95  return v == Uninitialized;
96}
97
98namespace {
99
100typedef llvm::PackedVector<Value, 2> ValueVector;
101
102class CFGBlockValues {
103  const CFG &cfg;
104  std::vector<ValueVector*> vals;
105  ValueVector scratch;
106  DeclToIndex declToIndex;
107public:
108  CFGBlockValues(const CFG &cfg);
109  ~CFGBlockValues();
110
111  unsigned getNumEntries() const { return declToIndex.size(); }
112
113  void computeSetOfDeclarations(const DeclContext &dc);
114  ValueVector &getValueVector(const CFGBlock *block) {
115    return *vals[block->getBlockID()];
116  }
117
118  void setAllScratchValues(Value V);
119  void mergeIntoScratch(ValueVector const &source, bool isFirst);
120  bool updateValueVectorWithScratch(const CFGBlock *block);
121
122  bool hasNoDeclarations() const {
123    return declToIndex.size() == 0;
124  }
125
126  void resetScratch();
127
128  ValueVector::reference operator[](const VarDecl *vd);
129
130  Value getValue(const CFGBlock *block, const CFGBlock *dstBlock,
131                 const VarDecl *vd) {
132    const llvm::Optional<unsigned> &idx = declToIndex.getValueIndex(vd);
133    assert(idx.hasValue());
134    return getValueVector(block)[idx.getValue()];
135  }
136};
137} // end anonymous namespace
138
139CFGBlockValues::CFGBlockValues(const CFG &c) : cfg(c), vals(0) {}
140
141CFGBlockValues::~CFGBlockValues() {
142  for (std::vector<ValueVector*>::iterator I = vals.begin(), E = vals.end();
143       I != E; ++I)
144    delete *I;
145}
146
147void CFGBlockValues::computeSetOfDeclarations(const DeclContext &dc) {
148  declToIndex.computeMap(dc);
149  unsigned decls = declToIndex.size();
150  scratch.resize(decls);
151  unsigned n = cfg.getNumBlockIDs();
152  if (!n)
153    return;
154  vals.resize(n);
155  for (unsigned i = 0; i < n; ++i)
156    vals[i] = new ValueVector(decls);
157}
158
159#if DEBUG_LOGGING
160static void printVector(const CFGBlock *block, ValueVector &bv,
161                        unsigned num) {
162  llvm::errs() << block->getBlockID() << " :";
163  for (unsigned i = 0; i < bv.size(); ++i) {
164    llvm::errs() << ' ' << bv[i];
165  }
166  llvm::errs() << " : " << num << '\n';
167}
168#endif
169
170void CFGBlockValues::setAllScratchValues(Value V) {
171  for (unsigned I = 0, E = scratch.size(); I != E; ++I)
172    scratch[I] = V;
173}
174
175void CFGBlockValues::mergeIntoScratch(ValueVector const &source,
176                                      bool isFirst) {
177  if (isFirst)
178    scratch = source;
179  else
180    scratch |= source;
181}
182
183bool CFGBlockValues::updateValueVectorWithScratch(const CFGBlock *block) {
184  ValueVector &dst = getValueVector(block);
185  bool changed = (dst != scratch);
186  if (changed)
187    dst = scratch;
188#if DEBUG_LOGGING
189  printVector(block, scratch, 0);
190#endif
191  return changed;
192}
193
194void CFGBlockValues::resetScratch() {
195  scratch.reset();
196}
197
198ValueVector::reference CFGBlockValues::operator[](const VarDecl *vd) {
199  const llvm::Optional<unsigned> &idx = declToIndex.getValueIndex(vd);
200  assert(idx.hasValue());
201  return scratch[idx.getValue()];
202}
203
204//------------------------------------------------------------------------====//
205// Worklist: worklist for dataflow analysis.
206//====------------------------------------------------------------------------//
207
208namespace {
209class DataflowWorklist {
210  SmallVector<const CFGBlock *, 20> worklist;
211  llvm::BitVector enqueuedBlocks;
212public:
213  DataflowWorklist(const CFG &cfg) : enqueuedBlocks(cfg.getNumBlockIDs()) {}
214
215  void enqueueSuccessors(const CFGBlock *block);
216  const CFGBlock *dequeue();
217};
218}
219
220void DataflowWorklist::enqueueSuccessors(const clang::CFGBlock *block) {
221  unsigned OldWorklistSize = worklist.size();
222  for (CFGBlock::const_succ_iterator I = block->succ_begin(),
223       E = block->succ_end(); I != E; ++I) {
224    const CFGBlock *Successor = *I;
225    if (!Successor || enqueuedBlocks[Successor->getBlockID()])
226      continue;
227    worklist.push_back(Successor);
228    enqueuedBlocks[Successor->getBlockID()] = true;
229  }
230  if (OldWorklistSize == 0 || OldWorklistSize == worklist.size())
231    return;
232
233  // Rotate the newly added blocks to the start of the worklist so that it forms
234  // a proper queue when we pop off the end of the worklist.
235  std::rotate(worklist.begin(), worklist.begin() + OldWorklistSize,
236              worklist.end());
237}
238
239const CFGBlock *DataflowWorklist::dequeue() {
240  if (worklist.empty())
241    return 0;
242  const CFGBlock *b = worklist.back();
243  worklist.pop_back();
244  enqueuedBlocks[b->getBlockID()] = false;
245  return b;
246}
247
248//------------------------------------------------------------------------====//
249// Classification of DeclRefExprs as use or initialization.
250//====------------------------------------------------------------------------//
251
252namespace {
253class FindVarResult {
254  const VarDecl *vd;
255  const DeclRefExpr *dr;
256public:
257  FindVarResult(const VarDecl *vd, const DeclRefExpr *dr) : vd(vd), dr(dr) {}
258
259  const DeclRefExpr *getDeclRefExpr() const { return dr; }
260  const VarDecl *getDecl() const { return vd; }
261};
262
263static const Expr *stripCasts(ASTContext &C, const Expr *Ex) {
264  while (Ex) {
265    Ex = Ex->IgnoreParenNoopCasts(C);
266    if (const CastExpr *CE = dyn_cast<CastExpr>(Ex)) {
267      if (CE->getCastKind() == CK_LValueBitCast) {
268        Ex = CE->getSubExpr();
269        continue;
270      }
271    }
272    break;
273  }
274  return Ex;
275}
276
277/// If E is an expression comprising a reference to a single variable, find that
278/// variable.
279static FindVarResult findVar(const Expr *E, const DeclContext *DC) {
280  if (const DeclRefExpr *DRE =
281        dyn_cast<DeclRefExpr>(stripCasts(DC->getParentASTContext(), E)))
282    if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
283      if (isTrackedVar(VD, DC))
284        return FindVarResult(VD, DRE);
285  return FindVarResult(0, 0);
286}
287
288/// \brief Classify each DeclRefExpr as an initialization or a use. Any
289/// DeclRefExpr which isn't explicitly classified will be assumed to have
290/// escaped the analysis and will be treated as an initialization.
291class ClassifyRefs : public StmtVisitor<ClassifyRefs> {
292public:
293  enum Class {
294    Init,
295    Use,
296    SelfInit,
297    Ignore
298  };
299
300private:
301  const DeclContext *DC;
302  llvm::DenseMap<const DeclRefExpr*, Class> Classification;
303
304  bool isTrackedVar(const VarDecl *VD) const {
305    return ::isTrackedVar(VD, DC);
306  }
307
308  void classify(const Expr *E, Class C);
309
310public:
311  ClassifyRefs(AnalysisDeclContext &AC) : DC(cast<DeclContext>(AC.getDecl())) {}
312
313  void VisitDeclStmt(DeclStmt *DS);
314  void VisitUnaryOperator(UnaryOperator *UO);
315  void VisitBinaryOperator(BinaryOperator *BO);
316  void VisitCallExpr(CallExpr *CE);
317  void VisitCastExpr(CastExpr *CE);
318
319  void operator()(Stmt *S) { Visit(S); }
320
321  Class get(const DeclRefExpr *DRE) const {
322    llvm::DenseMap<const DeclRefExpr*, Class>::const_iterator I
323        = Classification.find(DRE);
324    if (I != Classification.end())
325      return I->second;
326
327    const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
328    if (!VD || !isTrackedVar(VD))
329      return Ignore;
330
331    return Init;
332  }
333};
334}
335
336static const DeclRefExpr *getSelfInitExpr(VarDecl *VD) {
337  if (Expr *Init = VD->getInit()) {
338    const DeclRefExpr *DRE
339      = dyn_cast<DeclRefExpr>(stripCasts(VD->getASTContext(), Init));
340    if (DRE && DRE->getDecl() == VD)
341      return DRE;
342  }
343  return 0;
344}
345
346void ClassifyRefs::classify(const Expr *E, Class C) {
347  FindVarResult Var = findVar(E, DC);
348  if (const DeclRefExpr *DRE = Var.getDeclRefExpr())
349    Classification[DRE] = std::max(Classification[DRE], C);
350}
351
352void ClassifyRefs::VisitDeclStmt(DeclStmt *DS) {
353  for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
354       DI != DE; ++DI) {
355    VarDecl *VD = dyn_cast<VarDecl>(*DI);
356    if (VD && isTrackedVar(VD))
357      if (const DeclRefExpr *DRE = getSelfInitExpr(VD))
358        Classification[DRE] = SelfInit;
359  }
360}
361
362void ClassifyRefs::VisitBinaryOperator(BinaryOperator *BO) {
363  // Ignore the evaluation of a DeclRefExpr on the LHS of an assignment. If this
364  // is not a compound-assignment, we will treat it as initializing the variable
365  // when TransferFunctions visits it. A compound-assignment does not affect
366  // whether a variable is uninitialized, and there's no point counting it as a
367  // use.
368  if (BO->isCompoundAssignmentOp())
369    classify(BO->getLHS(), Use);
370  else if (BO->getOpcode() == BO_Assign)
371    classify(BO->getLHS(), Ignore);
372}
373
374void ClassifyRefs::VisitUnaryOperator(UnaryOperator *UO) {
375  // Increment and decrement are uses despite there being no lvalue-to-rvalue
376  // conversion.
377  if (UO->isIncrementDecrementOp())
378    classify(UO->getSubExpr(), Use);
379}
380
381void ClassifyRefs::VisitCallExpr(CallExpr *CE) {
382  // If a value is passed by const reference to a function, we should not assume
383  // that it is initialized by the call, and we conservatively do not assume
384  // that it is used.
385  for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
386       I != E; ++I)
387    if ((*I)->getType().isConstQualified() && (*I)->isGLValue())
388      classify(*I, Ignore);
389}
390
391void ClassifyRefs::VisitCastExpr(CastExpr *CE) {
392  if (CE->getCastKind() == CK_LValueToRValue)
393    classify(CE->getSubExpr(), Use);
394  else if (CStyleCastExpr *CSE = dyn_cast<CStyleCastExpr>(CE)) {
395    if (CSE->getType()->isVoidType()) {
396      // Squelch any detected load of an uninitialized value if
397      // we cast it to void.
398      // e.g. (void) x;
399      classify(CSE->getSubExpr(), Ignore);
400    }
401  }
402}
403
404//------------------------------------------------------------------------====//
405// Transfer function for uninitialized values analysis.
406//====------------------------------------------------------------------------//
407
408namespace {
409class TransferFunctions : public StmtVisitor<TransferFunctions> {
410  CFGBlockValues &vals;
411  const CFG &cfg;
412  const CFGBlock *block;
413  AnalysisDeclContext &ac;
414  const ClassifyRefs &classification;
415  UninitVariablesHandler *handler;
416
417public:
418  TransferFunctions(CFGBlockValues &vals, const CFG &cfg,
419                    const CFGBlock *block, AnalysisDeclContext &ac,
420                    const ClassifyRefs &classification,
421                    UninitVariablesHandler *handler)
422    : vals(vals), cfg(cfg), block(block), ac(ac),
423      classification(classification), handler(handler) {}
424
425  void reportUse(const Expr *ex, const VarDecl *vd);
426
427  void VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS);
428  void VisitBlockExpr(BlockExpr *be);
429  void VisitCallExpr(CallExpr *ce);
430  void VisitDeclStmt(DeclStmt *ds);
431  void VisitDeclRefExpr(DeclRefExpr *dr);
432  void VisitBinaryOperator(BinaryOperator *bo);
433
434  bool isTrackedVar(const VarDecl *vd) {
435    return ::isTrackedVar(vd, cast<DeclContext>(ac.getDecl()));
436  }
437
438  FindVarResult findVar(const Expr *ex) {
439    return ::findVar(ex, cast<DeclContext>(ac.getDecl()));
440  }
441
442  UninitUse getUninitUse(const Expr *ex, const VarDecl *vd, Value v) {
443    UninitUse Use(ex, isAlwaysUninit(v));
444
445    assert(isUninitialized(v));
446    if (Use.getKind() == UninitUse::Always)
447      return Use;
448
449    // If an edge which leads unconditionally to this use did not initialize
450    // the variable, we can say something stronger than 'may be uninitialized':
451    // we can say 'either it's used uninitialized or you have dead code'.
452    //
453    // We track the number of successors of a node which have been visited, and
454    // visit a node once we have visited all of its successors. Only edges where
455    // the variable might still be uninitialized are followed. Since a variable
456    // can't transfer from being initialized to being uninitialized, this will
457    // trace out the subgraph which inevitably leads to the use and does not
458    // initialize the variable. We do not want to skip past loops, since their
459    // non-termination might be correlated with the initialization condition.
460    //
461    // For example:
462    //
463    //         void f(bool a, bool b) {
464    // block1:   int n;
465    //           if (a) {
466    // block2:     if (b)
467    // block3:       n = 1;
468    // block4:   } else if (b) {
469    // block5:     while (!a) {
470    // block6:       do_work(&a);
471    //               n = 2;
472    //             }
473    //           }
474    // block7:   if (a)
475    // block8:     g();
476    // block9:   return n;
477    //         }
478    //
479    // Starting from the maybe-uninitialized use in block 9:
480    //  * Block 7 is not visited because we have only visited one of its two
481    //    successors.
482    //  * Block 8 is visited because we've visited its only successor.
483    // From block 8:
484    //  * Block 7 is visited because we've now visited both of its successors.
485    // From block 7:
486    //  * Blocks 1, 2, 4, 5, and 6 are not visited because we didn't visit all
487    //    of their successors (we didn't visit 4, 3, 5, 6, and 5, respectively).
488    //  * Block 3 is not visited because it initializes 'n'.
489    // Now the algorithm terminates, having visited blocks 7 and 8, and having
490    // found the frontier is blocks 2, 4, and 5.
491    //
492    // 'n' is definitely uninitialized for two edges into block 7 (from blocks 2
493    // and 4), so we report that any time either of those edges is taken (in
494    // each case when 'b == false'), 'n' is used uninitialized.
495    llvm::SmallVector<const CFGBlock*, 32> Queue;
496    llvm::SmallVector<unsigned, 32> SuccsVisited(cfg.getNumBlockIDs(), 0);
497    Queue.push_back(block);
498    // Specify that we've already visited all successors of the starting block.
499    // This has the dual purpose of ensuring we never add it to the queue, and
500    // of marking it as not being a candidate element of the frontier.
501    SuccsVisited[block->getBlockID()] = block->succ_size();
502    while (!Queue.empty()) {
503      const CFGBlock *B = Queue.back();
504      Queue.pop_back();
505      for (CFGBlock::const_pred_iterator I = B->pred_begin(), E = B->pred_end();
506           I != E; ++I) {
507        const CFGBlock *Pred = *I;
508        if (vals.getValue(Pred, B, vd) == Initialized)
509          // This block initializes the variable.
510          continue;
511
512        unsigned &SV = SuccsVisited[Pred->getBlockID()];
513        if (!SV) {
514          // When visiting the first successor of a block, mark all NULL
515          // successors as having been visited.
516          for (CFGBlock::const_succ_iterator SI = Pred->succ_begin(),
517                                             SE = Pred->succ_end();
518               SI != SE; ++SI)
519            if (!*SI)
520              ++SV;
521        }
522
523        if (++SV == Pred->succ_size())
524          // All paths from this block lead to the use and don't initialize the
525          // variable.
526          Queue.push_back(Pred);
527      }
528    }
529
530    // Scan the frontier, looking for blocks where the variable was
531    // uninitialized.
532    for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) {
533      const CFGBlock *Block = *BI;
534      unsigned BlockID = Block->getBlockID();
535      const Stmt *Term = Block->getTerminator();
536      if (SuccsVisited[BlockID] && SuccsVisited[BlockID] < Block->succ_size() &&
537          Term) {
538        // This block inevitably leads to the use. If we have an edge from here
539        // to a post-dominator block, and the variable is uninitialized on that
540        // edge, we have found a bug.
541        for (CFGBlock::const_succ_iterator I = Block->succ_begin(),
542             E = Block->succ_end(); I != E; ++I) {
543          const CFGBlock *Succ = *I;
544          if (Succ && SuccsVisited[Succ->getBlockID()] >= Succ->succ_size() &&
545              vals.getValue(Block, Succ, vd) == Uninitialized) {
546            // Switch cases are a special case: report the label to the caller
547            // as the 'terminator', not the switch statement itself. Suppress
548            // situations where no label matched: we can't be sure that's
549            // possible.
550            if (isa<SwitchStmt>(Term)) {
551              const Stmt *Label = Succ->getLabel();
552              if (!Label || !isa<SwitchCase>(Label))
553                // Might not be possible.
554                continue;
555              UninitUse::Branch Branch;
556              Branch.Terminator = Label;
557              Branch.Output = 0; // Ignored.
558              Use.addUninitBranch(Branch);
559            } else {
560              UninitUse::Branch Branch;
561              Branch.Terminator = Term;
562              Branch.Output = I - Block->succ_begin();
563              Use.addUninitBranch(Branch);
564            }
565          }
566        }
567      }
568    }
569
570    return Use;
571  }
572};
573}
574
575void TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd) {
576  if (!handler)
577    return;
578  Value v = vals[vd];
579  if (isUninitialized(v))
580    handler->handleUseOfUninitVariable(vd, getUninitUse(ex, vd, v));
581}
582
583void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS) {
584  // This represents an initialization of the 'element' value.
585  if (DeclStmt *DS = dyn_cast<DeclStmt>(FS->getElement())) {
586    const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
587    if (isTrackedVar(VD))
588      vals[VD] = Initialized;
589  }
590}
591
592void TransferFunctions::VisitBlockExpr(BlockExpr *be) {
593  const BlockDecl *bd = be->getBlockDecl();
594  for (BlockDecl::capture_const_iterator i = bd->capture_begin(),
595        e = bd->capture_end() ; i != e; ++i) {
596    const VarDecl *vd = i->getVariable();
597    if (!isTrackedVar(vd))
598      continue;
599    if (i->isByRef()) {
600      vals[vd] = Initialized;
601      continue;
602    }
603    reportUse(be, vd);
604  }
605}
606
607void TransferFunctions::VisitCallExpr(CallExpr *ce) {
608  // After a call to a function like setjmp or vfork, any variable which is
609  // initialized anywhere within this function may now be initialized. For now,
610  // just assume such a call initializes all variables.
611  // FIXME: Only mark variables as initialized if they have an initializer which
612  // is reachable from here.
613  Decl *Callee = ce->getCalleeDecl();
614  if (Callee && Callee->hasAttr<ReturnsTwiceAttr>())
615    vals.setAllScratchValues(Initialized);
616}
617
618void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) {
619  switch (classification.get(dr)) {
620  case ClassifyRefs::Ignore:
621    break;
622  case ClassifyRefs::Use:
623    reportUse(dr, cast<VarDecl>(dr->getDecl()));
624    break;
625  case ClassifyRefs::Init:
626    vals[cast<VarDecl>(dr->getDecl())] = Initialized;
627    break;
628  case ClassifyRefs::SelfInit:
629    if (handler)
630      handler->handleSelfInit(cast<VarDecl>(dr->getDecl()));
631    break;
632  }
633}
634
635void TransferFunctions::VisitBinaryOperator(BinaryOperator *BO) {
636  if (BO->getOpcode() == BO_Assign) {
637    FindVarResult Var = findVar(BO->getLHS());
638    if (const VarDecl *VD = Var.getDecl())
639      vals[VD] = Initialized;
640  }
641}
642
643void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
644  for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
645       DI != DE; ++DI) {
646    VarDecl *VD = dyn_cast<VarDecl>(*DI);
647    if (VD && isTrackedVar(VD)) {
648      if (getSelfInitExpr(VD)) {
649        // If the initializer consists solely of a reference to itself, we
650        // explicitly mark the variable as uninitialized. This allows code
651        // like the following:
652        //
653        //   int x = x;
654        //
655        // to deliberately leave a variable uninitialized. Different analysis
656        // clients can detect this pattern and adjust their reporting
657        // appropriately, but we need to continue to analyze subsequent uses
658        // of the variable.
659        vals[VD] = Uninitialized;
660      } else if (VD->getInit()) {
661        // Treat the new variable as initialized.
662        vals[VD] = Initialized;
663      } else {
664        // No initializer: the variable is now uninitialized. This matters
665        // for cases like:
666        //   while (...) {
667        //     int n;
668        //     use(n);
669        //     n = 0;
670        //   }
671        // FIXME: Mark the variable as uninitialized whenever its scope is
672        // left, since its scope could be re-entered by a jump over the
673        // declaration.
674        vals[VD] = Uninitialized;
675      }
676    }
677  }
678}
679
680//------------------------------------------------------------------------====//
681// High-level "driver" logic for uninitialized values analysis.
682//====------------------------------------------------------------------------//
683
684static bool runOnBlock(const CFGBlock *block, const CFG &cfg,
685                       AnalysisDeclContext &ac, CFGBlockValues &vals,
686                       const ClassifyRefs &classification,
687                       llvm::BitVector &wasAnalyzed,
688                       UninitVariablesHandler *handler = 0) {
689  wasAnalyzed[block->getBlockID()] = true;
690  vals.resetScratch();
691  // Merge in values of predecessor blocks.
692  bool isFirst = true;
693  for (CFGBlock::const_pred_iterator I = block->pred_begin(),
694       E = block->pred_end(); I != E; ++I) {
695    const CFGBlock *pred = *I;
696    if (wasAnalyzed[pred->getBlockID()]) {
697      vals.mergeIntoScratch(vals.getValueVector(pred), isFirst);
698      isFirst = false;
699    }
700  }
701  // Apply the transfer function.
702  TransferFunctions tf(vals, cfg, block, ac, classification, handler);
703  for (CFGBlock::const_iterator I = block->begin(), E = block->end();
704       I != E; ++I) {
705    if (const CFGStmt *cs = dyn_cast<CFGStmt>(&*I)) {
706      tf.Visit(const_cast<Stmt*>(cs->getStmt()));
707    }
708  }
709  return vals.updateValueVectorWithScratch(block);
710}
711
712void clang::runUninitializedVariablesAnalysis(
713    const DeclContext &dc,
714    const CFG &cfg,
715    AnalysisDeclContext &ac,
716    UninitVariablesHandler &handler,
717    UninitVariablesAnalysisStats &stats) {
718  CFGBlockValues vals(cfg);
719  vals.computeSetOfDeclarations(dc);
720  if (vals.hasNoDeclarations())
721    return;
722
723  stats.NumVariablesAnalyzed = vals.getNumEntries();
724
725  // Precompute which expressions are uses and which are initializations.
726  ClassifyRefs classification(ac);
727  cfg.VisitBlockStmts(classification);
728
729  // Mark all variables uninitialized at the entry.
730  const CFGBlock &entry = cfg.getEntry();
731  ValueVector &vec = vals.getValueVector(&entry);
732  const unsigned n = vals.getNumEntries();
733  for (unsigned j = 0; j < n ; ++j) {
734    vec[j] = Uninitialized;
735  }
736
737  // Proceed with the workist.
738  DataflowWorklist worklist(cfg);
739  llvm::BitVector previouslyVisited(cfg.getNumBlockIDs());
740  worklist.enqueueSuccessors(&cfg.getEntry());
741  llvm::BitVector wasAnalyzed(cfg.getNumBlockIDs(), false);
742  wasAnalyzed[cfg.getEntry().getBlockID()] = true;
743
744  while (const CFGBlock *block = worklist.dequeue()) {
745    // Did the block change?
746    bool changed = runOnBlock(block, cfg, ac, vals,
747                              classification, wasAnalyzed);
748    ++stats.NumBlockVisits;
749    if (changed || !previouslyVisited[block->getBlockID()])
750      worklist.enqueueSuccessors(block);
751    previouslyVisited[block->getBlockID()] = true;
752  }
753
754  // Run through the blocks one more time, and report uninitialized variabes.
755  for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) {
756    const CFGBlock *block = *BI;
757    if (wasAnalyzed[block->getBlockID()]) {
758      runOnBlock(block, cfg, ac, vals, classification, wasAnalyzed, &handler);
759      ++stats.NumBlockVisits;
760    }
761  }
762}
763
764UninitVariablesHandler::~UninitVariablesHandler() {}
765