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